[iOS & tvOS] Use `AboutView` for Series Poster Routing (#1438)
* 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>
This commit is contained in:
parent
137f0dbf13
commit
35b72b3a5a
|
@ -57,6 +57,7 @@ struct PosterButton<Item: Poster>: View {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.accessibilityIgnoresInvertColors()
|
||||||
|
|
||||||
imageOverlay()
|
imageOverlay()
|
||||||
.eraseToAnyView()
|
.eraseToAnyView()
|
||||||
|
|
|
@ -26,14 +26,7 @@ extension ItemView {
|
||||||
|
|
||||||
ScrollView(.horizontal) {
|
ScrollView(.horizontal) {
|
||||||
HStack(alignment: .top, spacing: 30) {
|
HStack(alignment: .top, spacing: 30) {
|
||||||
PosterButton(item: viewModel.item, type: .portrait)
|
ImageCard(viewModel: viewModel)
|
||||||
.content {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
.imageOverlay {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
.frame(height: 405)
|
|
||||||
|
|
||||||
OverviewCard(item: viewModel.item)
|
OverviewCard(item: viewModel.item)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,17 +29,6 @@ extension EpisodeItemView {
|
||||||
ItemView.CastAndCrewHStack(people: castAndCrew)
|
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)
|
ItemView.AboutView(viewModel: viewModel)
|
||||||
}
|
}
|
||||||
.background {
|
.background {
|
||||||
|
|
|
@ -106,6 +106,8 @@
|
||||||
4E556AB02D036F6900733377 /* UserPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E556AAF2D036F5E00733377 /* UserPermissions.swift */; };
|
4E556AB02D036F6900733377 /* UserPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E556AAF2D036F5E00733377 /* UserPermissions.swift */; };
|
||||||
4E556AB12D036F6900733377 /* 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 */; };
|
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 */; };
|
4E63B9FA2C8A5BEF00C25378 /* AdminDashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9F42C8A5BEF00C25378 /* AdminDashboardView.swift */; };
|
||||||
4E63B9FC2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9FB2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift */; };
|
4E63B9FC2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9FB2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift */; };
|
||||||
4E656C302D0798AA00F993F3 /* ParentalRating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E656C2F2D0798A900F993F3 /* ParentalRating.swift */; };
|
4E656C302D0798AA00F993F3 /* ParentalRating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E656C2F2D0798A900F993F3 /* ParentalRating.swift */; };
|
||||||
|
@ -1343,6 +1345,8 @@
|
||||||
4E5508722D13AFE3002A5345 /* UserProfileImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileImage.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
4E656C2F2D0798A900F993F3 /* ParentalRating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentalRating.swift; sourceTree = "<group>"; };
|
||||||
|
@ -4772,6 +4776,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E12376AD2A33D680001F5B44 /* AboutView+Card.swift */,
|
E12376AD2A33D680001F5B44 /* AboutView+Card.swift */,
|
||||||
|
4E5EE5502D67CE9000982290 /* ImageCard.swift */,
|
||||||
E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */,
|
E1E750662A33E9B400B2C1EE /* MediaSourcesCard.swift */,
|
||||||
E1E750652A33E9B400B2C1EE /* OverviewCard.swift */,
|
E1E750652A33E9B400B2C1EE /* OverviewCard.swift */,
|
||||||
E1E750672A33E9B400B2C1EE /* RatingsCard.swift */,
|
E1E750672A33E9B400B2C1EE /* RatingsCard.swift */,
|
||||||
|
@ -5241,6 +5246,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */,
|
E12376AF2A33D6AE001F5B44 /* AboutViewCard.swift */,
|
||||||
|
4E5EE5522D67CFAB00982290 /* ImageCard.swift */,
|
||||||
E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */,
|
E1DABAFB2A270EE7008AC34A /* MediaSourcesCard.swift */,
|
||||||
E1DABAF92A270E62008AC34A /* OverviewCard.swift */,
|
E1DABAF92A270E62008AC34A /* OverviewCard.swift */,
|
||||||
E1DABAFD2A27B982008AC34A /* RatingsCard.swift */,
|
E1DABAFD2A27B982008AC34A /* RatingsCard.swift */,
|
||||||
|
@ -5874,6 +5880,7 @@
|
||||||
E1DC983E296DEB9B00982F06 /* UnwatchedIndicator.swift in Sources */,
|
E1DC983E296DEB9B00982F06 /* UnwatchedIndicator.swift in Sources */,
|
||||||
4E2AC4BF2C6C48D200DD600D /* CustomDeviceProfileAction.swift in Sources */,
|
4E2AC4BF2C6C48D200DD600D /* CustomDeviceProfileAction.swift in Sources */,
|
||||||
4EBE06472C7E9509004A6C03 /* PlaybackCompatibility.swift in Sources */,
|
4EBE06472C7E9509004A6C03 /* PlaybackCompatibility.swift in Sources */,
|
||||||
|
4E5EE5532D67CFAB00982290 /* ImageCard.swift in Sources */,
|
||||||
4E661A2B2CEFE6F400025C99 /* Video3DFormat.swift in Sources */,
|
4E661A2B2CEFE6F400025C99 /* Video3DFormat.swift in Sources */,
|
||||||
E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */,
|
E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */,
|
||||||
53ABFDE9267974EF00886593 /* HomeViewModel.swift in Sources */,
|
53ABFDE9267974EF00886593 /* HomeViewModel.swift in Sources */,
|
||||||
|
@ -6890,6 +6897,7 @@
|
||||||
4E35CE662CBED8B600DBD886 /* ServerTicks.swift in Sources */,
|
4E35CE662CBED8B600DBD886 /* ServerTicks.swift in Sources */,
|
||||||
E1D3043528D1763100587289 /* SeeAllButton.swift in Sources */,
|
E1D3043528D1763100587289 /* SeeAllButton.swift in Sources */,
|
||||||
4E73E2A62C41CFD3002D2A78 /* PlaybackBitrateTestSize.swift in Sources */,
|
4E73E2A62C41CFD3002D2A78 /* PlaybackBitrateTestSize.swift in Sources */,
|
||||||
|
4E5EE5512D67CE9500982290 /* ImageCard.swift in Sources */,
|
||||||
E172D3B22BACA569007B4647 /* EpisodeContent.swift in Sources */,
|
E172D3B22BACA569007B4647 /* EpisodeContent.swift in Sources */,
|
||||||
4E1A39342D56C84200BAC1C7 /* ItemViewAttributes.swift in Sources */,
|
4E1A39342D56C84200BAC1C7 /* ItemViewAttributes.swift in Sources */,
|
||||||
4EC1C8522C7FDFA300E2879E /* PlaybackDeviceProfile.swift in Sources */,
|
4EC1C8522C7FDFA300E2879E /* PlaybackDeviceProfile.swift in Sources */,
|
||||||
|
|
|
@ -106,22 +106,6 @@ extension ItemView {
|
||||||
return CGSize(width: width, height: height)
|
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 {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
L10n.about.text
|
L10n.about.text
|
||||||
|
@ -136,7 +120,8 @@ extension ItemView {
|
||||||
) { item in
|
) { item in
|
||||||
switch item {
|
switch item {
|
||||||
case .image:
|
case .image:
|
||||||
imageView
|
ImageCard(viewModel: viewModel)
|
||||||
|
.frame(width: UIDevice.isPad ? padImageWidth : phoneImageWidth)
|
||||||
case .overview:
|
case .overview:
|
||||||
OverviewCard(item: viewModel.item)
|
OverviewCard(item: viewModel.item)
|
||||||
.frame(width: cardSize.width, height: cardSize.height)
|
.frame(width: cardSize.width, height: cardSize.height)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,21 +78,6 @@ extension EpisodeItemView {
|
||||||
RowDivider()
|
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)
|
ItemView.AboutView(viewModel: viewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,19 +48,6 @@ extension iPadOSEpisodeItemView {
|
||||||
RowDivider()
|
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)
|
ItemView.AboutView(viewModel: viewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue