Move to `IdentifiedArray` in `PagingLibraryViewModel` (#1346)
* init * update packages, cleanup
This commit is contained in:
parent
0797fb5fee
commit
e856303181
|
@ -1086,10 +1086,10 @@ internal enum L10n {
|
||||||
internal static let run = L10n.tr("Localizable", "run", fallback: "Run")
|
internal static let run = L10n.tr("Localizable", "run", fallback: "Run")
|
||||||
/// Running...
|
/// Running...
|
||||||
internal static let running = L10n.tr("Localizable", "running", fallback: "Running...")
|
internal static let running = L10n.tr("Localizable", "running", fallback: "Running...")
|
||||||
/// Runtime
|
|
||||||
internal static let runtime = L10n.tr("Localizable", "runtime", fallback: "Runtime")
|
|
||||||
/// Run Time
|
/// Run Time
|
||||||
internal static let runTime = L10n.tr("Localizable", "runTime", fallback: "Run Time")
|
internal static let runTime = L10n.tr("Localizable", "runTime", fallback: "Run Time")
|
||||||
|
/// Runtime
|
||||||
|
internal static let runtime = L10n.tr("Localizable", "runtime", fallback: "Runtime")
|
||||||
/// Save
|
/// Save
|
||||||
internal static let save = L10n.tr("Localizable", "save", fallback: "Save")
|
internal static let save = L10n.tr("Localizable", "save", fallback: "Save")
|
||||||
/// Scan All Libraries
|
/// Scan All Libraries
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Combine
|
||||||
import Defaults
|
import Defaults
|
||||||
import Foundation
|
import Foundation
|
||||||
import Get
|
import Get
|
||||||
|
import IdentifiedCollections
|
||||||
import JellyfinAPI
|
import JellyfinAPI
|
||||||
import OrderedCollections
|
import OrderedCollections
|
||||||
import UIKit
|
import UIKit
|
||||||
|
@ -32,7 +33,7 @@ private let DefaultPageSize = 50
|
||||||
on remembering other filters.
|
on remembering other filters.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
|
class PagingLibraryViewModel<Element: Poster & Identifiable>: ViewModel, Eventful, Stateful {
|
||||||
|
|
||||||
// MARK: Event
|
// MARK: Event
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
|
||||||
@Published
|
@Published
|
||||||
final var backgroundStates: OrderedSet<BackgroundState> = []
|
final var backgroundStates: OrderedSet<BackgroundState> = []
|
||||||
@Published
|
@Published
|
||||||
final var elements: OrderedSet<Element>
|
final var elements: IdentifiedArrayOf<Element>
|
||||||
@Published
|
@Published
|
||||||
final var state: State = .initial
|
final var state: State = .initial
|
||||||
@Published
|
@Published
|
||||||
|
@ -103,7 +104,7 @@ class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
|
||||||
parent: (any LibraryParent)? = nil
|
parent: (any LibraryParent)? = nil
|
||||||
) {
|
) {
|
||||||
self.filterViewModel = nil
|
self.filterViewModel = nil
|
||||||
self.elements = OrderedSet(data)
|
self.elements = IdentifiedArray(uniqueElements: data)
|
||||||
self.isStatic = true
|
self.isStatic = true
|
||||||
self.hasNextPage = false
|
self.hasNextPage = false
|
||||||
self.pageSize = DefaultPageSize
|
self.pageSize = DefaultPageSize
|
||||||
|
@ -130,7 +131,7 @@ class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
|
||||||
filters: ItemFilterCollection? = nil,
|
filters: ItemFilterCollection? = nil,
|
||||||
pageSize: Int = DefaultPageSize
|
pageSize: Int = DefaultPageSize
|
||||||
) {
|
) {
|
||||||
self.elements = OrderedSet()
|
self.elements = IdentifiedArray()
|
||||||
self.isStatic = false
|
self.isStatic = false
|
||||||
self.pageSize = pageSize
|
self.pageSize = pageSize
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
|
@ -11,7 +11,8 @@ import JellyfinAPI
|
||||||
|
|
||||||
extension MediaViewModel {
|
extension MediaViewModel {
|
||||||
|
|
||||||
enum MediaType: Displayable, Hashable {
|
enum MediaType: Displayable, Hashable, Identifiable {
|
||||||
|
|
||||||
case collectionFolder(BaseItemDto)
|
case collectionFolder(BaseItemDto)
|
||||||
case downloads
|
case downloads
|
||||||
case favorites
|
case favorites
|
||||||
|
@ -29,5 +30,18 @@ extension MediaViewModel {
|
||||||
return L10n.liveTV
|
return L10n.liveTV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var id: String? {
|
||||||
|
switch self {
|
||||||
|
case let .collectionFolder(item):
|
||||||
|
return item.id
|
||||||
|
case .downloads:
|
||||||
|
return "downloads"
|
||||||
|
case .favorites:
|
||||||
|
return "favorites"
|
||||||
|
case let .liveTV(item):
|
||||||
|
return item.id
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,19 +12,19 @@ import SwiftUI
|
||||||
|
|
||||||
// TODO: trailing content refactor?
|
// TODO: trailing content refactor?
|
||||||
|
|
||||||
struct PosterHStack<Item: Poster>: View {
|
struct PosterHStack<Element: Poster & Identifiable, Data: Collection>: View where Data.Element == Element, Data.Index == Int {
|
||||||
|
|
||||||
|
private var data: Data
|
||||||
private var title: String?
|
private var title: String?
|
||||||
private var type: PosterDisplayType
|
private var type: PosterDisplayType
|
||||||
private var items: Binding<OrderedSet<Item>>
|
private var content: (Element) -> any View
|
||||||
private var content: (Item) -> any View
|
private var imageOverlay: (Element) -> any View
|
||||||
private var imageOverlay: (Item) -> any View
|
private var contextMenu: (Element) -> any View
|
||||||
private var contextMenu: (Item) -> any View
|
|
||||||
private var trailingContent: () -> any View
|
private var trailingContent: () -> any View
|
||||||
private var onSelect: (Item) -> Void
|
private var onSelect: (Element) -> Void
|
||||||
|
|
||||||
// See PosterButton for implementation reason
|
// See PosterButton for implementation reason
|
||||||
private var focusedItem: Binding<Item?>?
|
private var focusedItem: Binding<Element?>?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 20) {
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
|
@ -42,7 +42,7 @@ struct PosterHStack<Item: Poster>: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
items,
|
uniqueElements: data,
|
||||||
columns: type == .landscape ? 4 : 7
|
columns: type == .landscape ? 4 : 7
|
||||||
) { item in
|
) { item in
|
||||||
PosterButton(item: item, type: type)
|
PosterButton(item: item, type: type)
|
||||||
|
@ -86,42 +86,29 @@ extension PosterHStack {
|
||||||
init(
|
init(
|
||||||
title: String? = nil,
|
title: String? = nil,
|
||||||
type: PosterDisplayType,
|
type: PosterDisplayType,
|
||||||
items: Binding<OrderedSet<Item>>
|
items: Data
|
||||||
) {
|
) {
|
||||||
self.init(
|
self.init(
|
||||||
|
data: items,
|
||||||
title: title,
|
title: title,
|
||||||
type: type,
|
type: type,
|
||||||
items: items,
|
|
||||||
content: { PosterButton.TitleSubtitleContentView(item: $0) },
|
content: { PosterButton.TitleSubtitleContentView(item: $0) },
|
||||||
imageOverlay: { PosterButton.DefaultOverlay(item: $0) },
|
imageOverlay: { PosterButton.DefaultOverlay(item: $0) },
|
||||||
contextMenu: { _ in EmptyView() },
|
contextMenu: { _ in EmptyView() },
|
||||||
trailingContent: { EmptyView() },
|
trailingContent: { EmptyView() },
|
||||||
onSelect: { _ in },
|
onSelect: { _ in }
|
||||||
focusedItem: nil
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
init<S: Sequence<Item>>(
|
func content(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
|
||||||
title: String? = nil,
|
|
||||||
type: PosterDisplayType,
|
|
||||||
items: S
|
|
||||||
) {
|
|
||||||
self.init(
|
|
||||||
title: title,
|
|
||||||
type: type,
|
|
||||||
items: .constant(OrderedSet(items))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func content(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
|
|
||||||
copy(modifying: \.content, with: content)
|
copy(modifying: \.content, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageOverlay(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
|
func imageOverlay(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
|
||||||
copy(modifying: \.imageOverlay, with: content)
|
copy(modifying: \.imageOverlay, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func contextMenu(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
|
func contextMenu(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
|
||||||
copy(modifying: \.contextMenu, with: content)
|
copy(modifying: \.contextMenu, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,11 +116,11 @@ extension PosterHStack {
|
||||||
copy(modifying: \.trailingContent, with: content)
|
copy(modifying: \.trailingContent, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSelect(_ action: @escaping (Item) -> Void) -> Self {
|
func onSelect(_ action: @escaping (Element) -> Void) -> Self {
|
||||||
copy(modifying: \.onSelect, with: action)
|
copy(modifying: \.onSelect, with: action)
|
||||||
}
|
}
|
||||||
|
|
||||||
func focusedItem(_ binding: Binding<Item?>) -> Self {
|
func focusedItem(_ binding: Binding<Element?>) -> Self {
|
||||||
copy(modifying: \.focusedItem, with: binding)
|
copy(modifying: \.focusedItem, with: binding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct ChannelLibraryView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var contentView: some View {
|
private var contentView: some View {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
$viewModel.elements,
|
uniqueElements: viewModel.elements,
|
||||||
layout: .columns(3, insets: .init(0), itemSpacing: 25, lineSpacing: 25)
|
layout: .columns(3, insets: .init(0), itemSpacing: 25, lineSpacing: 25)
|
||||||
) { channel in
|
) { channel in
|
||||||
WideChannelGridItem(channel: channel)
|
WideChannelGridItem(channel: channel)
|
||||||
|
|
|
@ -24,7 +24,7 @@ extension HomeView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.latestWithString(viewModel.parent?.displayTitle ?? .emptyDash),
|
title: L10n.latestWithString(viewModel.parent?.displayTitle ?? .emptyDash),
|
||||||
type: .portrait,
|
type: .portrait,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.onSelect { item in
|
.onSelect { item in
|
||||||
router.route(to: \.item, item)
|
router.route(to: \.item, item)
|
||||||
|
|
|
@ -27,7 +27,7 @@ extension HomeView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.nextUp,
|
title: L10n.nextUp,
|
||||||
type: nextUpPosterType,
|
type: nextUpPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.onSelect { item in
|
.onSelect { item in
|
||||||
router.route(to: \.item, item)
|
router.route(to: \.item, item)
|
||||||
|
|
|
@ -27,7 +27,7 @@ extension HomeView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.recentlyAdded,
|
title: L10n.recentlyAdded,
|
||||||
type: recentlyAddedPosterType,
|
type: recentlyAddedPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.onSelect { item in
|
.onSelect { item in
|
||||||
router.route(to: \.item, item)
|
router.route(to: \.item, item)
|
||||||
|
|
|
@ -30,13 +30,13 @@ extension SeriesEpisodeSelector {
|
||||||
private var lastFocusedEpisodeID: String?
|
private var lastFocusedEpisodeID: String?
|
||||||
|
|
||||||
@StateObject
|
@StateObject
|
||||||
private var proxy = CollectionHStackProxy<BaseItemDto>()
|
private var proxy = CollectionHStackProxy()
|
||||||
|
|
||||||
let playButtonItem: BaseItemDto?
|
let playButtonItem: BaseItemDto?
|
||||||
|
|
||||||
private func contentView(viewModel: SeasonItemViewModel) -> some View {
|
private func contentView(viewModel: SeasonItemViewModel) -> some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
$viewModel.elements,
|
uniqueElements: viewModel.elements,
|
||||||
columns: 3.5
|
columns: 3.5
|
||||||
) { episode in
|
) { episode in
|
||||||
SeriesEpisodeSelector.EpisodeCard(episode: episode)
|
SeriesEpisodeSelector.EpisodeCard(episode: episode)
|
||||||
|
@ -103,7 +103,7 @@ extension SeriesEpisodeSelector {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
0 ..< 1,
|
count: 1,
|
||||||
columns: 3.5
|
columns: 3.5
|
||||||
) { _ in
|
) { _ in
|
||||||
SeriesEpisodeSelector.ErrorCard(error: error)
|
SeriesEpisodeSelector.ErrorCard(error: error)
|
||||||
|
@ -121,7 +121,7 @@ extension SeriesEpisodeSelector {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
0 ..< Int.random(in: 2 ..< 5),
|
count: Int.random(in: 2 ..< 5),
|
||||||
columns: 3.5
|
columns: 3.5
|
||||||
) { _ in
|
) { _ in
|
||||||
SeriesEpisodeSelector.LoadingCard()
|
SeriesEpisodeSelector.LoadingCard()
|
||||||
|
|
|
@ -31,7 +31,7 @@ extension ItemView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.recommended,
|
title: L10n.recommended,
|
||||||
type: similarPosterType,
|
type: similarPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.onSelect { item in
|
.onSelect { item in
|
||||||
router.route(to: \.item, item)
|
router.route(to: \.item, item)
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct MediaView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var contentView: some View {
|
private var contentView: some View {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
$viewModel.mediaItems,
|
uniqueElements: viewModel.mediaItems,
|
||||||
layout: .columns(4, insets: .init(50), itemSpacing: 50, lineSpacing: 50)
|
layout: .columns(4, insets: .init(50), itemSpacing: 50, lineSpacing: 50)
|
||||||
) { mediaType in
|
) { mediaType in
|
||||||
MediaItem(viewModel: viewModel, type: mediaType)
|
MediaItem(viewModel: viewModel, type: mediaType)
|
||||||
|
|
|
@ -16,7 +16,7 @@ import SwiftUI
|
||||||
// TODO: list row view (LibraryRow)
|
// TODO: list row view (LibraryRow)
|
||||||
// TODO: fix paging for next item focusing the tab
|
// TODO: fix paging for next item focusing the tab
|
||||||
|
|
||||||
struct PagingLibraryView<Element: Poster>: View {
|
struct PagingLibraryView<Element: Poster & Identifiable>: View {
|
||||||
|
|
||||||
@Default(.Customization.Library.cinematicBackground)
|
@Default(.Customization.Library.cinematicBackground)
|
||||||
private var cinematicBackground
|
private var cinematicBackground
|
||||||
|
@ -159,7 +159,7 @@ struct PagingLibraryView<Element: Poster>: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var contentView: some View {
|
private var contentView: some View {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
$viewModel.elements,
|
uniqueElements: viewModel.elements,
|
||||||
layout: layout
|
layout: layout
|
||||||
) { item in
|
) { item in
|
||||||
switch (posterType, viewType) {
|
switch (posterType, viewType) {
|
||||||
|
|
|
@ -453,13 +453,12 @@
|
||||||
E1153D9C2BBA3E9D00424D36 /* LoadingCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153D9B2BBA3E9D00424D36 /* LoadingCard.swift */; };
|
E1153D9C2BBA3E9D00424D36 /* LoadingCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153D9B2BBA3E9D00424D36 /* LoadingCard.swift */; };
|
||||||
E1153DA42BBA614F00424D36 /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DA32BBA614F00424D36 /* CollectionVGrid */; };
|
E1153DA42BBA614F00424D36 /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DA32BBA614F00424D36 /* CollectionVGrid */; };
|
||||||
E1153DAC2BBA6AD200424D36 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DAB2BBA6AD200424D36 /* CollectionHStack */; };
|
E1153DAC2BBA6AD200424D36 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DAB2BBA6AD200424D36 /* CollectionHStack */; };
|
||||||
E1153DAF2BBA734200424D36 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DAE2BBA734200424D36 /* CollectionHStack */; };
|
|
||||||
E1153DB12BBA734C00424D36 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DB02BBA734C00424D36 /* CollectionHStack */; };
|
|
||||||
E1153DB42BBA80FB00424D36 /* EmptyCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153DB22BBA80B400424D36 /* EmptyCard.swift */; };
|
E1153DB42BBA80FB00424D36 /* EmptyCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153DB22BBA80B400424D36 /* EmptyCard.swift */; };
|
||||||
E1153DCC2BBB633B00424D36 /* FastSVGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153DCB2BBB633B00424D36 /* FastSVGView.swift */; };
|
E1153DCC2BBB633B00424D36 /* FastSVGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153DCB2BBB633B00424D36 /* FastSVGView.swift */; };
|
||||||
E1153DCD2BBB633B00424D36 /* FastSVGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153DCB2BBB633B00424D36 /* FastSVGView.swift */; };
|
E1153DCD2BBB633B00424D36 /* FastSVGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1153DCB2BBB633B00424D36 /* FastSVGView.swift */; };
|
||||||
E1153DD02BBB634F00424D36 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DCF2BBB634F00424D36 /* SVGKit */; };
|
E1153DD02BBB634F00424D36 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DCF2BBB634F00424D36 /* SVGKit */; };
|
||||||
E1153DD22BBB649C00424D36 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DD12BBB649C00424D36 /* SVGKit */; };
|
E1153DD22BBB649C00424D36 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = E1153DD12BBB649C00424D36 /* SVGKit */; };
|
||||||
|
E1155ACB2D0584A90021557A /* IdentifiedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = E1155ACA2D0584A90021557A /* IdentifiedCollections */; };
|
||||||
E11562952C818CB2001D5DE4 /* BindingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11562942C818CB2001D5DE4 /* BindingBox.swift */; };
|
E11562952C818CB2001D5DE4 /* BindingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11562942C818CB2001D5DE4 /* BindingBox.swift */; };
|
||||||
E11562962C818CB2001D5DE4 /* BindingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11562942C818CB2001D5DE4 /* BindingBox.swift */; };
|
E11562962C818CB2001D5DE4 /* BindingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11562942C818CB2001D5DE4 /* BindingBox.swift */; };
|
||||||
E118959D289312020042947B /* BaseItemPerson+Poster.swift in Sources */ = {isa = PBXBuildFile; fileRef = E118959C289312020042947B /* BaseItemPerson+Poster.swift */; };
|
E118959D289312020042947B /* BaseItemPerson+Poster.swift in Sources */ = {isa = PBXBuildFile; fileRef = E118959C289312020042947B /* BaseItemPerson+Poster.swift */; };
|
||||||
|
@ -525,8 +524,6 @@
|
||||||
E12E30F5296392EC0022FAC9 /* EnumPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12E30F4296392EC0022FAC9 /* EnumPickerView.swift */; };
|
E12E30F5296392EC0022FAC9 /* EnumPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12E30F4296392EC0022FAC9 /* EnumPickerView.swift */; };
|
||||||
E12F038C28F8B0B100976CC3 /* EdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12F038B28F8B0B100976CC3 /* EdgeInsets.swift */; };
|
E12F038C28F8B0B100976CC3 /* EdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12F038B28F8B0B100976CC3 /* EdgeInsets.swift */; };
|
||||||
E132D3C82BD200C10058A2DF /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E132D3C72BD200C10058A2DF /* CollectionVGrid */; };
|
E132D3C82BD200C10058A2DF /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E132D3C72BD200C10058A2DF /* CollectionVGrid */; };
|
||||||
E132D3CD2BD2179C0058A2DF /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E132D3CC2BD2179C0058A2DF /* CollectionVGrid */; };
|
|
||||||
E132D3CF2BD217AA0058A2DF /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E132D3CE2BD217AA0058A2DF /* CollectionVGrid */; };
|
|
||||||
E13316FE2ADE42B6009BF865 /* OnSizeChangedModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13316FD2ADE42B6009BF865 /* OnSizeChangedModifier.swift */; };
|
E13316FE2ADE42B6009BF865 /* OnSizeChangedModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13316FD2ADE42B6009BF865 /* OnSizeChangedModifier.swift */; };
|
||||||
E13316FF2ADE42B6009BF865 /* OnSizeChangedModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13316FD2ADE42B6009BF865 /* OnSizeChangedModifier.swift */; };
|
E13316FF2ADE42B6009BF865 /* OnSizeChangedModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13316FD2ADE42B6009BF865 /* OnSizeChangedModifier.swift */; };
|
||||||
E133328829538D8D00EE76AB /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = E133328729538D8D00EE76AB /* Files.swift */; };
|
E133328829538D8D00EE76AB /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = E133328729538D8D00EE76AB /* Files.swift */; };
|
||||||
|
@ -749,6 +746,10 @@
|
||||||
E1763A722BF3F67C004DF6AB /* SwiftfinStore+Mappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1763A702BF3F67C004DF6AB /* SwiftfinStore+Mappings.swift */; };
|
E1763A722BF3F67C004DF6AB /* SwiftfinStore+Mappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1763A702BF3F67C004DF6AB /* SwiftfinStore+Mappings.swift */; };
|
||||||
E1763A742BF3FA4C004DF6AB /* AppLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1763A732BF3FA4C004DF6AB /* AppLoadingView.swift */; };
|
E1763A742BF3FA4C004DF6AB /* AppLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1763A732BF3FA4C004DF6AB /* AppLoadingView.swift */; };
|
||||||
E1763A762BF3FF01004DF6AB /* AppLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1763A752BF3FF01004DF6AB /* AppLoadingView.swift */; };
|
E1763A762BF3FF01004DF6AB /* AppLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1763A752BF3FF01004DF6AB /* AppLoadingView.swift */; };
|
||||||
|
E176EBDE2D050067009F4CF1 /* IdentifiedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = E176EBDD2D050067009F4CF1 /* IdentifiedCollections */; };
|
||||||
|
E176EBE02D0502A6009F4CF1 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E176EBDF2D0502A6009F4CF1 /* CollectionHStack */; };
|
||||||
|
E176EBE32D0502C6009F4CF1 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E176EBE22D0502C6009F4CF1 /* CollectionHStack */; };
|
||||||
|
E176EBE92D050925009F4CF1 /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E176EBE82D050925009F4CF1 /* CollectionVGrid */; };
|
||||||
E178859B2780F1F40094FBCF /* tvOSSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E178859A2780F1F40094FBCF /* tvOSSlider.swift */; };
|
E178859B2780F1F40094FBCF /* tvOSSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E178859A2780F1F40094FBCF /* tvOSSlider.swift */; };
|
||||||
E178859E2780F53B0094FBCF /* SliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E178859D2780F53B0094FBCF /* SliderView.swift */; };
|
E178859E2780F53B0094FBCF /* SliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E178859D2780F53B0094FBCF /* SliderView.swift */; };
|
||||||
E17885A4278105170094FBCF /* SFSymbolButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E17885A3278105170094FBCF /* SFSymbolButton.swift */; };
|
E17885A4278105170094FBCF /* SFSymbolButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E17885A3278105170094FBCF /* SFSymbolButton.swift */; };
|
||||||
|
@ -878,6 +879,10 @@
|
||||||
E19E6E0728A0B958005C10C8 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = E19E6E0628A0B958005C10C8 /* NukeUI */; };
|
E19E6E0728A0B958005C10C8 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = E19E6E0628A0B958005C10C8 /* NukeUI */; };
|
||||||
E19E6E0A28A0BEFF005C10C8 /* BlurHashKit in Frameworks */ = {isa = PBXBuildFile; productRef = E19E6E0928A0BEFF005C10C8 /* BlurHashKit */; };
|
E19E6E0A28A0BEFF005C10C8 /* BlurHashKit in Frameworks */ = {isa = PBXBuildFile; productRef = E19E6E0928A0BEFF005C10C8 /* BlurHashKit */; };
|
||||||
E19F6C5D28F5189300C5197E /* MediaStreamInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19F6C5C28F5189300C5197E /* MediaStreamInfoView.swift */; };
|
E19F6C5D28F5189300C5197E /* MediaStreamInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19F6C5C28F5189300C5197E /* MediaStreamInfoView.swift */; };
|
||||||
|
E1A09F722D05933D00835265 /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E1A09F712D05933D00835265 /* CollectionVGrid */; };
|
||||||
|
E1A09F752D05935100835265 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E1A09F742D05935100835265 /* CollectionHStack */; };
|
||||||
|
E1A09F772D05935A00835265 /* CollectionVGrid in Frameworks */ = {isa = PBXBuildFile; productRef = E1A09F762D05935A00835265 /* CollectionVGrid */; };
|
||||||
|
E1A09F792D05935A00835265 /* CollectionHStack in Frameworks */ = {isa = PBXBuildFile; productRef = E1A09F782D05935A00835265 /* CollectionHStack */; };
|
||||||
E1A1528228FD126C00600579 /* VerticalAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528128FD126C00600579 /* VerticalAlignment.swift */; };
|
E1A1528228FD126C00600579 /* VerticalAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528128FD126C00600579 /* VerticalAlignment.swift */; };
|
||||||
E1A1528528FD191A00600579 /* TextPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528428FD191A00600579 /* TextPair.swift */; };
|
E1A1528528FD191A00600579 /* TextPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528428FD191A00600579 /* TextPair.swift */; };
|
||||||
E1A1528828FD229500600579 /* ChevronButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528728FD229500600579 /* ChevronButton.swift */; };
|
E1A1528828FD229500600579 /* ChevronButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A1528728FD229500600579 /* ChevronButton.swift */; };
|
||||||
|
@ -1934,6 +1939,7 @@
|
||||||
E13AF3B828A0C598009093AB /* NukeExtensions in Frameworks */,
|
E13AF3B828A0C598009093AB /* NukeExtensions in Frameworks */,
|
||||||
E1575E58293E7685001665B1 /* Files in Frameworks */,
|
E1575E58293E7685001665B1 /* Files in Frameworks */,
|
||||||
E1B5F7A729577BCE004B26CF /* Pulse in Frameworks */,
|
E1B5F7A729577BCE004B26CF /* Pulse in Frameworks */,
|
||||||
|
E1A09F792D05935A00835265 /* CollectionHStack in Frameworks */,
|
||||||
E13AF3BA28A0C598009093AB /* NukeUI in Frameworks */,
|
E13AF3BA28A0C598009093AB /* NukeUI in Frameworks */,
|
||||||
E1B5F7AB29577BCE004B26CF /* PulseUI in Frameworks */,
|
E1B5F7AB29577BCE004B26CF /* PulseUI in Frameworks */,
|
||||||
E1B5F7A929577BCE004B26CF /* PulseLogHandler in Frameworks */,
|
E1B5F7A929577BCE004B26CF /* PulseLogHandler in Frameworks */,
|
||||||
|
@ -1943,18 +1949,18 @@
|
||||||
62666E1927E501D000EC0ECD /* CoreFoundation.framework in Frameworks */,
|
62666E1927E501D000EC0ECD /* CoreFoundation.framework in Frameworks */,
|
||||||
E19D41B22BF2BFA50082B8B2 /* KeychainSwift in Frameworks */,
|
E19D41B22BF2BFA50082B8B2 /* KeychainSwift in Frameworks */,
|
||||||
E18443CB2A037773002DDDC8 /* UDPBroadcast in Frameworks */,
|
E18443CB2A037773002DDDC8 /* UDPBroadcast in Frameworks */,
|
||||||
|
E1155ACB2D0584A90021557A /* IdentifiedCollections in Frameworks */,
|
||||||
62666E2E27E5021400EC0ECD /* Security.framework in Frameworks */,
|
62666E2E27E5021400EC0ECD /* Security.framework in Frameworks */,
|
||||||
E1B5F7AD29577BDD004B26CF /* OrderedCollections in Frameworks */,
|
E1B5F7AD29577BDD004B26CF /* OrderedCollections in Frameworks */,
|
||||||
53ABFDDC267972BF00886593 /* TVServices.framework in Frameworks */,
|
53ABFDDC267972BF00886593 /* TVServices.framework in Frameworks */,
|
||||||
62666E1F27E501DF00EC0ECD /* CoreText.framework in Frameworks */,
|
62666E1F27E501DF00EC0ECD /* CoreText.framework in Frameworks */,
|
||||||
E13DD3CD27164CA7009D4DAF /* CoreStore in Frameworks */,
|
E13DD3CD27164CA7009D4DAF /* CoreStore in Frameworks */,
|
||||||
E1A7B1652B9A9F7800152546 /* PreferencesView in Frameworks */,
|
E1A7B1652B9A9F7800152546 /* PreferencesView in Frameworks */,
|
||||||
|
E1A09F772D05935A00835265 /* CollectionVGrid in Frameworks */,
|
||||||
E1153DD22BBB649C00424D36 /* SVGKit in Frameworks */,
|
E1153DD22BBB649C00424D36 /* SVGKit in Frameworks */,
|
||||||
62666E1527E501C800EC0ECD /* AVFoundation.framework in Frameworks */,
|
62666E1527E501C800EC0ECD /* AVFoundation.framework in Frameworks */,
|
||||||
E132D3CF2BD217AA0058A2DF /* CollectionVGrid in Frameworks */,
|
|
||||||
E13AF3BC28A0C59E009093AB /* BlurHashKit in Frameworks */,
|
E13AF3BC28A0C59E009093AB /* BlurHashKit in Frameworks */,
|
||||||
E150C0C32BFD6DA200944FFA /* JellyfinAPI in Frameworks */,
|
E150C0C32BFD6DA200944FFA /* JellyfinAPI in Frameworks */,
|
||||||
E1153DB12BBA734C00424D36 /* CollectionHStack in Frameworks */,
|
|
||||||
62666E1327E501C300EC0ECD /* AudioToolbox.framework in Frameworks */,
|
62666E1327E501C300EC0ECD /* AudioToolbox.framework in Frameworks */,
|
||||||
E13AF3B628A0C598009093AB /* Nuke in Frameworks */,
|
E13AF3B628A0C598009093AB /* Nuke in Frameworks */,
|
||||||
E12186DE2718F1C50010884C /* Defaults in Frameworks */,
|
E12186DE2718F1C50010884C /* Defaults in Frameworks */,
|
||||||
|
@ -1981,6 +1987,7 @@
|
||||||
62666E0627E5017A00EC0ECD /* CoreVideo.framework in Frameworks */,
|
62666E0627E5017A00EC0ECD /* CoreVideo.framework in Frameworks */,
|
||||||
E19DDEC72948EF9900954E10 /* OrderedCollections in Frameworks */,
|
E19DDEC72948EF9900954E10 /* OrderedCollections in Frameworks */,
|
||||||
E10706102942F57D00646DAF /* Pulse in Frameworks */,
|
E10706102942F57D00646DAF /* Pulse in Frameworks */,
|
||||||
|
E176EBE92D050925009F4CF1 /* CollectionVGrid in Frameworks */,
|
||||||
E192608328D2D0DB002314B4 /* Factory in Frameworks */,
|
E192608328D2D0DB002314B4 /* Factory in Frameworks */,
|
||||||
E150C0C12BFD62FD00944FFA /* JellyfinAPI in Frameworks */,
|
E150C0C12BFD62FD00944FFA /* JellyfinAPI in Frameworks */,
|
||||||
E113A2A72B5A178D009CAAAA /* CollectionHStack in Frameworks */,
|
E113A2A72B5A178D009CAAAA /* CollectionHStack in Frameworks */,
|
||||||
|
@ -1990,7 +1997,9 @@
|
||||||
62C29E9C26D0FE4200C1D2E7 /* Stinsen in Frameworks */,
|
62C29E9C26D0FE4200C1D2E7 /* Stinsen in Frameworks */,
|
||||||
62666E0227E5016D00EC0ECD /* CoreGraphics.framework in Frameworks */,
|
62666E0227E5016D00EC0ECD /* CoreGraphics.framework in Frameworks */,
|
||||||
E1575E3C293C6B15001665B1 /* Files in Frameworks */,
|
E1575E3C293C6B15001665B1 /* Files in Frameworks */,
|
||||||
|
E176EBE02D0502A6009F4CF1 /* CollectionHStack in Frameworks */,
|
||||||
E14EA1652BF70A8E00DE757A /* Mantis in Frameworks */,
|
E14EA1652BF70A8E00DE757A /* Mantis in Frameworks */,
|
||||||
|
E176EBDE2D050067009F4CF1 /* IdentifiedCollections in Frameworks */,
|
||||||
62666E1027E501B400EC0ECD /* VideoToolbox.framework in Frameworks */,
|
62666E1027E501B400EC0ECD /* VideoToolbox.framework in Frameworks */,
|
||||||
62666E0C27E501A500EC0ECD /* OpenGLES.framework in Frameworks */,
|
62666E0C27E501A500EC0ECD /* OpenGLES.framework in Frameworks */,
|
||||||
E19E6E0A28A0BEFF005C10C8 /* BlurHashKit in Frameworks */,
|
E19E6E0A28A0BEFF005C10C8 /* BlurHashKit in Frameworks */,
|
||||||
|
@ -2003,22 +2012,23 @@
|
||||||
E18A8E7A28D5FEDF00333B9A /* VLCUI in Frameworks */,
|
E18A8E7A28D5FEDF00333B9A /* VLCUI in Frameworks */,
|
||||||
E114DB332B1944FA00B75FB3 /* CollectionVGrid in Frameworks */,
|
E114DB332B1944FA00B75FB3 /* CollectionVGrid in Frameworks */,
|
||||||
E15210562946DF1B00375CC2 /* PulseLogHandler in Frameworks */,
|
E15210562946DF1B00375CC2 /* PulseLogHandler in Frameworks */,
|
||||||
E1153DAF2BBA734200424D36 /* CollectionHStack in Frameworks */,
|
|
||||||
62666E0427E5017500EC0ECD /* CoreText.framework in Frameworks */,
|
62666E0427E5017500EC0ECD /* CoreText.framework in Frameworks */,
|
||||||
E132D3CD2BD2179C0058A2DF /* CollectionVGrid in Frameworks */,
|
|
||||||
E13DD3C62716499E009D4DAF /* CoreStore in Frameworks */,
|
E13DD3C62716499E009D4DAF /* CoreStore in Frameworks */,
|
||||||
|
E176EBE32D0502C6009F4CF1 /* CollectionHStack in Frameworks */,
|
||||||
62666E0E27E501AF00EC0ECD /* Security.framework in Frameworks */,
|
62666E0E27E501AF00EC0ECD /* Security.framework in Frameworks */,
|
||||||
E1DC9814296DC06200982F06 /* PulseLogHandler in Frameworks */,
|
E1DC9814296DC06200982F06 /* PulseLogHandler in Frameworks */,
|
||||||
E15EFA842BA167350080E926 /* CollectionHStack in Frameworks */,
|
E15EFA842BA167350080E926 /* CollectionHStack in Frameworks */,
|
||||||
E15EFA862BA1685F0080E926 /* SwiftUIIntrospect in Frameworks */,
|
E15EFA862BA1685F0080E926 /* SwiftUIIntrospect in Frameworks */,
|
||||||
62666DFE27E5015700EC0ECD /* AVFoundation.framework in Frameworks */,
|
62666DFE27E5015700EC0ECD /* AVFoundation.framework in Frameworks */,
|
||||||
62666DFD27E5014F00EC0ECD /* AudioToolbox.framework in Frameworks */,
|
62666DFD27E5014F00EC0ECD /* AudioToolbox.framework in Frameworks */,
|
||||||
|
E1A09F722D05933D00835265 /* CollectionVGrid in Frameworks */,
|
||||||
E19E6E0528A0B958005C10C8 /* Nuke in Frameworks */,
|
E19E6E0528A0B958005C10C8 /* Nuke in Frameworks */,
|
||||||
E1153DAC2BBA6AD200424D36 /* CollectionHStack in Frameworks */,
|
E1153DAC2BBA6AD200424D36 /* CollectionHStack in Frameworks */,
|
||||||
62666E0D27E501AA00EC0ECD /* QuartzCore.framework in Frameworks */,
|
62666E0D27E501AA00EC0ECD /* QuartzCore.framework in Frameworks */,
|
||||||
E15D4F052B1B0C3C00442DB8 /* PreferencesView in Frameworks */,
|
E15D4F052B1B0C3C00442DB8 /* PreferencesView in Frameworks */,
|
||||||
E19E6E0728A0B958005C10C8 /* NukeUI in Frameworks */,
|
E19E6E0728A0B958005C10C8 /* NukeUI in Frameworks */,
|
||||||
62666E3F27E5040300EC0ECD /* SystemConfiguration.framework in Frameworks */,
|
62666E3F27E5040300EC0ECD /* SystemConfiguration.framework in Frameworks */,
|
||||||
|
E1A09F752D05935100835265 /* CollectionHStack in Frameworks */,
|
||||||
62666E3927E502CE00EC0ECD /* SwizzleSwift in Frameworks */,
|
62666E3927E502CE00EC0ECD /* SwizzleSwift in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -4611,11 +4621,12 @@
|
||||||
E18443CA2A037773002DDDC8 /* UDPBroadcast */,
|
E18443CA2A037773002DDDC8 /* UDPBroadcast */,
|
||||||
E1A7B1642B9A9F7800152546 /* PreferencesView */,
|
E1A7B1642B9A9F7800152546 /* PreferencesView */,
|
||||||
E1392FEC2BA218A80034110D /* SwiftUIIntrospect */,
|
E1392FEC2BA218A80034110D /* SwiftUIIntrospect */,
|
||||||
E1153DB02BBA734C00424D36 /* CollectionHStack */,
|
|
||||||
E1153DD12BBB649C00424D36 /* SVGKit */,
|
E1153DD12BBB649C00424D36 /* SVGKit */,
|
||||||
E132D3CE2BD217AA0058A2DF /* CollectionVGrid */,
|
|
||||||
E19D41B12BF2BFA50082B8B2 /* KeychainSwift */,
|
E19D41B12BF2BFA50082B8B2 /* KeychainSwift */,
|
||||||
E150C0C22BFD6DA200944FFA /* JellyfinAPI */,
|
E150C0C22BFD6DA200944FFA /* JellyfinAPI */,
|
||||||
|
E1155ACA2D0584A90021557A /* IdentifiedCollections */,
|
||||||
|
E1A09F762D05935A00835265 /* CollectionVGrid */,
|
||||||
|
E1A09F782D05935A00835265 /* CollectionHStack */,
|
||||||
);
|
);
|
||||||
productName = "JellyfinPlayer tvOS";
|
productName = "JellyfinPlayer tvOS";
|
||||||
productReference = 535870602669D21600D05A09 /* Swiftfin tvOS.app */;
|
productReference = 535870602669D21600D05A09 /* Swiftfin tvOS.app */;
|
||||||
|
@ -4665,13 +4676,17 @@
|
||||||
E18D6AA52BAA96F000A0D167 /* CollectionHStack */,
|
E18D6AA52BAA96F000A0D167 /* CollectionHStack */,
|
||||||
E1153DA32BBA614F00424D36 /* CollectionVGrid */,
|
E1153DA32BBA614F00424D36 /* CollectionVGrid */,
|
||||||
E1153DAB2BBA6AD200424D36 /* CollectionHStack */,
|
E1153DAB2BBA6AD200424D36 /* CollectionHStack */,
|
||||||
E1153DAE2BBA734200424D36 /* CollectionHStack */,
|
|
||||||
E1153DCF2BBB634F00424D36 /* SVGKit */,
|
E1153DCF2BBB634F00424D36 /* SVGKit */,
|
||||||
E132D3C72BD200C10058A2DF /* CollectionVGrid */,
|
E132D3C72BD200C10058A2DF /* CollectionVGrid */,
|
||||||
E132D3CC2BD2179C0058A2DF /* CollectionVGrid */,
|
|
||||||
E145EB4A2BE16849003BF6F3 /* KeychainSwift */,
|
E145EB4A2BE16849003BF6F3 /* KeychainSwift */,
|
||||||
E14EA1642BF70A8E00DE757A /* Mantis */,
|
E14EA1642BF70A8E00DE757A /* Mantis */,
|
||||||
E150C0C02BFD62FD00944FFA /* JellyfinAPI */,
|
E150C0C02BFD62FD00944FFA /* JellyfinAPI */,
|
||||||
|
E176EBDD2D050067009F4CF1 /* IdentifiedCollections */,
|
||||||
|
E176EBDF2D0502A6009F4CF1 /* CollectionHStack */,
|
||||||
|
E176EBE22D0502C6009F4CF1 /* CollectionHStack */,
|
||||||
|
E176EBE82D050925009F4CF1 /* CollectionVGrid */,
|
||||||
|
E1A09F712D05933D00835265 /* CollectionVGrid */,
|
||||||
|
E1A09F742D05935100835265 /* CollectionHStack */,
|
||||||
);
|
);
|
||||||
productName = JellyfinPlayer;
|
productName = JellyfinPlayer;
|
||||||
productReference = 5377CBF1263B596A003A4E83 /* Swiftfin iOS.app */;
|
productReference = 5377CBF1263B596A003A4E83 /* Swiftfin iOS.app */;
|
||||||
|
@ -4739,12 +4754,13 @@
|
||||||
E1DC9812296DC06200982F06 /* XCRemoteSwiftPackageReference "PulseLogHandler" */,
|
E1DC9812296DC06200982F06 /* XCRemoteSwiftPackageReference "PulseLogHandler" */,
|
||||||
E1FAD1C42A0375BA007F5521 /* XCRemoteSwiftPackageReference "UDPBroadcastConnection" */,
|
E1FAD1C42A0375BA007F5521 /* XCRemoteSwiftPackageReference "UDPBroadcastConnection" */,
|
||||||
E15D4F032B1B0C3C00442DB8 /* XCLocalSwiftPackageReference "PreferencesView" */,
|
E15D4F032B1B0C3C00442DB8 /* XCLocalSwiftPackageReference "PreferencesView" */,
|
||||||
E1153DAD2BBA734200424D36 /* XCRemoteSwiftPackageReference "CollectionHStack" */,
|
|
||||||
E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */,
|
E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */,
|
||||||
E132D3CB2BD2179C0058A2DF /* XCRemoteSwiftPackageReference "CollectionVGrid" */,
|
|
||||||
E145EB492BE16849003BF6F3 /* XCRemoteSwiftPackageReference "keychain-swift" */,
|
E145EB492BE16849003BF6F3 /* XCRemoteSwiftPackageReference "keychain-swift" */,
|
||||||
E14EA1632BF70A8E00DE757A /* XCRemoteSwiftPackageReference "Mantis" */,
|
E14EA1632BF70A8E00DE757A /* XCRemoteSwiftPackageReference "Mantis" */,
|
||||||
E150C0BF2BFD62FD00944FFA /* XCRemoteSwiftPackageReference "jellyfin-sdk-swift" */,
|
E150C0BF2BFD62FD00944FFA /* XCRemoteSwiftPackageReference "jellyfin-sdk-swift" */,
|
||||||
|
E176EBDC2D050067009F4CF1 /* XCRemoteSwiftPackageReference "swift-identified-collections" */,
|
||||||
|
E1A09F702D05933D00835265 /* XCRemoteSwiftPackageReference "CollectionVGrid" */,
|
||||||
|
E1A09F732D05935100835265 /* XCRemoteSwiftPackageReference "CollectionHStack" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 5377CBF2263B596A003A4E83 /* Products */;
|
productRefGroup = 5377CBF2263B596A003A4E83 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
@ -6359,14 +6375,6 @@
|
||||||
minimumVersion = 2.0.0;
|
minimumVersion = 2.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E1153DAD2BBA734200424D36 /* XCRemoteSwiftPackageReference "CollectionHStack" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/LePips/CollectionHStack";
|
|
||||||
requirement = {
|
|
||||||
branch = main;
|
|
||||||
kind = branch;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */ = {
|
E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/SVGKit/SVGKit";
|
repositoryURL = "https://github.com/SVGKit/SVGKit";
|
||||||
|
@ -6375,14 +6383,6 @@
|
||||||
minimumVersion = 3.0.0;
|
minimumVersion = 3.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E132D3CB2BD2179C0058A2DF /* XCRemoteSwiftPackageReference "CollectionVGrid" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/LePips/CollectionVGrid";
|
|
||||||
requirement = {
|
|
||||||
branch = main;
|
|
||||||
kind = branch;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */ = {
|
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/JohnEstropia/CoreStore.git";
|
repositoryURL = "https://github.com/JohnEstropia/CoreStore.git";
|
||||||
|
@ -6439,6 +6439,14 @@
|
||||||
minimumVersion = 4.0.0;
|
minimumVersion = 4.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
E176EBDC2D050067009F4CF1 /* XCRemoteSwiftPackageReference "swift-identified-collections" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/pointfreeco/swift-identified-collections";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 1.1.0;
|
||||||
|
};
|
||||||
|
};
|
||||||
E18A8E7828D5FEDF00333B9A /* XCRemoteSwiftPackageReference "VLCUI" */ = {
|
E18A8E7828D5FEDF00333B9A /* XCRemoteSwiftPackageReference "VLCUI" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/LePips/VLCUI";
|
repositoryURL = "https://github.com/LePips/VLCUI";
|
||||||
|
@ -6479,6 +6487,22 @@
|
||||||
minimumVersion = 1.0.0;
|
minimumVersion = 1.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
E1A09F702D05933D00835265 /* XCRemoteSwiftPackageReference "CollectionVGrid" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/LePips/CollectionVGrid";
|
||||||
|
requirement = {
|
||||||
|
branch = main;
|
||||||
|
kind = branch;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
E1A09F732D05935100835265 /* XCRemoteSwiftPackageReference "CollectionHStack" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/LePips/CollectionHStack";
|
||||||
|
requirement = {
|
||||||
|
branch = main;
|
||||||
|
kind = branch;
|
||||||
|
};
|
||||||
|
};
|
||||||
E1DC9812296DC06200982F06 /* XCRemoteSwiftPackageReference "PulseLogHandler" */ = {
|
E1DC9812296DC06200982F06 /* XCRemoteSwiftPackageReference "PulseLogHandler" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/kean/PulseLogHandler";
|
repositoryURL = "https://github.com/kean/PulseLogHandler";
|
||||||
|
@ -6558,16 +6582,6 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = CollectionHStack;
|
productName = CollectionHStack;
|
||||||
};
|
};
|
||||||
E1153DAE2BBA734200424D36 /* CollectionHStack */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = E1153DAD2BBA734200424D36 /* XCRemoteSwiftPackageReference "CollectionHStack" */;
|
|
||||||
productName = CollectionHStack;
|
|
||||||
};
|
|
||||||
E1153DB02BBA734C00424D36 /* CollectionHStack */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = E1153DAD2BBA734200424D36 /* XCRemoteSwiftPackageReference "CollectionHStack" */;
|
|
||||||
productName = CollectionHStack;
|
|
||||||
};
|
|
||||||
E1153DCF2BBB634F00424D36 /* SVGKit */ = {
|
E1153DCF2BBB634F00424D36 /* SVGKit */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */;
|
package = E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */;
|
||||||
|
@ -6578,6 +6592,11 @@
|
||||||
package = E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */;
|
package = E1153DCE2BBB634F00424D36 /* XCRemoteSwiftPackageReference "SVGKit" */;
|
||||||
productName = SVGKit;
|
productName = SVGKit;
|
||||||
};
|
};
|
||||||
|
E1155ACA2D0584A90021557A /* IdentifiedCollections */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E176EBDC2D050067009F4CF1 /* XCRemoteSwiftPackageReference "swift-identified-collections" */;
|
||||||
|
productName = IdentifiedCollections;
|
||||||
|
};
|
||||||
E12186DD2718F1C50010884C /* Defaults */ = {
|
E12186DD2718F1C50010884C /* Defaults */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E13DD3D127168E65009D4DAF /* XCRemoteSwiftPackageReference "Defaults" */;
|
package = E13DD3D127168E65009D4DAF /* XCRemoteSwiftPackageReference "Defaults" */;
|
||||||
|
@ -6587,16 +6606,6 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = CollectionVGrid;
|
productName = CollectionVGrid;
|
||||||
};
|
};
|
||||||
E132D3CC2BD2179C0058A2DF /* CollectionVGrid */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = E132D3CB2BD2179C0058A2DF /* XCRemoteSwiftPackageReference "CollectionVGrid" */;
|
|
||||||
productName = CollectionVGrid;
|
|
||||||
};
|
|
||||||
E132D3CE2BD217AA0058A2DF /* CollectionVGrid */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = E132D3CB2BD2179C0058A2DF /* XCRemoteSwiftPackageReference "CollectionVGrid" */;
|
|
||||||
productName = CollectionVGrid;
|
|
||||||
};
|
|
||||||
E1388A45293F0ABA009721B1 /* SwizzleSwift */ = {
|
E1388A45293F0ABA009721B1 /* SwizzleSwift */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 62666E3727E502CE00EC0ECD /* XCRemoteSwiftPackageReference "SwizzleSwift" */;
|
package = 62666E3727E502CE00EC0ECD /* XCRemoteSwiftPackageReference "SwizzleSwift" */;
|
||||||
|
@ -6709,6 +6718,24 @@
|
||||||
package = 5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
|
package = 5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
|
||||||
productName = SwiftUIIntrospect;
|
productName = SwiftUIIntrospect;
|
||||||
};
|
};
|
||||||
|
E176EBDD2D050067009F4CF1 /* IdentifiedCollections */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E176EBDC2D050067009F4CF1 /* XCRemoteSwiftPackageReference "swift-identified-collections" */;
|
||||||
|
productName = IdentifiedCollections;
|
||||||
|
};
|
||||||
|
E176EBDF2D0502A6009F4CF1 /* CollectionHStack */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E176EBDC2D050067009F4CF1 /* XCRemoteSwiftPackageReference "swift-identified-collections" */;
|
||||||
|
productName = CollectionHStack;
|
||||||
|
};
|
||||||
|
E176EBE22D0502C6009F4CF1 /* CollectionHStack */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = CollectionHStack;
|
||||||
|
};
|
||||||
|
E176EBE82D050925009F4CF1 /* CollectionVGrid */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = CollectionVGrid;
|
||||||
|
};
|
||||||
E18443CA2A037773002DDDC8 /* UDPBroadcast */ = {
|
E18443CA2A037773002DDDC8 /* UDPBroadcast */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E1FAD1C42A0375BA007F5521 /* XCRemoteSwiftPackageReference "UDPBroadcastConnection" */;
|
package = E1FAD1C42A0375BA007F5521 /* XCRemoteSwiftPackageReference "UDPBroadcastConnection" */;
|
||||||
|
@ -6758,6 +6785,26 @@
|
||||||
package = E19E6E0828A0BEFF005C10C8 /* XCRemoteSwiftPackageReference "BlurHashKit" */;
|
package = E19E6E0828A0BEFF005C10C8 /* XCRemoteSwiftPackageReference "BlurHashKit" */;
|
||||||
productName = BlurHashKit;
|
productName = BlurHashKit;
|
||||||
};
|
};
|
||||||
|
E1A09F712D05933D00835265 /* CollectionVGrid */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E1A09F702D05933D00835265 /* XCRemoteSwiftPackageReference "CollectionVGrid" */;
|
||||||
|
productName = CollectionVGrid;
|
||||||
|
};
|
||||||
|
E1A09F742D05935100835265 /* CollectionHStack */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E1A09F732D05935100835265 /* XCRemoteSwiftPackageReference "CollectionHStack" */;
|
||||||
|
productName = CollectionHStack;
|
||||||
|
};
|
||||||
|
E1A09F762D05935A00835265 /* CollectionVGrid */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E1A09F702D05933D00835265 /* XCRemoteSwiftPackageReference "CollectionVGrid" */;
|
||||||
|
productName = CollectionVGrid;
|
||||||
|
};
|
||||||
|
E1A09F782D05935A00835265 /* CollectionHStack */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = E1A09F732D05935100835265 /* XCRemoteSwiftPackageReference "CollectionHStack" */;
|
||||||
|
productName = CollectionHStack;
|
||||||
|
};
|
||||||
E1A7B1642B9A9F7800152546 /* PreferencesView */ = {
|
E1A7B1642B9A9F7800152546 /* PreferencesView */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E15D4F032B1B0C3C00442DB8 /* XCLocalSwiftPackageReference "PreferencesView" */;
|
package = E15D4F032B1B0C3C00442DB8 /* XCLocalSwiftPackageReference "PreferencesView" */;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"originHash" : "651194fc1966b57201a0de2cba27dc40798bbdf515febdc83f00d634d916fea4",
|
"originHash" : "b7189175c8066640649da818750e83deee8ef2f766db25c34025f23d451b301d",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "blurhashkit",
|
"identity" : "blurhashkit",
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
"location" : "https://github.com/LePips/CollectionHStack",
|
"location" : "https://github.com/LePips/CollectionHStack",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "main",
|
"branch" : "main",
|
||||||
"revision" : "894b595185bbfce007d60b219ee3e4013884131c"
|
"revision" : "00beb78cc570ee1014a92eb1cd7a60c099bce5ec"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
"location" : "https://github.com/LePips/CollectionVGrid",
|
"location" : "https://github.com/LePips/CollectionVGrid",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "main",
|
"branch" : "main",
|
||||||
"revision" : "91ba930a502761924204ae74a59ded05f3b7ef89"
|
"revision" : "4b1591321339481756af6157c9205051d7fe3040"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -181,6 +181,15 @@
|
||||||
"version" : "1.0.5"
|
"version" : "1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-identified-collections",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/pointfreeco/swift-identified-collections",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "2f5ab6e091dd032b63dacbda052405756010dc3b",
|
||||||
|
"version" : "1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "swift-log",
|
"identity" : "swift-log",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
|
|
|
@ -10,23 +10,23 @@ import CollectionHStack
|
||||||
import OrderedCollections
|
import OrderedCollections
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct PosterHStack<Item: Poster>: View {
|
struct PosterHStack<Element: Poster & Identifiable, Data: Collection>: View where Data.Element == Element, Data.Index == Int {
|
||||||
|
|
||||||
|
private var data: Data
|
||||||
private var header: () -> any View
|
private var header: () -> any View
|
||||||
private var title: String?
|
private var title: String?
|
||||||
private var type: PosterDisplayType
|
private var type: PosterDisplayType
|
||||||
private var items: Binding<OrderedSet<Item>>
|
private var content: (Element) -> any View
|
||||||
private var content: (Item) -> any View
|
private var imageOverlay: (Element) -> any View
|
||||||
private var imageOverlay: (Item) -> any View
|
private var contextMenu: (Element) -> any View
|
||||||
private var contextMenu: (Item) -> any View
|
|
||||||
private var trailingContent: () -> any View
|
private var trailingContent: () -> any View
|
||||||
private var onSelect: (Item) -> Void
|
private var onSelect: (Element) -> Void
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var padHStack: some View {
|
private var padHStack: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
items,
|
uniqueElements: data,
|
||||||
minWidth: type == .portrait ? 140 : 220
|
columns: type == .portrait ? 140 : 220
|
||||||
) { item in
|
) { item in
|
||||||
PosterButton(
|
PosterButton(
|
||||||
item: item,
|
item: item,
|
||||||
|
@ -47,7 +47,7 @@ struct PosterHStack<Item: Poster>: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var phoneHStack: some View {
|
private var phoneHStack: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
items,
|
uniqueElements: data,
|
||||||
columns: type == .portrait ? 3 : 2
|
columns: type == .portrait ? 3 : 2
|
||||||
) { item in
|
) { item in
|
||||||
PosterButton(
|
PosterButton(
|
||||||
|
@ -94,13 +94,13 @@ extension PosterHStack {
|
||||||
init(
|
init(
|
||||||
title: String? = nil,
|
title: String? = nil,
|
||||||
type: PosterDisplayType,
|
type: PosterDisplayType,
|
||||||
items: Binding<OrderedSet<Item>>
|
items: Data
|
||||||
) {
|
) {
|
||||||
self.init(
|
self.init(
|
||||||
|
data: items,
|
||||||
header: { DefaultHeader(title: title) },
|
header: { DefaultHeader(title: title) },
|
||||||
title: title,
|
title: title,
|
||||||
type: type,
|
type: type,
|
||||||
items: items,
|
|
||||||
content: { PosterButton.TitleSubtitleContentView(item: $0) },
|
content: { PosterButton.TitleSubtitleContentView(item: $0) },
|
||||||
imageOverlay: { PosterButton.DefaultOverlay(item: $0) },
|
imageOverlay: { PosterButton.DefaultOverlay(item: $0) },
|
||||||
contextMenu: { _ in EmptyView() },
|
contextMenu: { _ in EmptyView() },
|
||||||
|
@ -109,31 +109,19 @@ extension PosterHStack {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
init<S: Sequence<Item>>(
|
|
||||||
title: String? = nil,
|
|
||||||
type: PosterDisplayType,
|
|
||||||
items: S
|
|
||||||
) {
|
|
||||||
self.init(
|
|
||||||
title: title,
|
|
||||||
type: type,
|
|
||||||
items: .constant(OrderedSet(items))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func header(@ViewBuilder _ header: @escaping () -> any View) -> Self {
|
func header(@ViewBuilder _ header: @escaping () -> any View) -> Self {
|
||||||
copy(modifying: \.header, with: header)
|
copy(modifying: \.header, with: header)
|
||||||
}
|
}
|
||||||
|
|
||||||
func content(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
|
func content(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
|
||||||
copy(modifying: \.content, with: content)
|
copy(modifying: \.content, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageOverlay(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
|
func imageOverlay(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
|
||||||
copy(modifying: \.imageOverlay, with: content)
|
copy(modifying: \.imageOverlay, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func contextMenu(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
|
func contextMenu(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
|
||||||
copy(modifying: \.contextMenu, with: content)
|
copy(modifying: \.contextMenu, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +129,7 @@ extension PosterHStack {
|
||||||
copy(modifying: \.trailingContent, with: content)
|
copy(modifying: \.trailingContent, with: content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSelect(_ action: @escaping (Item) -> Void) -> Self {
|
func onSelect(_ action: @escaping (Element) -> Void) -> Self {
|
||||||
copy(modifying: \.onSelect, with: action)
|
copy(modifying: \.onSelect, with: action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ struct ActiveSessionsView: View {
|
||||||
L10n.noResults.text
|
L10n.noResults.text
|
||||||
} else {
|
} else {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
viewModel.sessions.keys,
|
uniqueElements: viewModel.sessions.keys,
|
||||||
|
id: \.self,
|
||||||
layout: .columns(1, insets: .zero, itemSpacing: 0, lineSpacing: 0)
|
layout: .columns(1, insets: .zero, itemSpacing: 0, lineSpacing: 0)
|
||||||
) { id in
|
) { id in
|
||||||
ActiveSessionRow(box: viewModel.sessions[id]!) {
|
ActiveSessionRow(box: viewModel.sessions[id]!) {
|
||||||
|
|
|
@ -98,8 +98,8 @@ struct ChannelLibraryView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var contentView: some View {
|
private var contentView: some View {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
$viewModel.elements,
|
uniqueElements: viewModel.elements,
|
||||||
layout: $layout
|
layout: layout
|
||||||
) { channel in
|
) { channel in
|
||||||
switch channelDisplayType {
|
switch channelDisplayType {
|
||||||
case .grid:
|
case .grid:
|
||||||
|
|
|
@ -34,7 +34,7 @@ extension HomeView {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
$viewModel.resumeItems,
|
uniqueElements: viewModel.resumeItems,
|
||||||
columns: columnCount
|
columns: columnCount
|
||||||
) { item in
|
) { item in
|
||||||
PosterButton(item: item, type: .landscape)
|
PosterButton(item: item, type: .landscape)
|
||||||
|
|
|
@ -30,7 +30,7 @@ extension HomeView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.latestWithString(viewModel.parent?.displayTitle ?? .emptyDash),
|
title: L10n.latestWithString(viewModel.parent?.displayTitle ?? .emptyDash),
|
||||||
type: latestInLibraryPosterType,
|
type: latestInLibraryPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.trailing {
|
.trailing {
|
||||||
SeeAllButton()
|
SeeAllButton()
|
||||||
|
|
|
@ -31,7 +31,7 @@ extension HomeView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.nextUp,
|
title: L10n.nextUp,
|
||||||
type: nextUpPosterType,
|
type: nextUpPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.content { item in
|
.content { item in
|
||||||
if item.type == .episode {
|
if item.type == .episode {
|
||||||
|
|
|
@ -28,7 +28,7 @@ extension HomeView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.recentlyAdded,
|
title: L10n.recentlyAdded,
|
||||||
type: recentlyAddedPosterType,
|
type: recentlyAddedPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.trailing {
|
.trailing {
|
||||||
SeeAllButton()
|
SeeAllButton()
|
||||||
|
|
|
@ -22,12 +22,25 @@ extension ItemView {
|
||||||
|
|
||||||
struct AboutView: View {
|
struct AboutView: View {
|
||||||
|
|
||||||
private enum AboutViewItem: Hashable {
|
private enum AboutViewItem: Hashable, Identifiable {
|
||||||
|
|
||||||
case image
|
case image
|
||||||
case overview
|
case overview
|
||||||
case mediaSource(MediaSourceInfo)
|
case mediaSource(MediaSourceInfo)
|
||||||
case ratings
|
case ratings
|
||||||
|
|
||||||
|
var id: String? {
|
||||||
|
switch self {
|
||||||
|
case .image:
|
||||||
|
return "image"
|
||||||
|
case .overview:
|
||||||
|
return "overview"
|
||||||
|
case let .mediaSource(source):
|
||||||
|
return source.id
|
||||||
|
case .ratings:
|
||||||
|
return "ratings"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Default(.accentColor)
|
@Default(.accentColor)
|
||||||
|
@ -121,7 +134,10 @@ extension ItemView {
|
||||||
.accessibility(addTraits: [.isHeader])
|
.accessibility(addTraits: [.isHeader])
|
||||||
.edgePadding(.horizontal)
|
.edgePadding(.horizontal)
|
||||||
|
|
||||||
CollectionHStack($items, variadicWidths: true) { item in
|
CollectionHStack(
|
||||||
|
uniqueElements: items,
|
||||||
|
variadicWidths: true
|
||||||
|
) { item in
|
||||||
switch item {
|
switch item {
|
||||||
case .image:
|
case .image:
|
||||||
imageView
|
imageView
|
||||||
|
|
|
@ -24,13 +24,13 @@ extension SeriesEpisodeSelector {
|
||||||
private var didScrollToPlayButtonItem = false
|
private var didScrollToPlayButtonItem = false
|
||||||
|
|
||||||
@StateObject
|
@StateObject
|
||||||
private var proxy = CollectionHStackProxy<BaseItemDto>()
|
private var proxy = CollectionHStackProxy()
|
||||||
|
|
||||||
let playButtonItem: BaseItemDto?
|
let playButtonItem: BaseItemDto?
|
||||||
|
|
||||||
private func contentView(viewModel: SeasonItemViewModel) -> some View {
|
private func contentView(viewModel: SeasonItemViewModel) -> some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
$viewModel.elements,
|
uniqueElements: viewModel.elements,
|
||||||
columns: UIDevice.isPhone ? 1.5 : 3.5
|
columns: UIDevice.isPhone ? 1.5 : 3.5
|
||||||
) { episode in
|
) { episode in
|
||||||
SeriesEpisodeSelector.EpisodeCard(episode: episode)
|
SeriesEpisodeSelector.EpisodeCard(episode: episode)
|
||||||
|
@ -71,7 +71,7 @@ extension SeriesEpisodeSelector {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
0 ..< 1,
|
count: 1,
|
||||||
columns: UIDevice.isPhone ? 1.5 : 3.5
|
columns: UIDevice.isPhone ? 1.5 : 3.5
|
||||||
) { _ in
|
) { _ in
|
||||||
SeriesEpisodeSelector.EmptyCard()
|
SeriesEpisodeSelector.EmptyCard()
|
||||||
|
@ -92,7 +92,7 @@ extension SeriesEpisodeSelector {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
0 ..< 1,
|
count: 1,
|
||||||
columns: UIDevice.isPhone ? 1.5 : 3.5
|
columns: UIDevice.isPhone ? 1.5 : 3.5
|
||||||
) { _ in
|
) { _ in
|
||||||
SeriesEpisodeSelector.ErrorCard(error: error)
|
SeriesEpisodeSelector.ErrorCard(error: error)
|
||||||
|
@ -110,7 +110,7 @@ extension SeriesEpisodeSelector {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
0 ..< Int.random(in: 2 ..< 5),
|
count: Int.random(in: 2 ..< 5),
|
||||||
columns: UIDevice.isPhone ? 1.5 : 3.5
|
columns: UIDevice.isPhone ? 1.5 : 3.5
|
||||||
) { _ in
|
) { _ in
|
||||||
SeriesEpisodeSelector.LoadingCard()
|
SeriesEpisodeSelector.LoadingCard()
|
||||||
|
|
|
@ -32,7 +32,7 @@ extension ItemView {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: L10n.recommended,
|
title: L10n.recommended,
|
||||||
type: similarPosterType,
|
type: similarPosterType,
|
||||||
items: $viewModel.elements
|
items: viewModel.elements
|
||||||
)
|
)
|
||||||
.trailing {
|
.trailing {
|
||||||
SeeAllButton()
|
SeeAllButton()
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct MediaView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var contentView: some View {
|
private var contentView: some View {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
$viewModel.mediaItems,
|
uniqueElements: viewModel.mediaItems,
|
||||||
layout: UIDevice.isPhone ? phoneLayout : padLayout
|
layout: UIDevice.isPhone ? phoneLayout : padLayout
|
||||||
) { mediaType in
|
) { mediaType in
|
||||||
MediaItem(viewModel: viewModel, type: mediaType)
|
MediaItem(viewModel: viewModel, type: mediaType)
|
||||||
|
|
|
@ -36,7 +36,7 @@ import SwiftUI
|
||||||
should be applied.
|
should be applied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct PagingLibraryView<Element: Poster>: View {
|
struct PagingLibraryView<Element: Poster & Identifiable>: View {
|
||||||
|
|
||||||
@Default(.Customization.Library.enabledDrawerFilters)
|
@Default(.Customization.Library.enabledDrawerFilters)
|
||||||
private var enabledDrawerFilters
|
private var enabledDrawerFilters
|
||||||
|
@ -71,7 +71,7 @@ struct PagingLibraryView<Element: Poster>: View {
|
||||||
private var posterType: PosterDisplayType
|
private var posterType: PosterDisplayType
|
||||||
|
|
||||||
@StateObject
|
@StateObject
|
||||||
private var collectionVGridProxy: CollectionVGridProxy<Element> = .init()
|
private var collectionVGridProxy: CollectionVGridProxy = .init()
|
||||||
@StateObject
|
@StateObject
|
||||||
private var viewModel: PagingLibraryViewModel<Element>
|
private var viewModel: PagingLibraryViewModel<Element>
|
||||||
|
|
||||||
|
@ -239,8 +239,8 @@ struct PagingLibraryView<Element: Poster>: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var gridView: some View {
|
private var gridView: some View {
|
||||||
CollectionVGrid(
|
CollectionVGrid(
|
||||||
$viewModel.elements,
|
uniqueElements: viewModel.elements,
|
||||||
layout: $layout
|
layout: layout
|
||||||
) { item in
|
) { item in
|
||||||
|
|
||||||
let displayType = Defaults[.Customization.Library.rememberLayout] ? _displayType.wrappedValue : _defaultDisplayType
|
let displayType = Defaults[.Customization.Library.rememberLayout] ? _displayType.wrappedValue : _defaultDisplayType
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import CollectionHStack
|
import CollectionHStack
|
||||||
import Defaults
|
import Defaults
|
||||||
import JellyfinAPI
|
import JellyfinAPI
|
||||||
|
import OrderedCollections
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import VLCUI
|
import VLCUI
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ extension VideoPlayer.Overlay {
|
||||||
private var size: CGSize = .zero
|
private var size: CGSize = .zero
|
||||||
|
|
||||||
@StateObject
|
@StateObject
|
||||||
private var collectionHStackProxy: CollectionHStackProxy<ChapterInfo.FullInfo> = .init()
|
private var collectionHStackProxy: CollectionHStackProxy = .init()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
|
@ -61,7 +62,7 @@ extension VideoPlayer.Overlay {
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
if let currentChapter = viewModel.chapter(from: currentProgressHandler.seconds) {
|
if let currentChapter = viewModel.chapter(from: currentProgressHandler.seconds) {
|
||||||
collectionHStackProxy.scrollTo(element: currentChapter, animated: true)
|
collectionHStackProxy.scrollTo(element: currentChapter)
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Text(L10n.current)
|
Text(L10n.current)
|
||||||
|
@ -73,7 +74,7 @@ extension VideoPlayer.Overlay {
|
||||||
.edgePadding(.horizontal)
|
.edgePadding(.horizontal)
|
||||||
|
|
||||||
CollectionHStack(
|
CollectionHStack(
|
||||||
viewModel.chapters,
|
uniqueElements: viewModel.chapters,
|
||||||
minWidth: 200
|
minWidth: 200
|
||||||
) { chapter in
|
) { chapter in
|
||||||
ChapterButton(chapter: chapter)
|
ChapterButton(chapter: chapter)
|
||||||
|
|
Loading…
Reference in New Issue