Skip to content

Commit

Permalink
Move to IdentifiedArray in PagingLibraryViewModel (#1346)
Browse files Browse the repository at this point in the history
* init

* update packages, cleanup
  • Loading branch information
LePips authored Dec 8, 2024
1 parent 0797fb5 commit e856303
Show file tree
Hide file tree
Showing 27 changed files with 215 additions and 151 deletions.
4 changes: 2 additions & 2 deletions Shared/Strings/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1086,10 +1086,10 @@ internal enum L10n {
internal static let run = L10n.tr("Localizable", "run", fallback: "Run")
/// Running...
internal static let running = L10n.tr("Localizable", "running", fallback: "Running...")
/// Runtime
internal static let runtime = L10n.tr("Localizable", "runtime", fallback: "Runtime")
/// 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
internal static let save = L10n.tr("Localizable", "save", fallback: "Save")
/// Scan All Libraries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Combine
import Defaults
import Foundation
import Get
import IdentifiedCollections
import JellyfinAPI
import OrderedCollections
import UIKit
Expand All @@ -32,7 +33,7 @@ private let DefaultPageSize = 50
on remembering other filters.
*/

class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
class PagingLibraryViewModel<Element: Poster & Identifiable>: ViewModel, Eventful, Stateful {

// MARK: Event

Expand Down Expand Up @@ -67,7 +68,7 @@ class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
@Published
final var backgroundStates: OrderedSet<BackgroundState> = []
@Published
final var elements: OrderedSet<Element>
final var elements: IdentifiedArrayOf<Element>
@Published
final var state: State = .initial
@Published
Expand Down Expand Up @@ -103,7 +104,7 @@ class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
parent: (any LibraryParent)? = nil
) {
self.filterViewModel = nil
self.elements = OrderedSet(data)
self.elements = IdentifiedArray(uniqueElements: data)
self.isStatic = true
self.hasNextPage = false
self.pageSize = DefaultPageSize
Expand All @@ -130,7 +131,7 @@ class PagingLibraryViewModel<Element: Poster>: ViewModel, Eventful, Stateful {
filters: ItemFilterCollection? = nil,
pageSize: Int = DefaultPageSize
) {
self.elements = OrderedSet()
self.elements = IdentifiedArray()
self.isStatic = false
self.pageSize = pageSize
self.parent = parent
Expand Down
16 changes: 15 additions & 1 deletion Shared/ViewModels/MediaViewModel/MediaType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import JellyfinAPI

extension MediaViewModel {

enum MediaType: Displayable, Hashable {
enum MediaType: Displayable, Hashable, Identifiable {

case collectionFolder(BaseItemDto)
case downloads
case favorites
Expand All @@ -29,5 +30,18 @@ extension MediaViewModel {
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
}
}
}
}
45 changes: 16 additions & 29 deletions Swiftfin tvOS/Components/PosterHStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ import SwiftUI

// 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 type: PosterDisplayType
private var items: Binding<OrderedSet<Item>>
private var content: (Item) -> any View
private var imageOverlay: (Item) -> any View
private var contextMenu: (Item) -> any View
private var content: (Element) -> any View
private var imageOverlay: (Element) -> any View
private var contextMenu: (Element) -> any View
private var trailingContent: () -> any View
private var onSelect: (Item) -> Void
private var onSelect: (Element) -> Void

// See PosterButton for implementation reason
private var focusedItem: Binding<Item?>?
private var focusedItem: Binding<Element?>?

var body: some View {
VStack(alignment: .leading, spacing: 20) {
Expand All @@ -42,7 +42,7 @@ struct PosterHStack<Item: Poster>: View {
}

CollectionHStack(
items,
uniqueElements: data,
columns: type == .landscape ? 4 : 7
) { item in
PosterButton(item: item, type: type)
Expand Down Expand Up @@ -86,54 +86,41 @@ extension PosterHStack {
init(
title: String? = nil,
type: PosterDisplayType,
items: Binding<OrderedSet<Item>>
items: Data
) {
self.init(
data: items,
title: title,
type: type,
items: items,
content: { PosterButton.TitleSubtitleContentView(item: $0) },
imageOverlay: { PosterButton.DefaultOverlay(item: $0) },
contextMenu: { _ in EmptyView() },
trailingContent: { EmptyView() },
onSelect: { _ in },
focusedItem: nil
onSelect: { _ in }
)
}

init<S: Sequence<Item>>(
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 {
func content(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
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)
}

func contextMenu(@ViewBuilder _ content: @escaping (Item) -> any View) -> Self {
func contextMenu(@ViewBuilder _ content: @escaping (Element) -> any View) -> Self {
copy(modifying: \.contextMenu, with: content)
}

func trailing(@ViewBuilder _ content: @escaping () -> any View) -> Self {
copy(modifying: \.trailingContent, with: content)
}

func onSelect(_ action: @escaping (Item) -> Void) -> Self {
func onSelect(_ action: @escaping (Element) -> Void) -> Self {
copy(modifying: \.onSelect, with: action)
}

func focusedItem(_ binding: Binding<Item?>) -> Self {
func focusedItem(_ binding: Binding<Element?>) -> Self {
copy(modifying: \.focusedItem, with: binding)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct ChannelLibraryView: View {
@ViewBuilder
private var contentView: some View {
CollectionVGrid(
$viewModel.elements,
uniqueElements: viewModel.elements,
layout: .columns(3, insets: .init(0), itemSpacing: 25, lineSpacing: 25)
) { channel in
WideChannelGridItem(channel: channel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extension HomeView {
PosterHStack(
title: L10n.latestWithString(viewModel.parent?.displayTitle ?? .emptyDash),
type: .portrait,
items: $viewModel.elements
items: viewModel.elements
)
.onSelect { item in
router.route(to: \.item, item)
Expand Down
2 changes: 1 addition & 1 deletion Swiftfin tvOS/Views/HomeView/Components/NextUpView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extension HomeView {
PosterHStack(
title: L10n.nextUp,
type: nextUpPosterType,
items: $viewModel.elements
items: viewModel.elements
)
.onSelect { item in
router.route(to: \.item, item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extension HomeView {
PosterHStack(
title: L10n.recentlyAdded,
type: recentlyAddedPosterType,
items: $viewModel.elements
items: viewModel.elements
)
.onSelect { item in
router.route(to: \.item, item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ extension SeriesEpisodeSelector {
private var lastFocusedEpisodeID: String?

@StateObject
private var proxy = CollectionHStackProxy<BaseItemDto>()
private var proxy = CollectionHStackProxy()

let playButtonItem: BaseItemDto?

private func contentView(viewModel: SeasonItemViewModel) -> some View {
CollectionHStack(
$viewModel.elements,
uniqueElements: viewModel.elements,
columns: 3.5
) { episode in
SeriesEpisodeSelector.EpisodeCard(episode: episode)
Expand Down Expand Up @@ -103,7 +103,7 @@ extension SeriesEpisodeSelector {

var body: some View {
CollectionHStack(
0 ..< 1,
count: 1,
columns: 3.5
) { _ in
SeriesEpisodeSelector.ErrorCard(error: error)
Expand All @@ -121,7 +121,7 @@ extension SeriesEpisodeSelector {

var body: some View {
CollectionHStack(
0 ..< Int.random(in: 2 ..< 5),
count: Int.random(in: 2 ..< 5),
columns: 3.5
) { _ in
SeriesEpisodeSelector.LoadingCard()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension ItemView {
PosterHStack(
title: L10n.recommended,
type: similarPosterType,
items: $viewModel.elements
items: viewModel.elements
)
.onSelect { item in
router.route(to: \.item, item)
Expand Down
2 changes: 1 addition & 1 deletion Swiftfin tvOS/Views/MediaView/MediaView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct MediaView: View {
@ViewBuilder
private var contentView: some View {
CollectionVGrid(
$viewModel.mediaItems,
uniqueElements: viewModel.mediaItems,
layout: .columns(4, insets: .init(50), itemSpacing: 50, lineSpacing: 50)
) { mediaType in
MediaItem(viewModel: viewModel, type: mediaType)
Expand Down
4 changes: 2 additions & 2 deletions Swiftfin tvOS/Views/PagingLibraryView/PagingLibraryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import SwiftUI
// TODO: list row view (LibraryRow)
// TODO: fix paging for next item focusing the tab

struct PagingLibraryView<Element: Poster>: View {
struct PagingLibraryView<Element: Poster & Identifiable>: View {

@Default(.Customization.Library.cinematicBackground)
private var cinematicBackground
Expand Down Expand Up @@ -159,7 +159,7 @@ struct PagingLibraryView<Element: Poster>: View {
@ViewBuilder
private var contentView: some View {
CollectionVGrid(
$viewModel.elements,
uniqueElements: viewModel.elements,
layout: layout
) { item in
switch (posterType, viewType) {
Expand Down
Loading

0 comments on commit e856303

Please sign in to comment.