Implement movieDetailView
This commit is contained in:
parent
9da269a6ab
commit
69bed77458
@ -14,6 +14,8 @@
|
|||||||
3D13F95F2B375DB800E91913 /* ItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F95E2B375DB800E91913 /* ItemView.swift */; };
|
3D13F95F2B375DB800E91913 /* ItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F95E2B375DB800E91913 /* ItemView.swift */; };
|
||||||
3D13F9612B37637500E91913 /* ItemMovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F9602B37637500E91913 /* ItemMovieView.swift */; };
|
3D13F9612B37637500E91913 /* ItemMovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F9602B37637500E91913 /* ItemMovieView.swift */; };
|
||||||
3D13F9652B37EC7A00E91913 /* ItemHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F9642B37EC7A00E91913 /* ItemHeaderView.swift */; };
|
3D13F9652B37EC7A00E91913 /* ItemHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F9642B37EC7A00E91913 /* ItemHeaderView.swift */; };
|
||||||
|
3D13F9692B389FA300E91913 /* ViewOffsetKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F9682B389FA300E91913 /* ViewOffsetKey.swift */; };
|
||||||
|
3D13F96F2B38A32500E91913 /* StickyHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F96E2B38A32500E91913 /* StickyHeaderView.swift */; };
|
||||||
3D16FC3C2B2CDFB500E6D8B3 /* DashboardLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D16FC3B2B2CDFB500E6D8B3 /* DashboardLibraryView.swift */; };
|
3D16FC3C2B2CDFB500E6D8B3 /* DashboardLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D16FC3B2B2CDFB500E6D8B3 /* DashboardLibraryView.swift */; };
|
||||||
3D41D1F52B2C962500E58234 /* AppearancePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D41D1F42B2C962500E58234 /* AppearancePicker.swift */; };
|
3D41D1F52B2C962500E58234 /* AppearancePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D41D1F42B2C962500E58234 /* AppearancePicker.swift */; };
|
||||||
3D41D1FA2B2CAE0000E58234 /* LibraryIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D41D1F92B2CAE0000E58234 /* LibraryIconView.swift */; };
|
3D41D1FA2B2CAE0000E58234 /* LibraryIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D41D1F92B2CAE0000E58234 /* LibraryIconView.swift */; };
|
||||||
@ -32,6 +34,8 @@
|
|||||||
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDC82B28C62800919017 /* SignInView.swift */; };
|
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDC82B28C62800919017 /* SignInView.swift */; };
|
||||||
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */; };
|
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */; };
|
||||||
3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */; };
|
3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */; };
|
||||||
|
3DAFA8E82B38AFED00D71AD1 /* ItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */; };
|
||||||
|
3DAFA8EA2B39039900D71AD1 /* JellyfinKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8E92B39039900D71AD1 /* JellyfinKitExtensions.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 */; };
|
||||||
@ -75,6 +79,8 @@
|
|||||||
3D13F95E2B375DB800E91913 /* ItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemView.swift; sourceTree = "<group>"; };
|
3D13F95E2B375DB800E91913 /* ItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemView.swift; sourceTree = "<group>"; };
|
||||||
3D13F9602B37637500E91913 /* ItemMovieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemMovieView.swift; sourceTree = "<group>"; };
|
3D13F9602B37637500E91913 /* ItemMovieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemMovieView.swift; sourceTree = "<group>"; };
|
||||||
3D13F9642B37EC7A00E91913 /* ItemHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemHeaderView.swift; sourceTree = "<group>"; };
|
3D13F9642B37EC7A00E91913 /* ItemHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemHeaderView.swift; sourceTree = "<group>"; };
|
||||||
|
3D13F9682B389FA300E91913 /* ViewOffsetKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewOffsetKey.swift; sourceTree = "<group>"; };
|
||||||
|
3D13F96E2B38A32500E91913 /* StickyHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickyHeaderView.swift; sourceTree = "<group>"; };
|
||||||
3D16FC3B2B2CDFB500E6D8B3 /* DashboardLibraryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardLibraryView.swift; sourceTree = "<group>"; };
|
3D16FC3B2B2CDFB500E6D8B3 /* DashboardLibraryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardLibraryView.swift; sourceTree = "<group>"; };
|
||||||
3D41D1F42B2C962500E58234 /* AppearancePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePicker.swift; sourceTree = "<group>"; };
|
3D41D1F42B2C962500E58234 /* AppearancePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePicker.swift; sourceTree = "<group>"; };
|
||||||
3D41D1F92B2CAE0000E58234 /* LibraryIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryIconView.swift; sourceTree = "<group>"; };
|
3D41D1F92B2CAE0000E58234 /* LibraryIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryIconView.swift; sourceTree = "<group>"; };
|
||||||
@ -94,6 +100,8 @@
|
|||||||
3D91FDC82B28C62800919017 /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
3D91FDC82B28C62800919017 /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
||||||
3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInToServerView.swift; sourceTree = "<group>"; };
|
3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInToServerView.swift; sourceTree = "<group>"; };
|
||||||
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinDateFormatter.swift; sourceTree = "<group>"; };
|
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinDateFormatter.swift; sourceTree = "<group>"; };
|
||||||
|
3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemInfoView.swift; sourceTree = "<group>"; };
|
||||||
|
3DAFA8E92B39039900D71AD1 /* JellyfinKitExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinKitExtensions.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>"; };
|
||||||
@ -134,6 +142,7 @@
|
|||||||
3D1015D72B27F54A00F5C29A /* Views */ = {
|
3D1015D72B27F54A00F5C29A /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3D13F96D2B38A31300E91913 /* Utility */,
|
||||||
3D9063CC2B279A310063DD2A /* ContentView.swift */,
|
3D9063CC2B279A310063DD2A /* ContentView.swift */,
|
||||||
3DDD67902B293B780026781E /* Dashboard */,
|
3DDD67902B293B780026781E /* Dashboard */,
|
||||||
3D8AB2A62B366309005BD7D0 /* Library */,
|
3D8AB2A62B366309005BD7D0 /* Library */,
|
||||||
@ -158,6 +167,8 @@
|
|||||||
children = (
|
children = (
|
||||||
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */,
|
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */,
|
||||||
3D8AB2A42B36440D005BD7D0 /* BlurHashDecode.swift */,
|
3D8AB2A42B36440D005BD7D0 /* BlurHashDecode.swift */,
|
||||||
|
3D13F9682B389FA300E91913 /* ViewOffsetKey.swift */,
|
||||||
|
3DAFA8E92B39039900D71AD1 /* JellyfinKitExtensions.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -167,11 +178,20 @@
|
|||||||
children = (
|
children = (
|
||||||
3D13F95E2B375DB800E91913 /* ItemView.swift */,
|
3D13F95E2B375DB800E91913 /* ItemView.swift */,
|
||||||
3D13F9602B37637500E91913 /* ItemMovieView.swift */,
|
3D13F9602B37637500E91913 /* ItemMovieView.swift */,
|
||||||
|
3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */,
|
||||||
3D13F9642B37EC7A00E91913 /* ItemHeaderView.swift */,
|
3D13F9642B37EC7A00E91913 /* ItemHeaderView.swift */,
|
||||||
);
|
);
|
||||||
path = Item;
|
path = Item;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3D13F96D2B38A31300E91913 /* Utility */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3D13F96E2B38A32500E91913 /* StickyHeaderView.swift */,
|
||||||
|
);
|
||||||
|
path = Utility;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
3D8AB2A62B366309005BD7D0 /* Library */ = {
|
3D8AB2A62B366309005BD7D0 /* Library */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -414,10 +434,13 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
3D9063CD2B279A310063DD2A /* ContentView.swift in Sources */,
|
3D9063CD2B279A310063DD2A /* ContentView.swift in Sources */,
|
||||||
|
3D13F96F2B38A32500E91913 /* StickyHeaderView.swift in Sources */,
|
||||||
3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */,
|
3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */,
|
||||||
3D1015D92B27F57400F5C29A /* AddServerView.swift in Sources */,
|
3D1015D92B27F57400F5C29A /* AddServerView.swift in Sources */,
|
||||||
|
3DAFA8EA2B39039900D71AD1 /* JellyfinKitExtensions.swift in Sources */,
|
||||||
3D13F9652B37EC7A00E91913 /* ItemHeaderView.swift in Sources */,
|
3D13F9652B37EC7A00E91913 /* ItemHeaderView.swift in Sources */,
|
||||||
3D9063CB2B279A310063DD2A /* JelApp.swift in Sources */,
|
3D9063CB2B279A310063DD2A /* JelApp.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 */,
|
||||||
3D8AB2A82B366353005BD7D0 /* LibraryDetailView.swift in Sources */,
|
3D8AB2A82B366353005BD7D0 /* LibraryDetailView.swift in Sources */,
|
||||||
@ -426,6 +449,7 @@
|
|||||||
3D41D1FA2B2CAE0000E58234 /* LibraryIconView.swift in Sources */,
|
3D41D1FA2B2CAE0000E58234 /* LibraryIconView.swift in Sources */,
|
||||||
3D8AB2A52B36440D005BD7D0 /* BlurHashDecode.swift in Sources */,
|
3D8AB2A52B36440D005BD7D0 /* BlurHashDecode.swift in Sources */,
|
||||||
3DC6BA2D2B2A422300416B9F /* SettingsController.swift in Sources */,
|
3DC6BA2D2B2A422300416B9F /* SettingsController.swift in Sources */,
|
||||||
|
3DAFA8E82B38AFED00D71AD1 /* ItemInfoView.swift in Sources */,
|
||||||
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */,
|
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */,
|
||||||
3D16FC3C2B2CDFB500E6D8B3 /* DashboardLibraryView.swift in Sources */,
|
3D16FC3C2B2CDFB500E6D8B3 /* DashboardLibraryView.swift in Sources */,
|
||||||
3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */,
|
3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */,
|
||||||
|
28
Jel/Models/JellyfinKitExtensions.swift
Normal file
28
Jel/Models/JellyfinKitExtensions.swift
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// JellyfinKitExtensions.swift
|
||||||
|
// Jel
|
||||||
|
//
|
||||||
|
// Created by zerocool on 12/24/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import JellyfinKit
|
||||||
|
|
||||||
|
extension BaseItemDto {
|
||||||
|
func getRuntime() -> String? {
|
||||||
|
let formatter: DateComponentsFormatter = {
|
||||||
|
let localFormatter = DateComponentsFormatter()
|
||||||
|
localFormatter.unitsStyle = .brief
|
||||||
|
localFormatter.allowedUnits = [.hour, .minute]
|
||||||
|
|
||||||
|
return localFormatter
|
||||||
|
}()
|
||||||
|
|
||||||
|
if let runTimeTicks = self.runTimeTicks {
|
||||||
|
let text = formatter.string(from: Double(runTimeTicks / 10_000_000))
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
17
Jel/Models/ViewOffsetKey.swift
Normal file
17
Jel/Models/ViewOffsetKey.swift
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// ViewOffsetKey.swift
|
||||||
|
// Jel
|
||||||
|
//
|
||||||
|
// Created by zerocool on 12/24/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
/// A preference key to store ScrollView offset
|
||||||
|
public struct ViewOffsetKey: PreferenceKey {
|
||||||
|
public typealias Value = CGFloat
|
||||||
|
public static var defaultValue = CGFloat.zero
|
||||||
|
public static func reduce(value: inout Value, nextValue: () -> Value) {
|
||||||
|
value += nextValue()
|
||||||
|
}
|
||||||
|
}
|
@ -13,35 +13,43 @@ struct ItemHeaderView: View {
|
|||||||
|
|
||||||
let overlayGradient = LinearGradient(gradient: Gradient(stops: [
|
let overlayGradient = LinearGradient(gradient: Gradient(stops: [
|
||||||
.init(color: .clear, location: 0),
|
.init(color: .clear, location: 0),
|
||||||
.init(color: .black, location: 0.3),
|
.init(color: .black, location: 0.5),
|
||||||
.init(color: .black, location: 0.7),
|
// .init(color: .black, location: 0.7),
|
||||||
|
// .init(color: .clear, location: 1)
|
||||||
.init(color: .clear, location: 1)
|
|
||||||
]), startPoint: .bottom, endPoint: .top)
|
]), startPoint: .bottom, endPoint: .top)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .bottom) {
|
ZStack(alignment: .bottom) {
|
||||||
|
StickyHeaderView(minHeight: 300) {
|
||||||
LibraryIconView(library: item, imageType: "Backdrop", contentMode: .fill)
|
LibraryIconView(library: item, imageType: "Backdrop", contentMode: .fill)
|
||||||
.hideCaption()
|
.hideCaption()
|
||||||
.setCornerRadius(0)
|
.setCornerRadius(0)
|
||||||
.mask(overlayGradient)
|
.mask(overlayGradient)
|
||||||
// .padding(.top, 50)
|
|
||||||
.background {
|
.background {
|
||||||
LibraryIconView(library: item, imageType: "Backdrop", contentMode: .fill)
|
LibraryIconView(library: item, imageType: "Backdrop", contentMode: .fill)
|
||||||
.hideCaption()
|
.hideCaption()
|
||||||
.setCornerRadius(0)
|
.setCornerRadius(0)
|
||||||
.blur(radius: 50)
|
.blur(radius: 50)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
LibraryIconView(library: item, imageType: "Logo", width: 200, height: 100, placeHolder: AnyView(Text(item.name ?? "Unknown").font(.title).bold().truncationMode(.middle)))
|
LibraryIconView(library: item, imageType: "Logo", width: 200, height: 100, placeHolder: AnyView(Text(item.name ?? "Unknown").font(.title).bold().truncationMode(.middle)))
|
||||||
.hideCaption()
|
.hideCaption()
|
||||||
.setCornerRadius(0)
|
.setCornerRadius(0)
|
||||||
.shadow(radius: 10)
|
.shadow(radius: 10)
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.frame(alignment: .leading)
|
.frame(alignment: .leading)
|
||||||
.padding(.leading)
|
Spacer()
|
||||||
|
ItemInfoView(item: item)
|
||||||
|
.foregroundStyle(.white)
|
||||||
|
}
|
||||||
|
.padding([.leading, .trailing])
|
||||||
|
}
|
||||||
|
.scrollTransition {content, phase in
|
||||||
|
content
|
||||||
|
.scaleEffect(phase.isIdentity ? 1 : 2)
|
||||||
|
.opacity(phase.isIdentity ? 1 : 0.1)
|
||||||
|
.blur(radius: phase.isIdentity ? 0 : 50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
Jel/Views/Library/Item/ItemInfoView.swift
Normal file
29
Jel/Views/Library/Item/ItemInfoView.swift
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// ItemInfoView.swift
|
||||||
|
// Jel
|
||||||
|
//
|
||||||
|
// Created by zerocool on 12/24/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import JellyfinKit
|
||||||
|
|
||||||
|
struct ItemInfoView: View {
|
||||||
|
@State var item: BaseItemDto
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
HStack {
|
||||||
|
Text(item.genres?.first ?? "---")
|
||||||
|
Text("•")
|
||||||
|
Text((item.productionYear != nil) ? String(item.productionYear!) : "---")
|
||||||
|
}
|
||||||
|
Text(item.getRuntime() ?? "-:--")
|
||||||
|
}
|
||||||
|
.font(.caption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#Preview {
|
||||||
|
// ItemInfoView()
|
||||||
|
//}
|
@ -18,59 +18,50 @@ struct ItemMovieView: View {
|
|||||||
@State var navigationTitle: String = ""
|
@State var navigationTitle: String = ""
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
if loading {
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
} else {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
// ItemHeaderView(item: item)
|
|
||||||
// .scrollTransition {content, phase in
|
|
||||||
// content
|
|
||||||
// .scaleEffect(phase.isIdentity ? 1 : 2)
|
|
||||||
// .opacity(phase.isIdentity ? 1 : 0.1)
|
|
||||||
// .blur(radius: phase.isIdentity ? 0 : 50)
|
|
||||||
// }
|
|
||||||
ItemHeaderView(item: item)
|
ItemHeaderView(item: item)
|
||||||
.opacity(0) // this is the jankiest thing in existence
|
.padding(.bottom)
|
||||||
.background {
|
.background {
|
||||||
GeometryReader {geo in
|
GeometryReader {geo in
|
||||||
ItemHeaderView(item: item)
|
EmptyView()
|
||||||
.onChange(of: geo.frame(in: .global).minY) {
|
.onChange(of: geo.frame(in: .global).minY) {
|
||||||
navigationTitle = geo.frame(in: .global).minY < 0 ? item.name ?? "Unknown" : ""
|
let minY = geo.frame(in: .global).minY
|
||||||
|
if minY < 0 {
|
||||||
|
navigationTitle = item.name ?? ""
|
||||||
|
} else {
|
||||||
|
navigationTitle = ""
|
||||||
}
|
}
|
||||||
.scaleEffect(1 + (geo.frame(in: .global).minY > 0 ? geo.frame(in: .global).minY * 0.001 : 0))
|
|
||||||
.offset(y: 1 + (geo.frame(in: .global).minY > 0 ? geo.frame(in: .global).minY * 0.001 : 0))
|
|
||||||
.scrollTransition {content, phase in
|
|
||||||
content
|
|
||||||
.scaleEffect(phase.isIdentity ? 1 : 2)
|
|
||||||
.opacity(phase.isIdentity ? 1 : 0.1)
|
|
||||||
.blur(radius: phase.isIdentity ? 0 : 50)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack {
|
VStack(alignment: .leading) {
|
||||||
Text(item.taglines?[0] ?? "Unknown")
|
Text(item.taglines?.count ?? 0 > 0 ? item.taglines?[0] ?? "" : "")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.padding(.top, 20)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|
||||||
Text(item.overview ?? "Unknown")
|
Text(item.overview ?? "---")
|
||||||
.padding()
|
}
|
||||||
Text(item.overview ?? "Unknown")
|
|
||||||
.padding()
|
|
||||||
Text(item.overview ?? "Unknown")
|
|
||||||
.padding()
|
|
||||||
Text(item.overview ?? "Unknown")
|
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.redacted(reason: loading ? .placeholder : [])
|
}
|
||||||
.ignoresSafeArea(edges: .top)
|
|
||||||
.scrollIndicators(.hidden)
|
|
||||||
.toolbarRole(.editor)
|
.toolbarRole(.editor)
|
||||||
.navigationTitle(navigationTitle)
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.navigationTitle(navigationTitle)
|
||||||
|
.ignoresSafeArea(edges: .bottom)
|
||||||
|
.scrollIndicators(.hidden)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let request = Paths.getItem(userID: authState.userId ?? "", itemID: item.id ?? "")
|
let request = Paths.getItem(userID: authState.userId ?? "", itemID: item.id ?? "")
|
||||||
item = try await jellyfinClient.send(request).value
|
let response = try await jellyfinClient.send(request)
|
||||||
|
item = response.value
|
||||||
loading = false
|
loading = false
|
||||||
} catch {
|
} catch {
|
||||||
}
|
}
|
||||||
@ -79,6 +70,7 @@ struct ItemMovieView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
//#Preview {
|
||||||
ItemMovieView(item: BaseItemDto())
|
// ItemMovieView(item: BaseItemDto())
|
||||||
}
|
|
||||||
|
//}
|
||||||
|
@ -47,6 +47,7 @@ struct LibraryDetailView: View {
|
|||||||
do {
|
do {
|
||||||
let res = try await jellyfinClient.send(request)
|
let res = try await jellyfinClient.send(request)
|
||||||
items = res.value.items
|
items = res.value.items
|
||||||
|
items?.sort(by: {$0.name?.lowercased() ?? "" < $1.name?.lowercased() ?? ""})
|
||||||
loading = false
|
loading = false
|
||||||
} catch {
|
} catch {
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,6 @@ struct LibraryIconView: View {
|
|||||||
if let image = state.image {
|
if let image = state.image {
|
||||||
image
|
image
|
||||||
.resizable()
|
.resizable()
|
||||||
} else if state.error != nil {
|
|
||||||
Color.red
|
|
||||||
} else {
|
} else {
|
||||||
if let content = placeHolder {
|
if let content = placeHolder {
|
||||||
content
|
content
|
||||||
|
38
Jel/Views/Utility/StickyHeaderView.swift
Normal file
38
Jel/Views/Utility/StickyHeaderView.swift
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// StickyHeaderView.swift
|
||||||
|
// Jel
|
||||||
|
//
|
||||||
|
// Created by zerocool on 12/24/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct StickyHeaderView<Content: View>: View {
|
||||||
|
|
||||||
|
var minHeight: CGFloat
|
||||||
|
var content: Content
|
||||||
|
|
||||||
|
init(minHeight: CGFloat = 200, @ViewBuilder content: () -> Content) {
|
||||||
|
self.minHeight = minHeight
|
||||||
|
self.content = content()
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
GeometryReader { geo in
|
||||||
|
if(geo.frame(in: .global).minY <= 0) {
|
||||||
|
content
|
||||||
|
.frame(width: geo.size.width, height: geo.size.height, alignment: .center)
|
||||||
|
} else {
|
||||||
|
content
|
||||||
|
.offset(y: -geo.frame(in: .global).minY)
|
||||||
|
.frame(width: geo.size.width, height: geo.size.height + geo.frame(in: .global).minY)
|
||||||
|
}
|
||||||
|
}.frame(minHeight: minHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
StickyHeaderView {
|
||||||
|
Text("Test")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user