Use Nuke to load images + start movieView

This commit is contained in:
Shav Kinderlehrer 2023-12-23 14:15:01 -05:00
parent a25acb1219
commit 53bdc33ac7
8 changed files with 155 additions and 33 deletions

View File

@ -9,6 +9,10 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
3D1015D92B27F57400F5C29A /* AddServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015D82B27F57400F5C29A /* AddServerView.swift */; }; 3D1015D92B27F57400F5C29A /* AddServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015D82B27F57400F5C29A /* AddServerView.swift */; };
3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015E32B28000E00F5C29A /* AuthStateController.swift */; }; 3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015E32B28000E00F5C29A /* AuthStateController.swift */; };
3D13F95A2B375A9E00E91913 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = 3D13F9592B375A9E00E91913 /* Nuke */; };
3D13F95C2B375A9E00E91913 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3D13F95B2B375A9E00E91913 /* NukeUI */; };
3D13F95F2B375DB800E91913 /* ItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F95E2B375DB800E91913 /* ItemView.swift */; };
3D13F9612B37637500E91913 /* ItemMovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D13F9602B37637500E91913 /* ItemMovieView.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 */; };
@ -67,6 +71,8 @@
3D1015D42B27F49000F5C29A /* JellyfinKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = JellyfinKit; path = ../JellyfinKit; sourceTree = "<group>"; }; 3D1015D42B27F49000F5C29A /* JellyfinKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = JellyfinKit; path = ../JellyfinKit; sourceTree = "<group>"; };
3D1015D82B27F57400F5C29A /* AddServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddServerView.swift; sourceTree = "<group>"; }; 3D1015D82B27F57400F5C29A /* AddServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddServerView.swift; sourceTree = "<group>"; };
3D1015E32B28000E00F5C29A /* AuthStateController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthStateController.swift; sourceTree = "<group>"; }; 3D1015E32B28000E00F5C29A /* AuthStateController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthStateController.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>"; };
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>"; };
@ -98,9 +104,11 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
3D13F95C2B375A9E00E91913 /* NukeUI in Frameworks */,
3D77093B2B29139700199889 /* PulseUI in Frameworks */, 3D77093B2B29139700199889 /* PulseUI in Frameworks */,
3D7709392B29139700199889 /* Pulse in Frameworks */, 3D7709392B29139700199889 /* Pulse in Frameworks */,
3D9064592B27E4C70063DD2A /* JellyfinKit in Frameworks */, 3D9064592B27E4C70063DD2A /* JellyfinKit in Frameworks */,
3D13F95A2B375A9E00E91913 /* Nuke in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -152,9 +160,19 @@
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
3D13F95D2B375DAC00E91913 /* Item */ = {
isa = PBXGroup;
children = (
3D13F95E2B375DB800E91913 /* ItemView.swift */,
3D13F9602B37637500E91913 /* ItemMovieView.swift */,
);
path = Item;
sourceTree = "<group>";
};
3D8AB2A62B366309005BD7D0 /* Library */ = { 3D8AB2A62B366309005BD7D0 /* Library */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3D13F95D2B375DAC00E91913 /* Item */,
3D41D1F92B2CAE0000E58234 /* LibraryIconView.swift */, 3D41D1F92B2CAE0000E58234 /* LibraryIconView.swift */,
3D8AB2A72B366353005BD7D0 /* LibraryDetailView.swift */, 3D8AB2A72B366353005BD7D0 /* LibraryDetailView.swift */,
); );
@ -271,6 +289,8 @@
3D9064582B27E4C70063DD2A /* JellyfinKit */, 3D9064582B27E4C70063DD2A /* JellyfinKit */,
3D7709382B29139700199889 /* Pulse */, 3D7709382B29139700199889 /* Pulse */,
3D77093A2B29139700199889 /* PulseUI */, 3D77093A2B29139700199889 /* PulseUI */,
3D13F9592B375A9E00E91913 /* Nuke */,
3D13F95B2B375A9E00E91913 /* NukeUI */,
); );
productName = Jel; productName = Jel;
productReference = 3D9063C72B279A310063DD2A /* Jel.app */; productReference = 3D9063C72B279A310063DD2A /* Jel.app */;
@ -346,6 +366,7 @@
mainGroup = 3D9063BE2B279A310063DD2A; mainGroup = 3D9063BE2B279A310063DD2A;
packageReferences = ( packageReferences = (
3D7709372B29139700199889 /* XCRemoteSwiftPackageReference "Pulse" */, 3D7709372B29139700199889 /* XCRemoteSwiftPackageReference "Pulse" */,
3D13F9582B375A9E00E91913 /* XCRemoteSwiftPackageReference "Nuke" */,
); );
productRefGroup = 3D9063C82B279A310063DD2A /* Products */; productRefGroup = 3D9063C82B279A310063DD2A /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -397,12 +418,14 @@
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */, 3D91FDC92B28C62800919017 /* SignInView.swift in Sources */,
3D8AB2A82B366353005BD7D0 /* LibraryDetailView.swift in Sources */, 3D8AB2A82B366353005BD7D0 /* LibraryDetailView.swift in Sources */,
3DDD67932B293BC40026781E /* DashboardView.swift in Sources */, 3DDD67932B293BC40026781E /* DashboardView.swift in Sources */,
3D13F9612B37637500E91913 /* ItemMovieView.swift in Sources */,
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 */,
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 */,
3D13F95F2B375DB800E91913 /* ItemView.swift in Sources */,
3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */, 3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */,
3D41D1F52B2C962500E58234 /* AppearancePicker.swift in Sources */, 3D41D1F52B2C962500E58234 /* AppearancePicker.swift in Sources */,
); );
@ -769,6 +792,14 @@
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */ /* Begin XCRemoteSwiftPackageReference section */
3D13F9582B375A9E00E91913 /* XCRemoteSwiftPackageReference "Nuke" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kean/Nuke";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 12.2.0;
};
};
3D7709372B29139700199889 /* XCRemoteSwiftPackageReference "Pulse" */ = { 3D7709372B29139700199889 /* XCRemoteSwiftPackageReference "Pulse" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kean/Pulse"; repositoryURL = "https://github.com/kean/Pulse";
@ -780,6 +811,16 @@
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
3D13F9592B375A9E00E91913 /* Nuke */ = {
isa = XCSwiftPackageProductDependency;
package = 3D13F9582B375A9E00E91913 /* XCRemoteSwiftPackageReference "Nuke" */;
productName = Nuke;
};
3D13F95B2B375A9E00E91913 /* NukeUI */ = {
isa = XCSwiftPackageProductDependency;
package = 3D13F9582B375A9E00E91913 /* XCRemoteSwiftPackageReference "Nuke" */;
productName = NukeUI;
};
3D7709382B29139700199889 /* Pulse */ = { 3D7709382B29139700199889 /* Pulse */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 3D7709372B29139700199889 /* XCRemoteSwiftPackageReference "Pulse" */; package = 3D7709372B29139700199889 /* XCRemoteSwiftPackageReference "Pulse" */;

View File

@ -10,6 +10,15 @@
"version": "2.1.6" "version": "2.1.6"
} }
}, },
{
"package": "Nuke",
"repositoryURL": "https://github.com/kean/Nuke",
"state": {
"branch": null,
"revision": "1694798e876113d44f6ec6ead965d7286695981d",
"version": "12.2.0"
}
},
{ {
"package": "Pulse", "package": "Pulse",
"repositoryURL": "https://github.com/kean/Pulse", "repositoryURL": "https://github.com/kean/Pulse",

View File

@ -21,7 +21,7 @@ struct DashboardLibraryView: View {
.progressViewStyle(.circular) .progressViewStyle(.circular)
} }
ScrollView(.horizontal, showsIndicators: false) { ScrollView(.horizontal, showsIndicators: false) {
HStack { LazyHStack {
ForEach(libraries) {library in ForEach(libraries) {library in
if library.collectionType == "movies" || library.collectionType == "tvshows" { if library.collectionType == "movies" || library.collectionType == "tvshows" {
NavigationLink { NavigationLink {

View File

@ -16,6 +16,7 @@ struct DashboardView: View {
VStack { VStack {
DashboardLibraryView() DashboardLibraryView()
} }
.navigationTitle("Home")
.toolbar { .toolbar {
ToolbarItem(placement: .topBarTrailing) { ToolbarItem(placement: .topBarTrailing) {
Button { Button {

View File

@ -0,0 +1,44 @@
//
// ItemMovieView.swift
// Jel
//
// Created by zerocool on 12/23/23.
//
import SwiftUI
import JellyfinKit
struct ItemMovieView: View {
@EnvironmentObject var jellyfinClient: JellyfinClientController
@StateObject var authState: AuthStateController = AuthStateController.shared
@State var item: BaseItemDto
@State var loading: Bool = true
var body: some View {
VStack {
Text(item.name ?? "Unknown")
.font(.title)
Text(item.taglines?[0] ?? "Unknown")
.font(.headline)
Text(item.overview ?? "Unknown")
}
.navigationTitle(item.name ?? "Unknown")
.navigationBarTitleDisplayMode(.inline)
.redacted(reason: loading ? .placeholder : [])
.onAppear {
Task {
do {
let request = Paths.getItem(userID: authState.userId ?? "", itemID: item.id ?? "")
item = try await jellyfinClient.send(request).value
loading = false
} catch {
}
}
}
}
}
#Preview {
ItemMovieView(item: BaseItemDto())
}

View File

@ -0,0 +1,25 @@
//
// ItemView.swift
// Jel
//
// Created by zerocool on 12/23/23.
//
import SwiftUI
import JellyfinKit
struct ItemView: View {
@State var item: BaseItemDto
var body: some View {
switch item.type {
case .movie:
ItemMovieView(item: item)
default:
Text("Unkown media")
}
}
}
#Preview {
ItemView(item: BaseItemDto())
}

View File

@ -28,8 +28,13 @@ struct LibraryDetailView: View {
ScrollView { ScrollView {
LazyVGrid(columns: columns) { LazyVGrid(columns: columns) {
ForEach(items ?? []) {item in ForEach(items ?? []) {item in
LibraryIconView(library: item, imageType: "Primary", height: 150) NavigationLink {
.padding() ItemView(item: item)
} label: {
LibraryIconView(library: item, imageType: "Primary", width: 170)
.padding()
}
.buttonStyle(PlainButtonStyle())
} }
} }
} }

View File

@ -7,49 +7,46 @@
import SwiftUI import SwiftUI
import JellyfinKit import JellyfinKit
import NukeUI
struct LibraryIconView: View { struct LibraryIconView: View {
@EnvironmentObject var jellyfinClient: JellyfinClientController @EnvironmentObject var jellyfinClient: JellyfinClientController
@State var library: BaseItemDto var library: BaseItemDto
@State var loadingImage: Bool = true var imageType: String = "Primary"
@State var imageType: String = "Primary"
var width: CGFloat? var width: CGFloat?
var height: CGFloat? var height: CGFloat?
@State var blurHashImage: UIImage = UIImage() @State var blurHashImage: UIImage = UIImage()
@State var imageUrl: URL? @State var imageUrl: URL?
var body: some View { var body: some View {
AsyncImage(url: imageUrl) {image in VStack {
VStack { LazyImage(url: imageUrl) {state in
image if let image = state.image {
.resizable() image
.aspectRatio(contentMode: .fit) .resizable()
.frame(width: width, height: height) } else if state.error != nil {
.clipShape(RoundedRectangle(cornerRadius: 3)) Color.red
Text(library.name ?? "Unknown") } else {
.font(.subheadline) Image(uiImage: blurHashImage)
.resizable()
}
} }
} placeholder: { .aspectRatio(contentMode: .fit)
VStack { .frame(width: width, height: height)
Image(uiImage: blurHashImage) .clipShape(RoundedRectangle(cornerRadius: 5))
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: width, height: height)
.clipShape(RoundedRectangle(cornerRadius: 3))
Text(library.name ?? "Unknown")
.font(.subheadline)
}
}
.onAppear {
let blurhash = library.imageBlurHashes?.primary?[library.imageTags?[imageType] ?? ""] ?? ""
blurHashImage = UIImage(blurHash: blurhash, size: CGSize(width: 32, height: 32)) ?? UIImage()
let imageId = library.id ?? "" Text(library.name ?? "Unknown")
let request = Paths.getItemImage(itemID: imageId, imageType: imageType) .font(.subheadline)
imageUrl = jellyfinClient.getUrl()?.appending(path: request.url?.absoluteString ?? "") .onAppear {
let blurhash = library.imageBlurHashes?.primary?[library.imageTags?[imageType] ?? ""] ?? ""
blurHashImage = UIImage(blurHash: blurhash, size: CGSize(width: 16, height: 16)) ?? UIImage()
let imageId = library.id ?? ""
let request = Paths.getItemImage(itemID: imageId, imageType: imageType)
imageUrl = jellyfinClient.getUrl()?.appending(path: request.url?.absoluteString ?? "")
}
} }
} }
} }