Refactor ItemViews

This commit is contained in:
Shav Kinderlehrer 2024-01-08 14:00:59 -05:00
parent 6d32db6751
commit 4ec0f962b2
7 changed files with 103 additions and 89 deletions

View File

@ -41,6 +41,7 @@
3DAFA8EC2B394F9F00D71AD1 /* ViewConditionalMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8EB2B394F9F00D71AD1 /* ViewConditionalMethod.swift */; }; 3DAFA8EC2B394F9F00D71AD1 /* ViewConditionalMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8EB2B394F9F00D71AD1 /* ViewConditionalMethod.swift */; };
3DAFA8EF2B3B707B00D71AD1 /* ItemMovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8EE2B3B707B00D71AD1 /* ItemMovieView.swift */; }; 3DAFA8EF2B3B707B00D71AD1 /* ItemMovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8EE2B3B707B00D71AD1 /* ItemMovieView.swift */; };
3DBAC9E22B4C31BE005F8764 /* ItemPeopleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBAC9E12B4C31BE005F8764 /* ItemPeopleView.swift */; }; 3DBAC9E22B4C31BE005F8764 /* ItemPeopleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBAC9E12B4C31BE005F8764 /* ItemPeopleView.swift */; };
3DBAC9E42B4C7404005F8764 /* UIScreenCurrent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBAC9E32B4C7404005F8764 /* UIScreenCurrent.swift */; };
3DC6BA2D2B2A422300416B9F /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC6BA2C2B2A422300416B9F /* SettingsController.swift */; }; 3DC6BA2D2B2A422300416B9F /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC6BA2C2B2A422300416B9F /* SettingsController.swift */; };
3DDD67932B293BC40026781E /* DashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67922B293BC40026781E /* DashboardView.swift */; }; 3DDD67932B293BC40026781E /* DashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67922B293BC40026781E /* DashboardView.swift */; };
3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67952B29E28B0026781E /* SettingsView.swift */; }; 3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67952B29E28B0026781E /* SettingsView.swift */; };
@ -111,6 +112,7 @@
3DAFA8EB2B394F9F00D71AD1 /* ViewConditionalMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewConditionalMethod.swift; sourceTree = "<group>"; }; 3DAFA8EB2B394F9F00D71AD1 /* ViewConditionalMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewConditionalMethod.swift; sourceTree = "<group>"; };
3DAFA8EE2B3B707B00D71AD1 /* ItemMovieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemMovieView.swift; sourceTree = "<group>"; }; 3DAFA8EE2B3B707B00D71AD1 /* ItemMovieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemMovieView.swift; sourceTree = "<group>"; };
3DBAC9E12B4C31BE005F8764 /* ItemPeopleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPeopleView.swift; sourceTree = "<group>"; }; 3DBAC9E12B4C31BE005F8764 /* ItemPeopleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPeopleView.swift; sourceTree = "<group>"; };
3DBAC9E32B4C7404005F8764 /* UIScreenCurrent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIScreenCurrent.swift; sourceTree = "<group>"; };
3DC0E5802B2832B9001CCE96 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 3DC0E5802B2832B9001CCE96 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3DC6BA2C2B2A422300416B9F /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; }; 3DC6BA2C2B2A422300416B9F /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
3DDD67922B293BC40026781E /* DashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = "<group>"; }; 3DDD67922B293BC40026781E /* DashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = "<group>"; };
@ -168,6 +170,7 @@
3D1015E32B28000E00F5C29A /* AuthStateController.swift */, 3D1015E32B28000E00F5C29A /* AuthStateController.swift */,
3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */, 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */,
3DC6BA2C2B2A422300416B9F /* SettingsController.swift */, 3DC6BA2C2B2A422300416B9F /* SettingsController.swift */,
3DBAC9E32B4C7404005F8764 /* UIScreenCurrent.swift */,
); );
path = Controllers; path = Controllers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -466,6 +469,7 @@
3D3816C92B4B5648006414D7 /* ItemGenresView.swift in Sources */, 3D3816C92B4B5648006414D7 /* ItemGenresView.swift in Sources */,
3DAFA8EC2B394F9F00D71AD1 /* ViewConditionalMethod.swift in Sources */, 3DAFA8EC2B394F9F00D71AD1 /* ViewConditionalMethod.swift in Sources */,
3D9063CB2B279A310063DD2A /* JelApp.swift in Sources */, 3D9063CB2B279A310063DD2A /* JelApp.swift in Sources */,
3DBAC9E42B4C7404005F8764 /* UIScreenCurrent.swift in Sources */,
3D13F9692B389FA300E91913 /* ViewOffsetKey.swift in Sources */, 3D13F9692B389FA300E91913 /* ViewOffsetKey.swift in Sources */,
3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */, 3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */,
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */, 3D91FDC92B28C62800919017 /* SignInView.swift in Sources */,

View File

@ -0,0 +1,28 @@
//
// UIScreenCurrent.swift
// Jel
//
// Created by zerocool on 1/8/24.
//
import Foundation
import SwiftUI
extension UIWindow {
static var current: UIWindow? {
for scene in UIApplication.shared.connectedScenes {
guard let windowScene = scene as? UIWindowScene else { continue }
for window in windowScene.windows {
if window.isKeyWindow { return window }
}
}
return nil
}
}
extension UIScreen {
static var current: UIScreen? {
UIWindow.current?.screen
}
}

View File

@ -22,11 +22,10 @@ struct ItemHeaderView: View {
var body: some View { var body: some View {
ZStack(alignment: .bottom) { ZStack(alignment: .bottom) {
StickyHeaderView(minHeight: 300) { StickyHeaderView(minHeight: 400) {
ItemIconView(item: item, imageType: "Backdrop", contentMode: .fill) ItemIconView(item: item, imageType: "Backdrop", contentMode: .fill)
.setCornerRadius(0) .setCornerRadius(0)
.overlay(overlayGradient.opacity(0.8)) .overlay(overlayGradient.opacity(0.8))
.mask(overlayGradientMask)
} }
HStack { HStack {
@ -39,12 +38,12 @@ struct ItemHeaderView: View {
} }
.padding([.leading, .trailing]) .padding([.leading, .trailing])
} }
.scrollTransition {content, phase in // .scrollTransition {content, phase in
content // content
.scaleEffect(phase.isIdentity ? 1 : 2) // .scaleEffect(phase.isIdentity ? 1 : 2)
.opacity(phase.isIdentity ? 1 : 0.1) // .opacity(phase.isIdentity ? 1 : 0.1)
.blur(radius: phase.isIdentity ? 0 : 50) // .blur(radius: phase.isIdentity ? 0 : 50)
} // }
} }
} }

View File

@ -9,68 +9,24 @@ import SwiftUI
import JellyfinKit import JellyfinKit
import VisibilityTrackingScrollView import VisibilityTrackingScrollView
struct ItemMediaView<Content: View>: View { struct ItemMediaView: View {
@EnvironmentObject var jellyfinClient: JellyfinClientController @EnvironmentObject var jellyfinClient: JellyfinClientController
@StateObject var authState: AuthStateController = AuthStateController.shared @StateObject var authState: AuthStateController = AuthStateController.shared
@State var item: BaseItemDto var item: BaseItemDto
@ViewBuilder var playButton: () -> Content
@State var pageScrolled: Bool = false
var body: some View { var body: some View {
GeometryReader {geo in VStack(alignment: .leading) {
ScrollView() { Text(item.taglines?.count ?? 0 > 0 ? item.taglines?[0] ?? "" : "")
ItemHeaderView(item: item) .font(.headline)
.padding(.bottom) .frame(maxWidth: .infinity, alignment: .leading)
.background { .padding(.bottom)
GeometryReader {geo in
EmptyView() ForEach(item.overview?.components(separatedBy: "<br>") ?? [], id: \.self) {overview in
.onChange(of: geo.frame(in: .global).minY) { Text(overview)
let minY = geo.frame(in: .global).minY
pageScrolled = minY < 0
}
}
}
playButton()
VStack(alignment: .leading) {
Text(item.taglines?.count ?? 0 > 0 ? item.taglines?[0] ?? "" : "")
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom)
ForEach(item.overview?.components(separatedBy: "<br>") ?? [], id: \.self) {overview in
Text(overview)
}
ItemGenresView(item: item)
.padding(.vertical)
}
.if(max(geo.safeAreaInsets.leading, geo.safeAreaInsets.trailing) > 0) {view in
view
.padding(max(geo.safeAreaInsets.leading, geo.safeAreaInsets.trailing))
}
.if(max(geo.safeAreaInsets.leading, geo.safeAreaInsets.trailing) <= 0) {view in
view
.padding()
}
}
.ignoresSafeArea()
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(item.name ?? "Untitled")
.toolbarRole(.editor)
.toolbar {
ToolbarItem(placement: .principal) {
Text(pageScrolled ? item.name ?? "Untitled" : "")
.bold()
} }
} }
.scrollIndicators(.hidden)
} }
} }

View File

@ -10,18 +10,20 @@ import JellyfinKit
struct ItemView: View { struct ItemView: View {
@State var item: BaseItemDto @State var item: BaseItemDto
var body: some View { var body: some View {
switch item.type { ScrollView {
case .movie: VStack {
ItemMovieView(item: item) switch item.type {
default: case .movie:
ItemMediaView(item: item) { ItemMovieView(item: item)
EmptyView() default:
} ItemMediaView(item: item)
}
} }
} }
}
} }
#Preview { //#Preview {
ItemView(item: BaseItemDto()) // ItemView(item: BaseItemDto())
} //}

View File

@ -11,19 +11,43 @@ import JellyfinKit
struct ItemMovieView: View { struct ItemMovieView: View {
var item: BaseItemDto var item: BaseItemDto
var body: some View { @State var pageScrolled: Bool = false
VStack {
ItemMediaView(item: item) { var body: some View {
Button("Play") { VStack {
ItemHeaderView(item: item)
.foregroundStyle(.white)
.background {
GeometryReader {geo in
EmptyView()
.onChange(of: geo.frame(in: .global).minY) {
let minY = geo.frame(in: .global).minY
pageScrolled = minY < 0
}
} }
.buttonStyle(.borderedProminent)
} }
ItemPeopleView(item: item) ItemMediaView(item: item)
} .padding()
.padding()
ItemGenresView(item: item)
.padding()
ItemPeopleView(item: item)
.padding()
} }
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(item.name ?? "Untitled")
.toolbarRole(.editor)
.toolbar {
ToolbarItem(placement: .principal) {
Text(pageScrolled ? item.name ?? "Untitled" : "")
.bold()
}
}
.toolbarBackground(pageScrolled ? .visible : .hidden)
}
} }
//#Preview { //#Preview {

View File

@ -27,12 +27,13 @@ struct StickyHeaderView<Content: View>: View {
.offset(y: -geo.frame(in: .global).minY) .offset(y: -geo.frame(in: .global).minY)
.frame(width: geo.size.width, height: geo.size.height + geo.frame(in: .global).minY) .frame(width: geo.size.width, height: geo.size.height + geo.frame(in: .global).minY)
} }
}.frame(minHeight: minHeight) }
.frame(minWidth: UIScreen.current?.bounds.width ?? 200, minHeight: minHeight)
} }
} }
#Preview { //#Preview {
StickyHeaderView { // StickyHeaderView {
Text("Test") // Text("Test")
} // }
} //}