Skip to content

Commit

Permalink
Remove iOS PosterButtonType + cleanup (jellyfin#883)
Browse files Browse the repository at this point in the history
  • Loading branch information
LePips authored Nov 1, 2023
1 parent 5a40741 commit 9266d53
Show file tree
Hide file tree
Showing 38 changed files with 301 additions and 445 deletions.
1 change: 1 addition & 0 deletions Shared/Extensions/EnvironmentValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import SwiftUI

// TODO: Look at name spacing
// TODO: Consistent naming: ...Key

struct AudioOffset: EnvironmentKey {
static let defaultValue: Binding<Int> = .constant(0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2023 Jellyfin & Jellyfin Contributors
//

import SwiftUI

struct PaddingMultiplierModifier: ViewModifier {

let edges: Edge.Set
let multiplier: Int

func body(content: Content) -> some View {
content
.if(multiplier > 0) { view in
view.padding()
.padding(multiplier: multiplier - 1, edges)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2023 Jellyfin & Jellyfin Contributors
//

import SwiftUI

struct RatioCornerRadiusModifier: ViewModifier {

@State
private var cornerRadius: CGFloat = 0

let corners: UIRectCorner
let ratio: CGFloat
let side: KeyPath<CGSize, CGFloat>

func body(content: Content) -> some View {
content
.cornerRadius(cornerRadius, corners: corners)
.onSizeChanged { newSize in
cornerRadius = newSize[keyPath: side] * ratio
}
}
}
67 changes: 24 additions & 43 deletions Shared/Extensions/ViewExtensions/ViewExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,57 +50,32 @@ extension View {
}
}

// TODO: Simplify plethora of calls
// TODO: Centralize math
// TODO: Move poster stuff to own file
// TODO: Figure out proper handling of corner radius for tvOS buttons
func posterStyle(type: PosterType, width: CGFloat) -> some View {
Group {
switch type {
case .portrait:
self.portraitPoster(width: width)
case .landscape:
self.landscapePoster(width: width)
}
}
}

func posterStyle(type: PosterType, height: CGFloat) -> some View {
Group {
switch type {
case .portrait:
self.portraitPoster(height: height)
case .landscape:
self.landscapePoster(height: height)
}
// TODO: Don't apply corner radius on tvOS because buttons handle themselves, add new modifier for setting corner radius of poster type
@ViewBuilder
func posterStyle(_ type: PosterType) -> some View {
switch type {
case .portrait:
aspectRatio(2 / 3, contentMode: .fit)
.cornerRadius(ratio: 0.0375, of: \.width)
case .landscape:
aspectRatio(1.77, contentMode: .fit)
.cornerRadius(ratio: 1 / 30, of: \.width)
}
}

private func portraitPoster(width: CGFloat) -> some View {
frame(width: width, height: width * 1.5)
.cornerRadius((width * 1.5) / 40)
}

private func landscapePoster(width: CGFloat) -> some View {
frame(width: width, height: width / 1.77)
#if !os(tvOS)
.cornerRadius(width / 30)
#endif
}

private func portraitPoster(height: CGFloat) -> some View {
portraitPoster(width: height / 1.5)
}

private func landscapePoster(height: CGFloat) -> some View {
landscapePoster(width: height * 1.77)
}

// TODO: switch to padding(multiplier: 2)
@inlinable
func padding2(_ edges: Edge.Set = .all) -> some View {
padding(edges).padding(edges)
}

/// Applies the default system padding a number of times with a multiplier
func padding(multiplier: Int, _ edges: Edge.Set = .all) -> some View {
precondition(multiplier > 0, "Multiplier must be > 0")

return modifier(PaddingMultiplierModifier(edges: edges, multiplier: multiplier))
}

func scrollViewOffset(_ scrollViewOffset: Binding<CGFloat>) -> some View {
modifier(ScrollViewOffsetModifier(scrollViewOffset: scrollViewOffset))
}
Expand All @@ -126,6 +101,11 @@ extension View {
clipShape(RoundedCorner(radius: radius, corners: corners))
}

/// Apply a corner radius as a ratio of a side of the view's size
func cornerRadius(ratio: CGFloat, of side: KeyPath<CGSize, CGFloat>, corners: UIRectCorner = .allCorners) -> some View {
modifier(RatioCornerRadiusModifier(corners: corners, ratio: ratio, side: side))
}

func onFrameChanged(_ onChange: @escaping (CGRect) -> Void) -> some View {
background {
GeometryReader { reader in
Expand Down Expand Up @@ -174,6 +154,7 @@ extension View {
}
}

// TODO: rename isVisible
@inlinable
func visible(_ isVisible: Bool) -> some View {
opacity(isVisible ? 1 : 0)
Expand Down
2 changes: 1 addition & 1 deletion Shared/Objects/MenuPosterHStackModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ protocol MenuPosterHStackModel: ObservableObject {
associatedtype Item: Poster

var menuSelection: Section? { get }
var menuSections: [Section: [PosterButtonType<Item>]] { get set }
var menuSections: [Section: [Item]] { get set }
var menuSectionSort: (Section, Section) -> Bool { get }

func select(section: Section)
Expand Down
6 changes: 2 additions & 4 deletions Shared/Objects/Poster.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import Foundation

// TODO: find way to remove special `single` handling
// TODO: remove `showTitle` and `subtitle` since the PosterButton can define custom supplementary views?
protocol Poster: Displayable, Hashable {

var subtitle: String? { get }
Expand All @@ -19,10 +21,6 @@ protocol Poster: Displayable, Hashable {
}

extension Poster {
func hash(into hasher: inout Hasher) {
hasher.combine(displayTitle)
hasher.combine(subtitle)
}

func cinematicPosterImageSources() -> [ImageSource] {
[]
Expand Down
36 changes: 0 additions & 36 deletions Shared/Objects/PosterButtonType.swift

This file was deleted.

21 changes: 3 additions & 18 deletions Shared/ViewModels/ItemViewModel/SeriesItemViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class SeriesItemViewModel: ItemViewModel, MenuPosterHStackModel {
@Published
var menuSelection: BaseItemDto?
@Published
var menuSections: [BaseItemDto: [PosterButtonType<BaseItemDto>]]
var menuSections: [BaseItemDto: [BaseItemDto]]
var menuSectionSort: (BaseItemDto, BaseItemDto) -> Bool

override init(item: BaseItemDto) {
Expand Down Expand Up @@ -117,14 +117,7 @@ final class SeriesItemViewModel: ItemViewModel, MenuPosterHStackModel {
func select(section: BaseItemDto) {
self.menuSelection = section

if let existingItems = menuSections[section] {
if existingItems.allSatisfy({ $0 == .loading }) {
getEpisodesForSeason(section)
} else if existingItems.allSatisfy({ $0 == .noResult }) {
menuSections[section] = PosterButtonType.loading.random(in: 3 ..< 8)
getEpisodesForSeason(section)
}
} else {
if !menuSections.keys.contains(section) {
getEpisodesForSeason(section)
}
}
Expand All @@ -140,12 +133,6 @@ final class SeriesItemViewModel: ItemViewModel, MenuPosterHStackModel {

guard let seasons = response.value.items else { return }

await MainActor.run {
seasons.forEach { season in
self.menuSections[season] = PosterButtonType.loading.random(in: 3 ..< 8)
}
}

if let firstSeason = seasons.first {
self.getEpisodesForSeason(firstSeason)
await MainActor.run {
Expand All @@ -169,9 +156,7 @@ final class SeriesItemViewModel: ItemViewModel, MenuPosterHStackModel {

await MainActor.run {
if let items = response.value.items {
self.menuSections[season] = items.map { .item($0) }
} else {
self.menuSections[season] = [.noResult]
self.menuSections[season] = items
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Shared/ViewModels/SpecialFeaturesViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ class SpecialFeaturesViewModel: ViewModel, MenuPosterHStackModel {
@Published
var menuSelection: SpecialFeatureType?
@Published
var menuSections: [SpecialFeatureType: [PosterButtonType<BaseItemDto>]]
var menuSections: [SpecialFeatureType: [BaseItemDto]]
var menuSectionSort: (SpecialFeatureType, SpecialFeatureType) -> Bool

init(sections: [SpecialFeatureType: [PosterButtonType<BaseItemDto>]]) {
init(sections: [SpecialFeatureType: [BaseItemDto]]) {
let comparator: (SpecialFeatureType, SpecialFeatureType) -> Bool = { i, j in i.rawValue < j.rawValue }
self.menuSelection = Array(sections.keys).sorted(by: comparator).first!
self.menuSections = sections
Expand Down
3 changes: 2 additions & 1 deletion Swiftfin tvOS/Components/NonePosterButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ struct NonePosterButton: View {
.foregroundColor(.secondary)
}
}
.posterStyle(type: type, width: type.width)
.posterStyle(type)
.frame(width: type.width)
}
}
.buttonStyle(.card)
Expand Down
7 changes: 4 additions & 3 deletions Swiftfin tvOS/Components/PosterButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,20 @@ struct PosterButton<Item: Poster>: View {
.failure {
InitialFailureView(item.displayTitle.initials)
}
.posterStyle(type: type, width: itemWidth)
case .landscape:
ImageView(item.landscapePosterImageSources(maxWidth: itemWidth, single: singleImage))
.failure {
InitialFailureView(item.displayTitle.initials)
}
.posterStyle(type: type, width: itemWidth)
}
}
.posterStyle(type)
.frame(width: itemWidth)
.overlay {
imageOverlay()
.eraseToAnyView()
.posterStyle(type: type, width: itemWidth)
.posterStyle(type)
.frame(width: itemWidth)
}
}
.buttonStyle(.card)
Expand Down
3 changes: 2 additions & 1 deletion Swiftfin tvOS/Components/SeeAllPosterButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ struct SeeAllPosterButton: View {
.font(.title3)
}
}
.posterStyle(type: type, width: type.width)
.posterStyle(type)
.frame(width: type.width)
}
.buttonStyle(.card)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ extension SeriesEpisodeSelector {
private var items: [BaseItemDto] {
guard let selection = viewModel.menuSelection,
let items = viewModel.menuSections[selection] else { return [.noResults] }
return items.compactMap(\._item)
return items
}

var body: some View {
Expand Down
3 changes: 2 additions & 1 deletion Swiftfin tvOS/Views/MediaView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ extension MediaView {
}
}
}
.posterStyle(type: .landscape, width: itemWidth)
.posterStyle(.landscape)
.frame(width: itemWidth)
}
.buttonStyle(.card)
}
Expand Down
Loading

0 comments on commit 9266d53

Please sign in to comment.