Skip to content

Commit

Permalink
[iOS & tvOS] Use AboutView for Series Poster Routing (#1438)
Browse files Browse the repository at this point in the history
* Move Series Button to the About Section IF the item is an episode. Otherwise, continue using that image as just an image. tvOS & iOS.

* use posterbutton

---------

Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>
  • Loading branch information
JPKribs and LePips authored Feb 23, 2025
1 parent 137f0db commit 35b72b3
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 64 deletions.
1 change: 1 addition & 0 deletions Swiftfin tvOS/Components/PosterButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct PosterButton<Item: Poster>: View {
)
}
}
.accessibilityIgnoresInvertColors()

imageOverlay()
.eraseToAnyView()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@ extension ItemView {

ScrollView(.horizontal) {
HStack(alignment: .top, spacing: 30) {
PosterButton(item: viewModel.item, type: .portrait)
.content {
EmptyView()
}
.imageOverlay {
EmptyView()
}
.frame(height: 405)
ImageCard(viewModel: viewModel)

OverviewCard(item: viewModel.item)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// 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) 2025 Jellyfin & Jellyfin Contributors
//

import Defaults
import JellyfinAPI
import SwiftUI

extension ItemView.AboutView {

struct ImageCard: View {

// MARK: - Environment & Observed Objects

@EnvironmentObject
private var router: ItemCoordinator.Router

@ObservedObject
var viewModel: ItemViewModel

// MARK: - Body

var body: some View {
PosterButton(item: viewModel.item, type: .portrait)
.content { EmptyView() }
.imageOverlay { EmptyView() }
.onSelect(onSelect)
.frame(height: 405)
}

// MARK: - On Select

// Switch case to allow other funcitonality if we need to expand this beyond episode > series
private func onSelect() {
switch viewModel.item.type {
case .episode:
if let episodeViewModel = viewModel as? EpisodeItemViewModel,
let seriesItem = episodeViewModel.seriesItem
{
router.route(to: \.item, seriesItem)
}
default:
break
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ extension EpisodeItemView {
ItemView.CastAndCrewHStack(people: castAndCrew)
}

if let seriesItem = viewModel.seriesItem {
PosterHStack(
title: L10n.series,
type: .portrait,
items: [seriesItem]
)
.onSelect { item in
router.route(to: \.item, item)
}
}

ItemView.AboutView(viewModel: viewModel)
}
.background {
Expand Down
8 changes: 8 additions & 0 deletions Swiftfin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
4E556AB02D036F6900733377 /* UserPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E556AAF2D036F5E00733377 /* UserPermissions.swift */; };
4E556AB12D036F6900733377 /* UserPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E556AAF2D036F5E00733377 /* UserPermissions.swift */; };
4E5E48E52AB59806003F1B48 /* CustomizeViewsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */; };
4E5EE5512D67CE9500982290 /* ImageCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5EE5502D67CE9000982290 /* ImageCard.swift */; };
4E5EE5532D67CFAB00982290 /* ImageCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5EE5522D67CFAB00982290 /* ImageCard.swift */; };
4E63B9FA2C8A5BEF00C25378 /* AdminDashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9F42C8A5BEF00C25378 /* AdminDashboardView.swift */; };
4E63B9FC2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9FB2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift */; };
4E656C302D0798AA00F993F3 /* ParentalRating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E656C2F2D0798A900F993F3 /* ParentalRating.swift */; };
Expand Down Expand Up @@ -1343,6 +1345,8 @@
4E5508722D13AFE3002A5345 /* UserProfileImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileImage.swift; sourceTree = "<group>"; };
4E556AAF2D036F5E00733377 /* UserPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPermissions.swift; sourceTree = "<group>"; };
4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizeViewsSettings.swift; sourceTree = "<group>"; };
4E5EE5502D67CE9000982290 /* ImageCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCard.swift; sourceTree = "<group>"; };
4E5EE5522D67CFAB00982290 /* ImageCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCard.swift; sourceTree = "<group>"; };
4E63B9F42C8A5BEF00C25378 /* AdminDashboardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdminDashboardView.swift; sourceTree = "<group>"; };
4E63B9FB2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveSessionsViewModel.swift; sourceTree = "<group>"; };
4E656C2F2D0798A900F993F3 /* ParentalRating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentalRating.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4772,6 +4776,7 @@
isa = PBXGroup;
children = (
E12376AD2A33D680001F5B44 /* AboutView+Card.swift */,
4E5EE5502D67CE9000982290 /* ImageCard.swift */,
E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */,
E1E750652A33E9B400B2C1EE /* OverviewCard.swift */,
E1E750672A33E9B400B2C1EE /* RatingsCard.swift */,
Expand Down Expand Up @@ -5241,6 +5246,7 @@
isa = PBXGroup;
children = (
E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */,
4E5EE5522D67CFAB00982290 /* ImageCard.swift */,
E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */,
E1DABAF92A270E62008AC34A /* OverviewCard.swift */,
E1DABAFD2A27B982008AC34A /* RatingsCard.swift */,
Expand Down Expand Up @@ -5874,6 +5880,7 @@
E1DC983E296DEB9B00982F06 /* UnwatchedIndicator.swift in Sources */,
4E2AC4BF2C6C48D200DD600D /* CustomDeviceProfileAction.swift in Sources */,
4EBE06472C7E9509004A6C03 /* PlaybackCompatibility.swift in Sources */,
4E5EE5532D67CFAB00982290 /* ImageCard.swift in Sources */,
4E661A2B2CEFE6F400025C99 /* Video3DFormat.swift in Sources */,
E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */,
53ABFDE9267974EF00886593 /* HomeViewModel.swift in Sources */,
Expand Down Expand Up @@ -6890,6 +6897,7 @@
4E35CE662CBED8B600DBD886 /* ServerTicks.swift in Sources */,
E1D3043528D1763100587289 /* SeeAllButton.swift in Sources */,
4E73E2A62C41CFD3002D2A78 /* PlaybackBitrateTestSize.swift in Sources */,
4E5EE5512D67CE9500982290 /* ImageCard.swift in Sources */,
E172D3B22BACA569007B4647 /* EpisodeContent.swift in Sources */,
4E1A39342D56C84200BAC1C7 /* ItemViewAttributes.swift in Sources */,
4EC1C8522C7FDFA300E2879E /* PlaybackDeviceProfile.swift in Sources */,
Expand Down
19 changes: 2 additions & 17 deletions Swiftfin/Views/ItemView/Components/AboutView/AboutView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,22 +106,6 @@ extension ItemView {
return CGSize(width: width, height: height)
}

@ViewBuilder
private var imageView: some View {
ZStack {
Color.clear

ImageView(
viewModel.item.type == .episode ? viewModel.item.seriesImageSource(.primary, maxWidth: 300) : viewModel
.item.imageSource(.primary, maxWidth: 300)
)
.accessibilityIgnoresInvertColors()
}
.posterStyle(.portrait)
.posterShadow()
.frame(width: UIDevice.isPad ? padImageWidth : phoneImageWidth)
}

var body: some View {
VStack(alignment: .leading) {
L10n.about.text
Expand All @@ -136,7 +120,8 @@ extension ItemView {
) { item in
switch item {
case .image:
imageView
ImageCard(viewModel: viewModel)
.frame(width: UIDevice.isPad ? padImageWidth : phoneImageWidth)
case .overview:
OverviewCard(item: viewModel.item)
.frame(width: cardSize.width, height: cardSize.height)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// 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) 2025 Jellyfin & Jellyfin Contributors
//

import Defaults
import JellyfinAPI
import SwiftUI

extension ItemView.AboutView {

struct ImageCard: View {

// MARK: - Environment & Observed Objects

@EnvironmentObject
private var router: ItemCoordinator.Router

@ObservedObject
var viewModel: ItemViewModel

// MARK: - Body

var body: some View {
PosterButton(item: viewModel.item, type: .portrait)
.content { EmptyView() }
.imageOverlay { EmptyView() }
.onSelect(onSelect)
}

// MARK: - On Select

// Switch case to allow other funcitonality if we need to expand this beyond episode > series
private func onSelect() {
switch viewModel.item.type {
case .episode:
if let episodeViewModel = viewModel as? EpisodeItemViewModel,
let seriesItem = episodeViewModel.seriesItem
{
router.route(to: \.item, seriesItem)
}
default:
break
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,6 @@ extension EpisodeItemView {
RowDivider()
}

// MARK: Series

// TODO: have different way to get to series item
// - about view poster?
if let seriesItem = viewModel.seriesItem {
PosterHStack(
title: L10n.series,
type: .portrait,
items: [seriesItem]
)
.onSelect { item in
router.route(to: \.item, item)
}
}

ItemView.AboutView(viewModel: viewModel)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,6 @@ extension iPadOSEpisodeItemView {
RowDivider()
}

// MARK: Series

if let seriesItem = viewModel.seriesItem {
PosterHStack(
title: L10n.series,
type: .portrait,
items: [seriesItem]
)
.onSelect { item in
router.route(to: \.item, item)
}
}

ItemView.AboutView(viewModel: viewModel)
}
}
Expand Down

0 comments on commit 35b72b3

Please sign in to comment.