From 96dba15f0479e78b40a332bdd52212b88e8db53f Mon Sep 17 00:00:00 2001 From: Aiden Vigue Date: Sat, 12 Jun 2021 10:41:56 -0700 Subject: [PATCH] Update Nuke to 0.6.1 --- JellyfinPlayer.xcodeproj/project.pbxproj | 14 ++-- .../xcshareddata/swiftpm/Package.resolved | 4 +- JellyfinPlayer/ConnectToServerView.swift | 5 +- JellyfinPlayer/ContentView.swift | 2 +- JellyfinPlayer/ContinueWatchingView.swift | 14 +--- JellyfinPlayer/EpisodeItemView.swift | 71 +++--------------- JellyfinPlayer/ImageView.swift | 39 ++++++++++ JellyfinPlayer/LatestMediaView.swift | 9 +-- JellyfinPlayer/LibrarySearchView.swift | 10 +-- JellyfinPlayer/LibraryView.swift | 10 +-- JellyfinPlayer/MovieItemView.swift | 73 +++---------------- JellyfinPlayer/NextUpView.swift | 9 +-- JellyfinPlayer/SeasonItemView.swift | 62 ++-------------- JellyfinPlayer/SeriesItemView.swift | 9 +-- Shared/Extensions/NukeExtensions.swift | 22 ------ 15 files changed, 83 insertions(+), 270 deletions(-) create mode 100644 JellyfinPlayer/ImageView.swift delete mode 100644 Shared/Extensions/NukeExtensions.swift diff --git a/JellyfinPlayer.xcodeproj/project.pbxproj b/JellyfinPlayer.xcodeproj/project.pbxproj index 48e0afe6..18b736ca 100644 --- a/JellyfinPlayer.xcodeproj/project.pbxproj +++ b/JellyfinPlayer.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */; }; 531ABF6C2671F5CC00C0FE20 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 628B95212670CABD0091AF3B /* WidgetKit.framework */; }; + 531AC8BF26750DE20091C7EB /* ImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531AC8BE26750DE20091C7EB /* ImageView.swift */; }; 5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */; }; 5321753E2671DE9C005491E6 /* Typings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535870AC2669D8DD00D05A09 /* Typings.swift */; }; 5321753F2671DEA6005491E6 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */; }; @@ -36,7 +37,6 @@ 535870A62669D8AE00D05A09 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338B22660A07800A81A2A /* LazyView.swift */; }; 535870A72669D8AE00D05A09 /* MultiSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53E4E648263F725B00F67C6B /* MultiSelectorView.swift */; }; 535870A82669D8AE00D05A09 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* StringExtensions.swift */; }; - 535870A92669D8AE00D05A09 /* NukeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621C638126676728004216EA /* NukeExtensions.swift */; }; 535870AA2669D8AE00D05A09 /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5389277B263CC3DB0035E14B /* BlurHashDecode.swift */; }; 535870AD2669D8DD00D05A09 /* Typings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535870AC2669D8DD00D05A09 /* Typings.swift */; }; 535BAE9F2649E569005FA86D /* ItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535BAE9E2649E569005FA86D /* ItemView.swift */; }; @@ -72,7 +72,6 @@ 621338932660107500A81A2A /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* StringExtensions.swift */; }; 621338B32660A07800A81A2A /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338B22660A07800A81A2A /* LazyView.swift */; }; 621C638026672A30004216EA /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 621C637F26672A30004216EA /* NukeUI */; }; - 621C638226676728004216EA /* NukeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621C638126676728004216EA /* NukeExtensions.swift */; }; 6225FCCB2663841E00E067F6 /* ParallaxHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */; }; 6228B1C22670EB010067FD35 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5377CBFD263B596B003A4E83 /* PersistenceController.swift */; }; 6267B3D42671024A00A7371D /* APIExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* APIExtensions.swift */; }; @@ -153,6 +152,7 @@ /* Begin PBXFileReference section */ 53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceProfileBuilder.swift; sourceTree = ""; }; + 531AC8BE26750DE20091C7EB /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = ""; }; 5321753A2671BCFC005491E6 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = ""; }; 53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = VideoPlayer.storyboard; sourceTree = ""; }; 5338F74D263B61370014BF09 /* ConnectToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerView.swift; sourceTree = ""; }; @@ -201,7 +201,6 @@ 6213388F265F83A900A81A2A /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = ""; }; 621338922660107500A81A2A /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = ""; }; 621338B22660A07800A81A2A /* LazyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = ""; }; - 621C638126676728004216EA /* NukeExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NukeExtensions.swift; sourceTree = ""; }; 6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallaxHeader.swift; sourceTree = ""; }; 6267B3D526710B8900A7371D /* CollectionExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtensions.swift; sourceTree = ""; }; 6267B3D92671138200A7371D /* ImageExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageExtensions.swift; sourceTree = ""; }; @@ -359,6 +358,7 @@ 53313B8F265EEA6D00947AA3 /* VideoPlayer.storyboard */, 53F8377C265FF67C00F456B3 /* VideoPlayerSettingsView.swift */, 53DE4BD1267098F300739748 /* SearchBarView.swift */, + 531AC8BE26750DE20091C7EB /* ImageView.swift */, ); path = JellyfinPlayer; sourceTree = ""; @@ -391,7 +391,6 @@ 53C4404D266C75C70049424C /* HandleAPIRequestCompletion.swift */, 621338B22660A07800A81A2A /* LazyView.swift */, 53E4E648263F725B00F67C6B /* MultiSelectorView.swift */, - 621C638126676728004216EA /* NukeExtensions.swift */, 6225FCCA2663841E00E067F6 /* ParallaxHeader.swift */, 621338922660107500A81A2A /* StringExtensions.swift */, 6267B3D526710B8900A7371D /* CollectionExtensions.swift */, @@ -589,7 +588,6 @@ 6267B3D826710B9800A7371D /* CollectionExtensions.swift in Sources */, 535870A52669D8AE00D05A09 /* ParallaxHeader.swift in Sources */, 535870A72669D8AE00D05A09 /* MultiSelectorView.swift in Sources */, - 535870A92669D8AE00D05A09 /* NukeExtensions.swift in Sources */, 5358706C2669D21700D05A09 /* Persistence.swift in Sources */, 5321753F2671DEA6005491E6 /* SettingsViewModel.swift in Sources */, 535870AA2669D8AE00D05A09 /* BlurHashDecode.swift in Sources */, @@ -610,7 +608,6 @@ files = ( 5364F455266CA0DC0026ECBA /* APIExtensions.swift in Sources */, 621338932660107500A81A2A /* StringExtensions.swift in Sources */, - 621C638226676728004216EA /* NukeExtensions.swift in Sources */, 53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */, 5377CBFE263B596B003A4E83 /* PersistenceController.swift in Sources */, 5389276E263C25100035E14B /* ContinueWatchingView.swift in Sources */, @@ -632,6 +629,7 @@ 53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */, 53E4E649263F725B00F67C6B /* MultiSelectorView.swift in Sources */, 621338B32660A07800A81A2A /* LazyView.swift in Sources */, + 531AC8BF26750DE20091C7EB /* ImageView.swift in Sources */, 535870AD2669D8DD00D05A09 /* Typings.swift in Sources */, 53C4404E266C75C70049424C /* HandleAPIRequestCompletion.swift in Sources */, 6267B3DA2671138200A7371D /* ImageExtensions.swift in Sources */, @@ -1043,8 +1041,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kean/NukeUI"; requirement = { - kind = exactVersion; - version = 0.3.0; + kind = upToNextMajorVersion; + minimumVersion = 0.3.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/JellyfinPlayer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/JellyfinPlayer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 4cf2aa37..5fa76101 100644 --- a/JellyfinPlayer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/JellyfinPlayer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/kean/NukeUI", "state": { "branch": null, - "revision": "d2580b8d22b29c6244418d8e4b568f3162191460", - "version": "0.3.0" + "revision": "62b55e26eddc2ed59e63377ab877efac4f9e049c", + "version": "0.6.1" } }, { diff --git a/JellyfinPlayer/ConnectToServerView.swift b/JellyfinPlayer/ConnectToServerView.swift index d07655bb..b989876c 100644 --- a/JellyfinPlayer/ConnectToServerView.swift +++ b/JellyfinPlayer/ConnectToServerView.swift @@ -8,7 +8,6 @@ import SwiftUI import CoreData import KeychainSwift -import NukeUI import JellyfinAPI struct ConnectToServerView: View { @@ -290,11 +289,9 @@ struct ConnectToServerView: View { Text(publicUser.name ?? "").font(.subheadline).fontWeight(.semibold) Spacer() if publicUser.primaryImageTag != nil { - LazyImage(source: URL(string: "\(uri)/Users/\(publicUser.id ?? "")/Images/Primary?width=200&quality=80&tag=\(publicUser.primaryImageTag!)")) - .contentMode(.aspectFill) + ImageView(src: URL(string: "\(uri)/Users/\(publicUser.id ?? "")/Images/Primary?width=200&quality=80&tag=\(publicUser.primaryImageTag!)")!) .frame(width: 60, height: 60) .cornerRadius(30.0) - .shadow(radius: 6) } else { Image(systemName: "person.fill") .foregroundColor(Color(red: 1, green: 1, blue: 1).opacity(0.8)) diff --git a/JellyfinPlayer/ContentView.swift b/JellyfinPlayer/ContentView.swift index 77107e7e..2c8da660 100644 --- a/JellyfinPlayer/ContentView.swift +++ b/JellyfinPlayer/ContentView.swift @@ -224,7 +224,7 @@ struct ContentView: View { .onAppear(perform: { DispatchQueue.main.async { [self] in _viewDidLoad.wrappedValue = false - usleep(500_000) + sleep(1) self.jsi.did = false } }) diff --git a/JellyfinPlayer/ContinueWatchingView.swift b/JellyfinPlayer/ContinueWatchingView.swift index f68c7981..2d75908b 100644 --- a/JellyfinPlayer/ContinueWatchingView.swift +++ b/JellyfinPlayer/ContinueWatchingView.swift @@ -1,4 +1,5 @@ -/* JellyfinPlayer/Swiftfin is subject to the terms of the Mozilla Public +/* + * JellyfinPlayer/Swiftfin is subject to the terms of the Mozilla Public * License, v2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at https://mozilla.org/MPL/2.0/. * @@ -6,7 +7,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct ProgressBar: Shape { @@ -56,15 +56,7 @@ struct ContinueWatchingView: View { NavigationLink(destination: ItemView(item: item)) { VStack(alignment: .leading) { Spacer().frame(height: 10) - LazyImage(source: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 320)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getBackdropImageBlurHash(), size: CGSize(width: 48, height: 32))!) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 320, height: 180) - .cornerRadius(10) - } - .aspectRatio(contentMode: .fill) + ImageView(src: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 320), bh: item.getBackdropImageBlurHash()) .frame(width: 320, height: 180) .cornerRadius(10) .overlay( diff --git a/JellyfinPlayer/EpisodeItemView.swift b/JellyfinPlayer/EpisodeItemView.swift index 4854846f..b20743ae 100644 --- a/JellyfinPlayer/EpisodeItemView.swift +++ b/JellyfinPlayer/EpisodeItemView.swift @@ -6,7 +6,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct EpisodeItemView: View { @@ -63,13 +62,7 @@ struct EpisodeItemView: View { } var portraitHeaderView: some View { - LazyImage(source: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 1200)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getBackdropImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - } - .contentMode(.aspectFill) + ImageView(src: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 622 : Int(UIScreen.main.bounds.width)), bh: item.getBackdropImageBlurHash()) .opacity(0.4) .blur(radius: 2.0) } @@ -77,24 +70,16 @@ struct EpisodeItemView: View { var portraitHeaderOverlayView: some View { VStack(alignment: .leading) { HStack(alignment: .bottom, spacing: 12) { - LazyImage(source: item.getSeriesPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getSeriesPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 120, height: 180) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: item.getSeriesPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120), bh: item.getSeriesPrimaryImageBlurHash()) .frame(width: 120, height: 180) .cornerRadius(10) VStack(alignment: .leading) { Spacer() - Text(item.name!).font(.headline) + Text(item.name ?? "").font(.headline) .fontWeight(.semibold) .foregroundColor(.primary) .fixedSize(horizontal: false, vertical: true) - .offset(y: -4) + .offset(y: 5) HStack { Text(String(item.productionYear ?? 0)).font(.subheadline) .fontWeight(.medium) @@ -157,7 +142,7 @@ struct EpisodeItemView: View { } } } - } + }.padding(.top, 8) } .padding(.horizontal, 16) .padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? -189 : -64) @@ -205,17 +190,7 @@ struct EpisodeItemView: View { LibraryView(withPerson: person) }) { VStack { - LazyImage(source: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: person.getBlurHash(), - size: CGSize(width: 16, - height: 16))!) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 100, height: 100) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: person.getBlurHash()) .frame(width: 100, height: 100) .cornerRadius(10) Text(person.name ?? "").font(.footnote).fontWeight(.regular).lineLimit(1) @@ -254,18 +229,7 @@ struct EpisodeItemView: View { } else { GeometryReader { geometry in ZStack { - LazyImage(source: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 200)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getBackdropImageBlurHash(), - size: CGSize(width: 16, height: 16))!) - .resizable() - .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets - .trailing, - height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets - .bottom) - } - .contentMode(.aspectFill) - + ImageView(src: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 200), bh: item.getBackdropImageBlurHash()) .opacity(0.3) .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom) @@ -273,16 +237,9 @@ struct EpisodeItemView: View { .blur(radius: 4) HStack { VStack { - LazyImage(source: item.getSeriesPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getSeriesPrimaryImageBlurHash(), - size: CGSize(width: 16, height: 16))!) - .resizable() - .frame(width: 120, height: 180) - } + ImageView(src: item.getSeriesPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120), bh: item.getSeriesPrimaryImageBlurHash()) .frame(width: 120, height: 180) .cornerRadius(10) - .shadow(radius: 5) Spacer().frame(height: 15) Button { self.playbackInfo.itemToPlay = item @@ -404,17 +361,7 @@ struct EpisodeItemView: View { LibraryView(withPerson: person) }) { VStack { - LazyImage(source: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: person.getBlurHash(), - size: CGSize(width: 16, - height: 16))!) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 100, height: 100) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: person.getBlurHash()) .frame(width: 100, height: 100) .cornerRadius(10) Text(person.name ?? "").font(.footnote).fontWeight(.regular).lineLimit(1) diff --git a/JellyfinPlayer/ImageView.swift b/JellyfinPlayer/ImageView.swift new file mode 100644 index 00000000..46918cd4 --- /dev/null +++ b/JellyfinPlayer/ImageView.swift @@ -0,0 +1,39 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import SwiftUI +import NukeUI + +struct ImageView: View { + private var source: URL = URL(string: "https://example.com")! + private var blurhash: String = "001fC^" + + init(src: URL) { + self.source = src + } + + init(src: URL, bh: String) { + self.source = src + self.blurhash = bh + } + + var body: some View { + LazyImage(source: source, content: { state in + if let image = state.image { + image.resizingMode(.aspectFill) + } else if state.error != nil { + Image(uiImage: UIImage(blurHash: "001fC^", size: CGSize(width: 1, height: 1))!) + .resizable() + } else { + Image(uiImage: UIImage(blurHash: blurhash, size: CGSize(width: 16, height: 16))!) + .resizable() + } + }) + } +} diff --git a/JellyfinPlayer/LatestMediaView.swift b/JellyfinPlayer/LatestMediaView.swift index 80c53009..d44f6de5 100644 --- a/JellyfinPlayer/LatestMediaView.swift +++ b/JellyfinPlayer/LatestMediaView.swift @@ -6,7 +6,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct LatestMediaView: View { @@ -46,13 +45,7 @@ struct LatestMediaView: View { NavigationLink(destination: ItemView(item: item)) { VStack(alignment: .leading) { Spacer().frame(height: 10) - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), size: CGSize(width: 16, height: 20))!) - .resizable() - .frame(width: 100, height: 150) - .cornerRadius(10) - } + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: item.getPrimaryImageBlurHash()) .frame(width: 100, height: 150) .cornerRadius(10) Spacer().frame(height: 5) diff --git a/JellyfinPlayer/LibrarySearchView.swift b/JellyfinPlayer/LibrarySearchView.swift index 795fca2f..53870cf2 100644 --- a/JellyfinPlayer/LibrarySearchView.swift +++ b/JellyfinPlayer/LibrarySearchView.swift @@ -6,7 +6,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct LibrarySearchView: View { @@ -69,14 +68,7 @@ struct LibrarySearchView: View { ForEach(items, id: \.id) { item in NavigationLink(destination: ItemView(item: item)) { VStack(alignment: .leading) { - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 100, height: 150) - .cornerRadius(10) - } + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: item.getPrimaryImageBlurHash()) .frame(width: 100, height: 150) .cornerRadius(10) Text(item.name ?? "") diff --git a/JellyfinPlayer/LibraryView.swift b/JellyfinPlayer/LibraryView.swift index 5161caa0..1273953a 100644 --- a/JellyfinPlayer/LibraryView.swift +++ b/JellyfinPlayer/LibraryView.swift @@ -107,14 +107,7 @@ struct LibraryView: View { ForEach(items, id: \.id) { item in NavigationLink(destination: ItemView(item: item)) { VStack(alignment: .leading) { - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 100, height: 150) - .cornerRadius(10) - } + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: item.getPrimaryImageBlurHash()) .frame(width: 100, height: 150) .cornerRadius(10) Text(item.name ?? "") @@ -200,3 +193,4 @@ struct LibraryView: View { } // stream BM^S by nicki! +// diff --git a/JellyfinPlayer/MovieItemView.swift b/JellyfinPlayer/MovieItemView.swift index 8aa842bd..e132ef36 100644 --- a/JellyfinPlayer/MovieItemView.swift +++ b/JellyfinPlayer/MovieItemView.swift @@ -6,7 +6,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct MovieItemView: View { @@ -63,13 +62,7 @@ struct MovieItemView: View { } var portraitHeaderView: some View { - LazyImage(source: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 1200)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getBackdropImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - } - .contentMode(.aspectFill) + ImageView(src: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 622 : Int(UIScreen.main.bounds.width)), bh: item.getBackdropImageBlurHash()) .opacity(0.4) .blur(radius: 2.0) } @@ -77,24 +70,16 @@ struct MovieItemView: View { var portraitHeaderOverlayView: some View { VStack(alignment: .leading) { HStack(alignment: .bottom, spacing: 12) { - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 120, height: 180) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) .frame(width: 120, height: 180) .cornerRadius(10) VStack(alignment: .leading) { Spacer() - Text(item.name!).font(.headline) + Text(item.name ?? "").font(.headline) .fontWeight(.semibold) .foregroundColor(.primary) - .fixedSize(horizontal: false, vertical: true) - .offset(y: -4) + .lineLimit(1) + .offset(y: 5) HStack { if item.productionYear != nil { Text(String(item.productionYear ?? 0)).font(.subheadline) @@ -159,7 +144,7 @@ struct MovieItemView: View { } } } - } + }.padding(.top, 8) } .padding(.horizontal, 16) .padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad ? -189 : -64) @@ -207,17 +192,7 @@ struct MovieItemView: View { LibraryView(withPerson: person) }) { VStack { - LazyImage(source: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: person.getBlurHash(), - size: CGSize(width: 16, - height: 16))!) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 100, height: 100) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: person.getBlurHash()) .frame(width: 100, height: 100) .cornerRadius(10) Text(person.name ?? "").font(.footnote).fontWeight(.regular).lineLimit(1) @@ -256,18 +231,7 @@ struct MovieItemView: View { } else { GeometryReader { geometry in ZStack { - LazyImage(source: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 200)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getBackdropImageBlurHash(), - size: CGSize(width: 16, height: 16))!) - .resizable() - .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets - .trailing, - height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets - .bottom) - } - .contentMode(.aspectFill) - + ImageView(src: item.getBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 200), bh: item.getBackdropImageBlurHash()) .opacity(0.3) .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom) @@ -275,16 +239,9 @@ struct MovieItemView: View { .blur(radius: 4) HStack { VStack { - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), - size: CGSize(width: 16, height: 16))!) - .resizable() - .frame(width: 120, height: 180) - } + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120), bh: item.getPrimaryImageBlurHash()) .frame(width: 120, height: 180) .cornerRadius(10) - .shadow(radius: 5) Spacer().frame(height: 15) Button { self.playbackInfo.itemToPlay = item @@ -408,17 +365,7 @@ struct MovieItemView: View { LibraryView(withPerson: person) }) { VStack { - LazyImage(source: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: person.getBlurHash(), - size: CGSize(width: 16, - height: 16))!) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 100, height: 100) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: person.getImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: person.getBlurHash()) .frame(width: 100, height: 100) .cornerRadius(10) Text(person.name ?? "").font(.footnote).fontWeight(.regular).lineLimit(1) diff --git a/JellyfinPlayer/NextUpView.swift b/JellyfinPlayer/NextUpView.swift index 78ba4ca6..f0fd9400 100644 --- a/JellyfinPlayer/NextUpView.swift +++ b/JellyfinPlayer/NextUpView.swift @@ -6,7 +6,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct NextUpView: View { @@ -45,13 +44,7 @@ struct NextUpView: View { ForEach(items, id: \.id) { item in NavigationLink(destination: ItemView(item: item)) { VStack(alignment: .leading) { - LazyImage(source: item.getSeriesPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getSeriesPrimaryImageBlurHash(), size: CGSize(width: 16, height: 20))!) - .resizable() - .frame(width: 100, height: 150) - .cornerRadius(10) - } + ImageView(src: item.getSeriesPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: item.getSeriesPrimaryImageBlurHash()) .frame(width: 100, height: 150) .cornerRadius(10) Spacer().frame(height: 5) diff --git a/JellyfinPlayer/SeasonItemView.swift b/JellyfinPlayer/SeasonItemView.swift index 82d6165f..0c6b0b80 100644 --- a/JellyfinPlayer/SeasonItemView.swift +++ b/JellyfinPlayer/SeasonItemView.swift @@ -5,7 +5,6 @@ * Copyright 2021 Aiden Vigue & Jellyfin Contributors */ -import NukeUI import SwiftUI import JellyfinAPI @@ -46,13 +45,7 @@ struct SeasonItemView: View { if isLoading { EmptyView() } else { - LazyImage(source: item.getSeriesBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 1500)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getSeriesBackdropImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - } - .contentMode(.aspectFill) + ImageView(src: item.getSeriesBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: UIDevice.current.userInterfaceIdiom == .pad ? 622 : Int(UIScreen.main.bounds.width)), bh: item.getSeriesBackdropImageBlurHash()) .opacity(0.4) .blur(radius: 2.0) } @@ -60,15 +53,7 @@ struct SeasonItemView: View { var portraitHeaderOverlayView: some View { HStack(alignment: .bottom, spacing: 12) { - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 120, height: 180) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120), bh: item.getPrimaryImageBlurHash()) .frame(width: 120, height: 180) .cornerRadius(10) VStack(alignment: .leading) { @@ -107,15 +92,7 @@ struct SeasonItemView: View { ForEach(episodes, id: \.id) { episode in NavigationLink(destination: ItemView(item: episode)) { HStack { - LazyImage(source: episode.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 150)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: episode.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 150, height: 90) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: episode.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 150), bh: episode.getPrimaryImageBlurHash()) .shadow(radius: 5) .frame(width: 150, height: 90) .cornerRadius(10) @@ -174,18 +151,7 @@ struct SeasonItemView: View { } else { GeometryReader { geometry in ZStack { - LazyImage(source: item.getSeriesBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 200)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getSeriesBackdropImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets - .trailing, - height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets - .bottom) - } - .contentMode(.aspectFill) - + ImageView(src: item.getSeriesBackdropImage(baseURL: globalData.server.baseURI!, maxWidth: 200), bh: item.getSeriesBackdropImageBlurHash()) .opacity(0.4) .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom) @@ -194,15 +160,7 @@ struct SeasonItemView: View { HStack { VStack(alignment: .leading) { Spacer().frame(height: 16) - LazyImage(source: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: item.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 120, height: 180) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: item.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 120), bh: item.getPrimaryImageBlurHash()) .frame(width: 120, height: 180) .cornerRadius(10) Spacer().frame(height: 4) @@ -227,15 +185,7 @@ struct SeasonItemView: View { ForEach(episodes, id: \.id) { episode in NavigationLink(destination: ItemView(item: episode)) { HStack { - LazyImage(source: episode.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 150)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: episode.getPrimaryImageBlurHash(), - size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 150, height: 90) - .cornerRadius(10) - } - .contentMode(.aspectFill) + ImageView(src: episode.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 150), bh: episode.getPrimaryImageBlurHash()) .shadow(radius: 5) .frame(width: 150, height: 90) .cornerRadius(10) diff --git a/JellyfinPlayer/SeriesItemView.swift b/JellyfinPlayer/SeriesItemView.swift index da4df6b0..f84d97b0 100644 --- a/JellyfinPlayer/SeriesItemView.swift +++ b/JellyfinPlayer/SeriesItemView.swift @@ -6,7 +6,6 @@ */ import SwiftUI -import NukeUI import JellyfinAPI struct SeriesItemView: View { @@ -61,13 +60,7 @@ struct SeriesItemView: View { ForEach(seasons, id: \.id) { season in NavigationLink(destination: ItemView(item: season)) { VStack(alignment: .leading) { - LazyImage(source: season.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100)) - .placeholderAndFailure { - Image(uiImage: UIImage(blurHash: season.getPrimaryImageBlurHash(), size: CGSize(width: 32, height: 32))!) - .resizable() - .frame(width: 100, height: 150) - .cornerRadius(10) - } + ImageView(src: season.getPrimaryImage(baseURL: globalData.server.baseURI!, maxWidth: 100), bh: season.getPrimaryImageBlurHash()) .frame(width: 100, height: 150) .cornerRadius(10) .shadow(radius: 5) diff --git a/Shared/Extensions/NukeExtensions.swift b/Shared/Extensions/NukeExtensions.swift deleted file mode 100644 index da37c432..00000000 --- a/Shared/Extensions/NukeExtensions.swift +++ /dev/null @@ -1,22 +0,0 @@ -/* JellyfinPlayer/Swiftfin is subject to the terms of the Mozilla Public - * License, v2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * Copyright 2021 Aiden Vigue & Jellyfin Contributors - */ - -import Foundation -import SwiftUI -import NukeUI - -extension LazyImage { - func placeholderAndFailure(@ViewBuilder _ content: () -> Content?) -> LazyImage { - placeholder { - content() - } - .failure { - content() - } - } - -}