Some work

This commit is contained in:
Ethan Pippin 2021-08-30 11:09:26 -06:00
parent f9114ae6be
commit b349258086
5 changed files with 92 additions and 87 deletions

View File

@ -993,8 +993,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
535BAE9E2649E569005FA86D /* ItemView.swift */, 535BAE9E2649E569005FA86D /* ItemView.swift */,
E14F7D0626DB36EF007C3AE6 /* ItemPortraitBodyView.swift */,
E14F7D0826DB36F7007C3AE6 /* ItemLandscapeBodyView.swift */, E14F7D0826DB36F7007C3AE6 /* ItemLandscapeBodyView.swift */,
E14F7D0626DB36EF007C3AE6 /* ItemPortraitBodyView.swift */,
E1AD106126D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift */, E1AD106126D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift */,
); );
path = ItemView; path = ItemView;

View File

@ -12,16 +12,16 @@ import JellyfinAPI
struct ItemPortraitBodyView<PortraitHeaderView: View, PortraitStaticOverlayView: View>: View { struct ItemPortraitBodyView<PortraitHeaderView: View, PortraitStaticOverlayView: View>: View {
@Binding var videoIsLoading: Bool @Binding private var videoIsLoading: Bool
@EnvironmentObject var viewModel: MovieItemViewModel @EnvironmentObject private var viewModel: DetailItemViewModel
@EnvironmentObject var videoPlayerItem: VideoPlayerItem @EnvironmentObject private var videoPlayerItem: VideoPlayerItem
private let item: BaseItemDto private let portraitHeaderView: (DetailItemViewModel) -> PortraitHeaderView
private let portraitHeaderView: (BaseItemDto) -> PortraitHeaderView private let portraitStaticOverlayView: (DetailItemViewModel) -> PortraitStaticOverlayView
private let portraitStaticOverlayView: (BaseItemDto) -> PortraitStaticOverlayView
init(item: BaseItemDto, videoIsLoading: Binding<Bool>, portraitHeaderView: @escaping (BaseItemDto) -> PortraitHeaderView, portraitStaticOverlayView: @escaping (BaseItemDto) -> PortraitStaticOverlayView) { init(videoIsLoading: Binding<Bool>,
self.item = item portraitHeaderView: @escaping (DetailItemViewModel) -> PortraitHeaderView,
portraitStaticOverlayView: @escaping (DetailItemViewModel) -> PortraitStaticOverlayView) {
self._videoIsLoading = videoIsLoading self._videoIsLoading = videoIsLoading
self.portraitHeaderView = portraitHeaderView self.portraitHeaderView = portraitHeaderView
self.portraitStaticOverlayView = portraitStaticOverlayView self.portraitStaticOverlayView = portraitStaticOverlayView
@ -43,8 +43,8 @@ struct ItemPortraitBodyView<PortraitHeaderView: View, PortraitStaticOverlayView:
} }
// MARK: Body // MARK: Body
ParallaxHeaderScrollView(header: portraitHeaderView(item), ParallaxHeaderScrollView(header: portraitHeaderView(viewModel),
staticOverlayView: portraitStaticOverlayView(item), staticOverlayView: portraitStaticOverlayView(viewModel),
overlayAlignment: .bottomLeading, overlayAlignment: .bottomLeading,
headerHeight: UIDevice.current.userInterfaceIdiom == .pad ? 350 : UIScreen.main.bounds.width * 0.5625) { headerHeight: UIDevice.current.userInterfaceIdiom == .pad ? 350 : UIScreen.main.bounds.width * 0.5625) {
VStack { VStack {
@ -53,7 +53,7 @@ struct ItemPortraitBodyView<PortraitHeaderView: View, PortraitStaticOverlayView:
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 54 : 24) .padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 54 : 24)
// MARK: Overview // MARK: Overview
Text(item.overview ?? "") Text(viewModel.item.overview ?? "")
.font(.footnote) .font(.footnote)
.padding(.top, 3) .padding(.top, 3)
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
@ -63,12 +63,12 @@ struct ItemPortraitBodyView<PortraitHeaderView: View, PortraitStaticOverlayView:
// MARK: Genres // MARK: Genres
PillHStackView(title: "Genres", PillHStackView(title: "Genres",
items: item.genreItems ?? []) { genre in items: viewModel.item.genreItems ?? []) { genre in
LibraryView(viewModel: .init(genre: genre), title: genre.title) LibraryView(viewModel: .init(genre: genre), title: genre.title)
} }
// MARK: Studios // MARK: Studios
if let studios = item.studios { if let studios = viewModel.item.studios {
PillHStackView(title: "Studios", PillHStackView(title: "Studios",
items: studios) { studio in items: studios) { studio in
LibraryView(viewModel: .init(studio: studio), title: studio.name ?? "") LibraryView(viewModel: .init(studio: studio), title: studio.name ?? "")
@ -76,7 +76,7 @@ struct ItemPortraitBodyView<PortraitHeaderView: View, PortraitStaticOverlayView:
} }
// MARK: Cast // MARK: Cast
PortraitImageHStackView(items: item.people?.filter({ $0.type == "Actor" }) ?? [], PortraitImageHStackView(items: viewModel.item.people?.filter({ $0.type == "Actor" }) ?? [],
maxWidth: 150) { maxWidth: 150) {
Text("Cast") Text("Cast")
.font(.callout) .font(.callout)

View File

@ -15,26 +15,24 @@ struct PortraitHeaderOverlayView: View {
@EnvironmentObject private var viewModel: DetailItemViewModel @EnvironmentObject private var viewModel: DetailItemViewModel
@EnvironmentObject private var videoPlayerItem: VideoPlayerItem @EnvironmentObject private var videoPlayerItem: VideoPlayerItem
let item: BaseItemDto
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack(alignment: .bottom, spacing: 12) { HStack(alignment: .bottom, spacing: 12) {
ImageView(src: item.portraitHeaderViewURL(maxWidth: 130)) ImageView(src: viewModel.item.portraitHeaderViewURL(maxWidth: 130))
.frame(width: 130, height: 195) .frame(width: 130, height: 195)
.cornerRadius(10) .cornerRadius(10)
VStack(alignment: .leading, spacing: 1) { VStack(alignment: .leading, spacing: 1) {
Spacer() Spacer()
Text(item.name ?? "") Text(viewModel.item.name ?? "")
.font(.headline) .font(.headline)
.fontWeight(.semibold) .fontWeight(.semibold)
.foregroundColor(.primary) .foregroundColor(.primary)
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
.offset(y: 5) .offset(y: 5)
Text(item.getItemRuntime()) Text(viewModel.item.getItemRuntime())
.font(.subheadline) .font(.subheadline)
.fontWeight(.medium) .fontWeight(.medium)
.foregroundColor(.secondary) .foregroundColor(.secondary)
@ -42,7 +40,7 @@ struct PortraitHeaderOverlayView: View {
.padding(.top, 10) .padding(.top, 10)
HStack { HStack {
if let productionYear = item.productionYear { if let productionYear = viewModel.item.productionYear {
Text(String(productionYear)) Text(String(productionYear))
.font(.subheadline) .font(.subheadline)
.fontWeight(.medium) .fontWeight(.medium)
@ -50,7 +48,7 @@ struct PortraitHeaderOverlayView: View {
.lineLimit(1) .lineLimit(1)
} }
if let officialRating = item.officialRating { if let officialRating = viewModel.item.officialRating {
Text(officialRating) Text(officialRating)
.font(.subheadline) .font(.subheadline)
.fontWeight(.semibold) .fontWeight(.semibold)
@ -65,18 +63,19 @@ struct PortraitHeaderOverlayView: View {
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 98 : 30) .padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? 98 : 30)
} }
if viewModel.item.itemType != .series {
HStack { HStack {
// MARK: Play // MARK: Play
Button { Button {
self.videoPlayerItem.itemToPlay = item self.videoPlayerItem.itemToPlay = viewModel.item
self.videoPlayerItem.shouldShowPlayer = true self.videoPlayerItem.shouldShowPlayer = true
} label: { } label: {
HStack { HStack {
Image(systemName: "play.fill") Image(systemName: "play.fill")
.foregroundColor(Color.white) .foregroundColor(Color.white)
.font(.system(size: 20)) .font(.system(size: 20))
Text(item.getItemProgressString() == "" ? "Play" : item.getItemProgressString()) Text(viewModel.item.getItemProgressString() == "" ? "Play" : viewModel.item.getItemProgressString())
.foregroundColor(Color.white) .foregroundColor(Color.white)
.font(.callout) .font(.callout)
.fontWeight(.semibold) .fontWeight(.semibold)
@ -121,6 +120,7 @@ struct PortraitHeaderOverlayView: View {
.disabled(viewModel.isLoading) .disabled(viewModel.isLoading)
}.padding(.top, 8) }.padding(.top, 8)
} }
}
.padding(.horizontal, 16) .padding(.horizontal, 16)
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? -189 : -64) .padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? -189 : -64)
} }

View File

@ -23,26 +23,27 @@ struct ItemView: View {
@Environment(\.horizontalSizeClass) var hSizeClass @Environment(\.horizontalSizeClass) var hSizeClass
@Environment(\.verticalSizeClass) var vSizeClass @Environment(\.verticalSizeClass) var vSizeClass
private let item: BaseItemDto private let viewModel: DetailItemViewModel
init(item: BaseItemDto) { init(item: BaseItemDto) {
self.item = item self.viewModel = DetailItemViewModel(item: item)
} }
var body: some View { var body: some View {
if hSizeClass == .compact && vSizeClass == .regular { if hSizeClass == .compact && vSizeClass == .regular {
ItemPortraitBodyView(item: item, ItemPortraitBodyView(videoIsLoading: $videoIsLoading,
videoIsLoading: $videoIsLoading, portraitHeaderView: { viewModel in
portraitHeaderView: { item in ImageView(src: viewModel.item.getBackdropImage(maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 622 : Int(UIScreen.main.bounds.width)),
ImageView(src: item.getBackdropImage(maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 622 : Int(UIScreen.main.bounds.width)), bh: viewModel.item.getBackdropImageBlurHash())
bh: item.getBackdropImageBlurHash())
.opacity(0.4) .opacity(0.4)
.blur(radius: 2.0) .blur(radius: 2.0)
}, },
portraitStaticOverlayView: { item in portraitStaticOverlayView: { viewModel in
PortraitHeaderOverlayView(item: item) PortraitHeaderOverlayView()
.environmentObject(DetailItemViewModel(item: item)) .environmentObject(viewModel)
}).environmentObject(videoPlayerItem) })
.environmentObject(videoPlayerItem)
.environmentObject(viewModel)
} else { } else {
Text("Hello there") Text("Hello there")
} }

View File

@ -11,7 +11,7 @@ import Foundation
import Foundation import Foundation
import JellyfinAPI import JellyfinAPI
class DetailItemViewModel: ViewModel { class ItemViewModel: ViewModel {
@Published var item: BaseItemDto @Published var item: BaseItemDto
@Published var similarItems: [BaseItemDto] = [] @Published var similarItems: [BaseItemDto] = []
@ -83,3 +83,7 @@ class DetailItemViewModel: ViewModel {
} }
} }
} }
class DetailItemViewModel: ItemViewModel {
}