Refactor ItemViews
This commit is contained in:
parent
6d32db6751
commit
4ec0f962b2
@ -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 */,
|
||||||
|
28
Jel/Controllers/UIScreenCurrent.swift
Normal file
28
Jel/Controllers/UIScreenCurrent.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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())
|
||||||
}
|
//}
|
||||||
|
@ -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 {
|
||||||
|
@ -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")
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
Loading…
Reference in New Issue
Block a user