This commit is contained in:
PangMo5 2021-06-02 13:00:20 +09:00
parent 9add2c0add
commit 082ce29a44
13 changed files with 295 additions and 289 deletions

View File

@ -28,7 +28,6 @@
53892777263CBB000035E14B /* JellyApiTypings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53892776263CBB000035E14B /* JellyApiTypings.swift */; }; 53892777263CBB000035E14B /* JellyApiTypings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53892776263CBB000035E14B /* JellyApiTypings.swift */; };
5389277A263CBFE70035E14B /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 53892779263CBFE70035E14B /* SwiftyJSON */; }; 5389277A263CBFE70035E14B /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 53892779263CBFE70035E14B /* SwiftyJSON */; };
5389277C263CC3DB0035E14B /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5389277B263CC3DB0035E14B /* BlurHashDecode.swift */; }; 5389277C263CC3DB0035E14B /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5389277B263CC3DB0035E14B /* BlurHashDecode.swift */; };
538CD954263E3DC100BB5AF0 /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 538CD953263E3DC100BB5AF0 /* SDWebImageSwiftUI */; };
53987CA426572C1300E7EA70 /* SeasonItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53987CA326572C1300E7EA70 /* SeasonItemView.swift */; }; 53987CA426572C1300E7EA70 /* SeasonItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53987CA326572C1300E7EA70 /* SeasonItemView.swift */; };
53987CA626572F0700E7EA70 /* SeriesItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53987CA526572F0700E7EA70 /* SeriesItemView.swift */; }; 53987CA626572F0700E7EA70 /* SeriesItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53987CA526572F0700E7EA70 /* SeriesItemView.swift */; };
53987CA82657424A00E7EA70 /* EpisodeItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53987CA72657424A00E7EA70 /* EpisodeItemView.swift */; }; 53987CA82657424A00E7EA70 /* EpisodeItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53987CA72657424A00E7EA70 /* EpisodeItemView.swift */; };
@ -47,6 +46,7 @@
621338932660107500A81A2A /* String++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* String++.swift */; }; 621338932660107500A81A2A /* String++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* String++.swift */; };
62133895266096EF00A81A2A /* LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62133894266096EF00A81A2A /* LibraryListViewModel.swift */; }; 62133895266096EF00A81A2A /* LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62133894266096EF00A81A2A /* LibraryListViewModel.swift */; };
621338B32660A07800A81A2A /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338B22660A07800A81A2A /* LazyView.swift */; }; 621338B32660A07800A81A2A /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338B22660A07800A81A2A /* LazyView.swift */; };
621C638026672A30004216EA /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 621C637F26672A30004216EA /* NukeUI */; };
6225FCCB2663841E00E067F6 /* ParallaxHeaderScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6225FCCA2663841E00E067F6 /* ParallaxHeaderScrollView.swift */; }; 6225FCCB2663841E00E067F6 /* ParallaxHeaderScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6225FCCA2663841E00E067F6 /* ParallaxHeaderScrollView.swift */; };
6273DD43265F4195009C1D0B /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD42265F4195009C1D0B /* Moya */; }; 6273DD43265F4195009C1D0B /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD42265F4195009C1D0B /* Moya */; };
6273DD45265F4195009C1D0B /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD44265F4195009C1D0B /* CombineMoya */; }; 6273DD45265F4195009C1D0B /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD44265F4195009C1D0B /* CombineMoya */; };
@ -130,13 +130,13 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
538CD954263E3DC100BB5AF0 /* SDWebImageSwiftUI in Frameworks */,
5338F757263B7E2E0014BF09 /* KeychainSwift in Frameworks */, 5338F757263B7E2E0014BF09 /* KeychainSwift in Frameworks */,
6273DD45265F4195009C1D0B /* CombineMoya in Frameworks */, 6273DD45265F4195009C1D0B /* CombineMoya in Frameworks */,
6273DD43265F4195009C1D0B /* Moya in Frameworks */, 6273DD43265F4195009C1D0B /* Moya in Frameworks */,
53D5E3DD264B47EE00BADDC8 /* MobileVLCKit.xcframework in Frameworks */, 53D5E3DD264B47EE00BADDC8 /* MobileVLCKit.xcframework in Frameworks */,
5338F754263B65E10014BF09 /* SwiftyRequest in Frameworks */, 5338F754263B65E10014BF09 /* SwiftyRequest in Frameworks */,
53352571265EA0A0006CCA86 /* Introspect in Frameworks */, 53352571265EA0A0006CCA86 /* Introspect in Frameworks */,
621C638026672A30004216EA /* NukeUI in Frameworks */,
5302F82A2658791C00647A2E /* Sentry in Frameworks */, 5302F82A2658791C00647A2E /* Sentry in Frameworks */,
5389277A263CBFE70035E14B /* SwiftyJSON in Frameworks */, 5389277A263CBFE70035E14B /* SwiftyJSON in Frameworks */,
); );
@ -295,11 +295,11 @@
5338F753263B65E10014BF09 /* SwiftyRequest */, 5338F753263B65E10014BF09 /* SwiftyRequest */,
5338F756263B7E2E0014BF09 /* KeychainSwift */, 5338F756263B7E2E0014BF09 /* KeychainSwift */,
53892779263CBFE70035E14B /* SwiftyJSON */, 53892779263CBFE70035E14B /* SwiftyJSON */,
538CD953263E3DC100BB5AF0 /* SDWebImageSwiftUI */,
5302F8292658791C00647A2E /* Sentry */, 5302F8292658791C00647A2E /* Sentry */,
53352570265EA0A0006CCA86 /* Introspect */, 53352570265EA0A0006CCA86 /* Introspect */,
6273DD42265F4195009C1D0B /* Moya */, 6273DD42265F4195009C1D0B /* Moya */,
6273DD44265F4195009C1D0B /* CombineMoya */, 6273DD44265F4195009C1D0B /* CombineMoya */,
621C637F26672A30004216EA /* NukeUI */,
); );
productName = JellyfinPlayer; productName = JellyfinPlayer;
productReference = 5377CBF1263B596A003A4E83 /* JellyfinPlayer.app */; productReference = 5377CBF1263B596A003A4E83 /* JellyfinPlayer.app */;
@ -335,10 +335,10 @@
5338F752263B65E10014BF09 /* XCRemoteSwiftPackageReference "SwiftyRequest" */, 5338F752263B65E10014BF09 /* XCRemoteSwiftPackageReference "SwiftyRequest" */,
5338F755263B7E2E0014BF09 /* XCRemoteSwiftPackageReference "keychain-swift" */, 5338F755263B7E2E0014BF09 /* XCRemoteSwiftPackageReference "keychain-swift" */,
53892778263CBFE70035E14B /* XCRemoteSwiftPackageReference "SwiftyJSON" */, 53892778263CBFE70035E14B /* XCRemoteSwiftPackageReference "SwiftyJSON" */,
538CD952263E3DC100BB5AF0 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */,
5302F8282658791C00647A2E /* XCRemoteSwiftPackageReference "sentry-cocoa" */, 5302F8282658791C00647A2E /* XCRemoteSwiftPackageReference "sentry-cocoa" */,
5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, 5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
6273DD41265F4195009C1D0B /* XCRemoteSwiftPackageReference "Moya" */, 6273DD41265F4195009C1D0B /* XCRemoteSwiftPackageReference "Moya" */,
621C637E26672A30004216EA /* XCRemoteSwiftPackageReference "NukeUI" */,
); );
productRefGroup = 5377CBF2263B596A003A4E83 /* Products */; productRefGroup = 5377CBF2263B596A003A4E83 /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -535,7 +535,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 32; CURRENT_PROJECT_VERSION = 32;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 4BHXT8RHFR;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
EXCLUDED_ARCHS = ""; EXCLUDED_ARCHS = "";
@ -562,7 +562,7 @@
CURRENT_PROJECT_VERSION = 32; CURRENT_PROJECT_VERSION = 32;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = 9R8RREG67J; DEVELOPMENT_TEAM = 4BHXT8RHFR;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
EXCLUDED_ARCHS = ""; EXCLUDED_ARCHS = "";
@ -644,12 +644,12 @@
minimumVersion = 5.0.1; minimumVersion = 5.0.1;
}; };
}; };
538CD952263E3DC100BB5AF0 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = { 621C637E26672A30004216EA /* XCRemoteSwiftPackageReference "NukeUI" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SDWebImage/SDWebImageSwiftUI"; repositoryURL = "https://github.com/kean/NukeUI";
requirement = { requirement = {
kind = upToNextMajorVersion; branch = main;
minimumVersion = 2.0.2; kind = branch;
}; };
}; };
6273DD41265F4195009C1D0B /* XCRemoteSwiftPackageReference "Moya" */ = { 6273DD41265F4195009C1D0B /* XCRemoteSwiftPackageReference "Moya" */ = {
@ -688,10 +688,10 @@
package = 53892778263CBFE70035E14B /* XCRemoteSwiftPackageReference "SwiftyJSON" */; package = 53892778263CBFE70035E14B /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
productName = SwiftyJSON; productName = SwiftyJSON;
}; };
538CD953263E3DC100BB5AF0 /* SDWebImageSwiftUI */ = { 621C637F26672A30004216EA /* NukeUI */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 538CD952263E3DC100BB5AF0 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */; package = 621C637E26672A30004216EA /* XCRemoteSwiftPackageReference "NukeUI" */;
productName = SDWebImageSwiftUI; productName = NukeUI;
}; };
6273DD42265F4195009C1D0B /* Moya */ = { 6273DD42265F4195009C1D0B /* Moya */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;

View File

@ -28,6 +28,15 @@
"version": "5.0.200" "version": "5.0.200"
} }
}, },
{
"package": "Gifu",
"repositoryURL": "https://github.com/kaishin/Gifu",
"state": {
"branch": null,
"revision": "0ffe24744cc3d82ab9edece53670d0352c6d5507",
"version": "3.3.0"
}
},
{ {
"package": "KeychainSwift", "package": "KeychainSwift",
"repositoryURL": "https://github.com/evgenyneu/keychain-swift", "repositoryURL": "https://github.com/evgenyneu/keychain-swift",
@ -55,6 +64,24 @@
"version": "15.0.0-alpha.1" "version": "15.0.0-alpha.1"
} }
}, },
{
"package": "Nuke",
"repositoryURL": "https://github.com/kean/Nuke.git",
"state": {
"branch": null,
"revision": "2775239e10e23c0b70c5544b98c2af7f65c2bbd9",
"version": "10.0.1"
}
},
{
"package": "NukeUI",
"repositoryURL": "https://github.com/kean/NukeUI",
"state": {
"branch": "main",
"revision": "27dcb9065a18450ba47ecd46a913a74646d95144",
"version": null
}
},
{ {
"package": "ReactiveSwift", "package": "ReactiveSwift",
"repositoryURL": "https://github.com/Moya/ReactiveSwift.git", "repositoryURL": "https://github.com/Moya/ReactiveSwift.git",
@ -73,24 +100,6 @@
"version": "5.1.2" "version": "5.1.2"
} }
}, },
{
"package": "SDWebImage",
"repositoryURL": "https://github.com/SDWebImage/SDWebImage.git",
"state": {
"branch": null,
"revision": "76dd4b49110b8624317fc128e7fa0d8a252018bc",
"version": "5.11.1"
}
},
{
"package": "SDWebImageSwiftUI",
"repositoryURL": "https://github.com/SDWebImage/SDWebImageSwiftUI",
"state": {
"branch": null,
"revision": "cd8625b7cf11a97698e180d28bb7d5d357196678",
"version": "2.0.2"
}
},
{ {
"package": "Sentry", "package": "Sentry",
"repositoryURL": "https://github.com/getsentry/sentry-cocoa", "repositoryURL": "https://github.com/getsentry/sentry-cocoa",

View File

@ -12,7 +12,7 @@ import SwiftyJSON
import CoreData import CoreData
import KeychainSwift import KeychainSwift
import Sentry import Sentry
import SDWebImageSwiftUI import NukeUI
class publicUser: ObservableObject { class publicUser: ObservableObject {
@Published var username: String = ""; @Published var username: String = "";
@ -320,9 +320,8 @@ struct ConnectToServerView: View {
Text(pubuser.username).font(.subheadline).fontWeight(.semibold) Text(pubuser.username).font(.subheadline).fontWeight(.semibold)
Spacer() Spacer()
if(pubuser.primaryImageTag != "") { if(pubuser.primaryImageTag != "") {
WebImage(url: URL(string: "\(uri)/Users/\(pubuser.id)/Images/Primary?width=200&quality=80&tag=\(pubuser.primaryImageTag)")!) LazyImage(source: URL(string: "\(uri)/Users/\(pubuser.id)/Images/Primary?width=200&quality=80&tag=\(pubuser.primaryImageTag)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size .contentMode(.aspectFill)
.aspectRatio(contentMode: .fill)
.frame(width: 60, height: 60) .frame(width: 60, height: 60)
.cornerRadius(30.0) .cornerRadius(30.0)
.shadow(radius: 6) .shadow(radius: 6)

View File

@ -8,10 +8,10 @@
import SwiftUI import SwiftUI
import KeychainSwift import KeychainSwift
import SDWebImageSwiftUI
import Sentry import Sentry
import SwiftyJSON import SwiftyJSON
import SwiftyRequest import SwiftyRequest
import Nuke
struct ContentView: View { struct ContentView: View {
@Environment(\.managedObjectContext) @Environment(\.managedObjectContext)
@ -75,12 +75,15 @@ struct ContentView: View {
options.releaseName = "ios-" + (Bundle.main.infoDictionary?["CFBundleVersion"] as! String) options.releaseName = "ios-" + (Bundle.main.infoDictionary?["CFBundleVersion"] as! String)
options.enableOutOfMemoryTracking = true options.enableOutOfMemoryTracking = true
} }
ImageCache.shared.costLimit = 125 * 1024 * 1024 // 125MB memory
DataLoader.sharedUrlCache.diskCapacity = 1000 * 1024 * 1024 // 1000MB disk
let cache = SDImageCache(namespace: "tiny") // let cache = SDImageCache(namespace: "tiny")
cache.config.maxMemoryCost = 125 * 1024 * 1024 // 125MB memory // cache.config.maxMemoryCost = 125 * 1024 * 1024 // 125MB memory
cache.config.maxDiskSize = 1000 * 1024 * 1024 // 1000MB disk // cache.config.maxDiskSize = 1000 * 1024 * 1024 // 1000MB disk
SDImageCachesManager.shared.addCache(cache) // SDImageCachesManager.shared.addCache(cache)
SDWebImageManager.defaultImageCache = SDImageCachesManager.shared // SDWebImageManager.defaultImageCache = SDImageCachesManager.shared
_libraries.wrappedValue = [] _libraries.wrappedValue = []
_library_names.wrappedValue = [:] _library_names.wrappedValue = [:]

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
import SwiftyRequest import SwiftyRequest
import SwiftyJSON import SwiftyJSON
import SDWebImageSwiftUI import NukeUI
struct CustomShape: Shape { struct CustomShape: Shape {
let radius: CGFloat let radius: CGFloat
@ -115,8 +115,7 @@ struct ContinueWatchingView: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Spacer().frame(height: 10) Spacer().frame(height: 10)
if(item.Type == "Episode") { if(item.Type == "Episode") {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 48, height: 32))!) Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 48, height: 32))!)
.resizable() .resizable()
@ -144,8 +143,7 @@ struct ContinueWatchingView: View {
.padding(0), alignment: .bottomLeading .padding(0), alignment: .bottomLeading
) )
} else { } else {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 48, height: 32))!) Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 48, height: 32))!)
.resizable() .resizable()

View File

@ -5,10 +5,10 @@
// Created by Aiden Vigue on 5/13/21. // Created by Aiden Vigue on 5/13/21.
// //
import SDWebImageSwiftUI
import SwiftUI import SwiftUI
import SwiftyJSON import SwiftyJSON
import SwiftyRequest import SwiftyRequest
import NukeUI
struct EpisodeItemView: View { struct EpisodeItemView: View {
@EnvironmentObject @EnvironmentObject
@ -204,8 +204,7 @@ struct EpisodeItemView: View {
var portraitHeaderView: some View { var portraitHeaderView: some View {
VStack { VStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.ParentBackdropItemId)/Images/Backdrop?maxWidth=550&quality=90&tag=\(fullItem.Backdrop)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.ParentBackdropItemId)/Images/Backdrop?maxWidth=550&quality=90&tag=\(fullItem.Backdrop)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem .BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
@ -213,9 +212,8 @@ struct EpisodeItemView: View {
size: CGSize(width: 32, height: 32))!) size: CGSize(width: 32, height: 32))!)
.resizable() .resizable()
} }
.contentMode(.aspectFill)
.opacity(0.3) .opacity(0.3)
.aspectRatio(contentMode: .fill)
.shadow(radius: 5) .shadow(radius: 5)
} }
} }
@ -223,8 +221,7 @@ struct EpisodeItemView: View {
var portraitHeaderOverlayView: some View { var portraitHeaderOverlayView: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack(alignment: .bottom, spacing: 12) { HStack(alignment: .bottom, spacing: 12) {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : .PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" :
@ -233,7 +230,8 @@ struct EpisodeItemView: View {
.resizable() .resizable()
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
}.aspectRatio(contentMode: .fill) }
.contentMode(.aspectFill)
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
VStack(alignment: .leading) { VStack(alignment: .leading) {
@ -365,8 +363,7 @@ struct EpisodeItemView: View {
])), title: cast.Name) ])), title: cast.Name)
}) { }) {
VStack { VStack {
WebImage(url: cast.Image) LazyImage(source: cast.Image)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: cast Image(uiImage: UIImage(blurHash: cast
.ImageBlurHash == "" ? .ImageBlurHash == "" ?
@ -379,7 +376,8 @@ struct EpisodeItemView: View {
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
} }
.aspectRatio(contentMode: .fill)
.contentMode(.aspectFill)
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1) Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1)
@ -424,8 +422,7 @@ struct EpisodeItemView: View {
} else { } else {
GeometryReader { geometry in GeometryReader { geometry in
ZStack { ZStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.ParentBackdropItemId)/Images/Backdrop?maxWidth=\(String(Int(geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing)))&quality=80&tag=\(fullItem.Backdrop)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.ParentBackdropItemId)/Images/Backdrop?maxWidth=\(String(Int(geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing)))&quality=80&tag=\(fullItem.Backdrop)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem .BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
@ -437,17 +434,16 @@ struct EpisodeItemView: View {
height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets
.bottom) .bottom)
} }
.contentMode(.aspectFill)
.opacity(0.3) .opacity(0.3)
.aspectRatio(contentMode: .fill)
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing,
height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom) height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom)
.edgesIgnoringSafeArea(.all) .edgesIgnoringSafeArea(.all)
.blur(radius: 2) .blur(radius: 2)
HStack { HStack {
VStack { VStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : .PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" :
@ -456,7 +452,7 @@ struct EpisodeItemView: View {
.resizable() .resizable()
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
} }
.aspectRatio(contentMode: .fill) .contentMode(.fill)
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
.shadow(radius: 5) .shadow(radius: 5)
@ -585,8 +581,7 @@ struct EpisodeItemView: View {
])), title: cast.Name) ])), title: cast.Name)
}) { }) {
VStack { VStack {
WebImage(url: cast.Image) LazyImage(source: cast.Image)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: cast Image(uiImage: UIImage(blurHash: cast
.ImageBlurHash == "" ? .ImageBlurHash == "" ?
@ -599,7 +594,7 @@ struct EpisodeItemView: View {
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
} }
.aspectRatio(contentMode: .fill) .contentMode(.aspectFill)
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1) Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1)

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
import SwiftyRequest import SwiftyRequest
import SwiftyJSON import SwiftyJSON
import SDWebImageSwiftUI import NukeUI
struct LatestMediaView: View { struct LatestMediaView: View {
@Environment(\.managedObjectContext) private var viewContext @Environment(\.managedObjectContext) private var viewContext
@ -91,8 +91,7 @@ struct LatestMediaView: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
if(item.Type == "Series") { if(item.Type == "Series") {
Spacer().frame(height:10) Spacer().frame(height:10)
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!) Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
.resizable() .resizable()
@ -122,8 +121,7 @@ struct LatestMediaView: View {
) )
} else { } else {
Spacer().frame(height:10) Spacer().frame(height:10)
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!) Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
.resizable() .resizable()

View File

@ -5,10 +5,10 @@
// Created by Aiden Vigue on 5/2/21. // Created by Aiden Vigue on 5/2/21.
// //
import SDWebImageSwiftUI
import SwiftUI import SwiftUI
import SwiftyJSON import SwiftyJSON
import SwiftyRequest import SwiftyRequest
import NukeUI
struct LibrarySearchView: View { struct LibrarySearchView: View {
@Environment(\.managedObjectContext) @Environment(\.managedObjectContext)
@ -68,7 +68,7 @@ struct LibrarySearchView: View {
} }
} }
if viewModel.isLoading { if viewModel.isLoading {
ActivityIndicator($viewModel.isLoading) ProgressView()
} else if viewModel.items.isEmpty { } else if viewModel.items.isEmpty {
Text("Empty Response") Text("Empty Response")
} }
@ -87,8 +87,7 @@ struct ResumeItemGridCell: View {
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
if item.Type == "Movie" { if item.Type == "Movie" {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)"))
.resizable()
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: item Image(uiImage: UIImage(blurHash: item
.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item .BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item
@ -101,8 +100,7 @@ struct ResumeItemGridCell: View {
.frame(width: 100, height: 150) .frame(width: 100, height: 150)
.cornerRadius(10) .cornerRadius(10)
} else { } else {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)")) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?fillWidth=300&fillHeight=450&quality=90&tag=\(item.Image)"))
.resizable()
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: item Image(uiImage: UIImage(blurHash: item
.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item .BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item

View File

@ -5,8 +5,8 @@
// Created by Aiden Vigue on 5/1/21. // Created by Aiden Vigue on 5/1/21.
// //
import SDWebImageSwiftUI
import SwiftUI import SwiftUI
import NukeUI
struct LibraryView: View { struct LibraryView: View {
@Environment(\.managedObjectContext) @Environment(\.managedObjectContext)
@ -87,7 +87,7 @@ struct LibraryView: View {
recalcTracks() recalcTracks()
} }
if viewModel.isLoading { if viewModel.isLoading {
ActivityIndicator($viewModel.isLoading) ProgressView()
} else if viewModel.items.isEmpty { } else if viewModel.items.isEmpty {
Text("Empty Response") Text("Empty Response")
} }
@ -136,8 +136,7 @@ extension LibraryView {
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
if item.Type == "Movie" { if item.Type == "Movie" {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable()
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: item Image(uiImage: UIImage(blurHash: item
.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item .BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item
@ -150,8 +149,7 @@ extension LibraryView {
.frame(width: 100, height: 150) .frame(width: 100, height: 150)
.cornerRadius(10) .cornerRadius(10)
} else { } else {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable()
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: item Image(uiImage: UIImage(blurHash: item
.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item .BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item

View File

@ -5,10 +5,10 @@
// Created by Aiden Vigue on 5/13/21. // Created by Aiden Vigue on 5/13/21.
// //
import SDWebImageSwiftUI
import SwiftUI import SwiftUI
import SwiftyJSON import SwiftyJSON
import SwiftyRequest import SwiftyRequest
import NukeUI
class DetailItem: ObservableObject { class DetailItem: ObservableObject {
@Published @Published
@ -293,8 +293,7 @@ struct MovieItemView: View {
} }
var portraitHeaderView: some View { var portraitHeaderView: some View {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=550&quality=90&tag=\(fullItem.Backdrop)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=550&quality=90&tag=\(fullItem.Backdrop)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem .BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
@ -302,17 +301,15 @@ struct MovieItemView: View {
size: CGSize(width: 32, height: 32))!) size: CGSize(width: 32, height: 32))!)
.resizable() .resizable()
} }
.contentMode(.aspectFill)
.opacity(0.3) .opacity(0.3)
.aspectRatio(contentMode: .fill)
.shadow(radius: 5) .shadow(radius: 5)
} }
var portraitHeaderOverlayView: some View { var portraitHeaderOverlayView: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack(alignment: .bottom, spacing: 12) { HStack(alignment: .bottom, spacing: 12) {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : .PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" :
@ -321,7 +318,8 @@ struct MovieItemView: View {
.resizable() .resizable()
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
}.aspectRatio(contentMode: .fill) }
.contentMode(.aspectFill)
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
VStack(alignment: .leading) { VStack(alignment: .leading) {
@ -454,8 +452,7 @@ struct MovieItemView: View {
])), title: cast.Name) ])), title: cast.Name)
}) { }) {
VStack { VStack {
WebImage(url: cast.Image) LazyImage(source: cast.Image)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: cast Image(uiImage: UIImage(blurHash: cast
.ImageBlurHash == "" ? .ImageBlurHash == "" ?
@ -468,7 +465,7 @@ struct MovieItemView: View {
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
} }
.aspectRatio(contentMode: .fill) .contentMode(.aspectFill)
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1) Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1)
@ -513,8 +510,7 @@ struct MovieItemView: View {
} else { } else {
GeometryReader { geometry in GeometryReader { geometry in
ZStack { ZStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=\(String(Int(geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing)))&quality=80&tag=\(fullItem.Backdrop)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Backdrop?maxWidth=\(String(Int(geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing)))&quality=80&tag=\(fullItem.Backdrop)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem .BackdropBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
@ -526,17 +522,16 @@ struct MovieItemView: View {
height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets
.bottom) .bottom)
} }
.contentMode(.aspectFill)
.opacity(0.3) .opacity(0.3)
.aspectRatio(contentMode: .fill)
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing, .frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing,
height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom) height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom)
.edgesIgnoringSafeArea(.all) .edgesIgnoringSafeArea(.all)
.blur(radius: 2) .blur(radius: 2)
HStack { HStack {
VStack { VStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : .PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" :
@ -674,8 +669,7 @@ struct MovieItemView: View {
])), title: cast.Name) ])), title: cast.Name)
}) { }) {
VStack { VStack {
WebImage(url: cast.Image) LazyImage(source: cast.Image)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: cast Image(uiImage: UIImage(blurHash: cast
.ImageBlurHash == "" ? .ImageBlurHash == "" ?
@ -688,7 +682,7 @@ struct MovieItemView: View {
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
} }
.aspectRatio(contentMode: .fill) .contentMode(.aspectFill)
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.cornerRadius(10) .cornerRadius(10)
Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1) Text(cast.Name).font(.footnote).fontWeight(.regular).lineLimit(1)

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
import SwiftyRequest import SwiftyRequest
import SwiftyJSON import SwiftyJSON
import SDWebImageSwiftUI import NukeUI
struct NextUpView: View { struct NextUpView: View {
@Environment(\.managedObjectContext) private var viewContext @Environment(\.managedObjectContext) private var viewContext
@ -79,8 +79,7 @@ struct NextUpView: View {
NavigationLink(destination: ItemView(item: item)) { NavigationLink(destination: ItemView(item: item)) {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Spacer().frame(height:10) Spacer().frame(height:10)
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.SeriesId ?? "")/Images/\(item.ImageType)?maxWidth=250&quality=80&tag=\(item.Image)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!) Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 16, height: 16))!)
.resizable() .resizable()

View File

@ -5,7 +5,7 @@
// Created by Aiden Vigue on 5/13/21. // Created by Aiden Vigue on 5/13/21.
// //
import SDWebImageSwiftUI import NukeUI
import SwiftUI import SwiftUI
import SwiftyJSON import SwiftyJSON
import SwiftyRequest import SwiftyRequest
@ -186,8 +186,7 @@ struct SeasonItemView: View {
} }
var portraitHeaderView: some View { var portraitHeaderView: some View {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Backdrop?maxWidth=750&quality=80&tag=\(item.SeasonImage ?? "")")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Backdrop?maxWidth=750&quality=90&tag=\(item.SeasonImage ?? "")"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: item Image(uiImage: UIImage(blurHash: item
.SeasonImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item .SeasonImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item
@ -195,15 +194,31 @@ struct SeasonItemView: View {
size: CGSize(width: 32, height: 32))!) size: CGSize(width: 32, height: 32))!)
.resizable() .resizable()
} }
.failure{
Image(uiImage: UIImage(blurHash: item
.SeasonImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item
.SeasonImageBlurHash ?? "",
size: CGSize(width: 32, height: 32))!)
.resizable()
}
.contentMode(.aspectFill)
.onStart { print("onStart \($0.request.url)") }
.onProgress { _,_,_ in print("onProgress") }
.onSuccess { _ in print("onSuccess") }
.onFailure { error in
print(error.dataLoadingError?.localizedDescription)
print(error.description)
print(error.localizedDescription)
}
.onCompletion { _ in print("onCompletion") }
.frame(minWidth: 0, maxWidth: .infinity)
.opacity(0.4) .opacity(0.4)
.aspectRatio(contentMode: .fill)
.shadow(radius: 5) .shadow(radius: 5)
} }
var portraitHeaderOverlayView: some View { var portraitHeaderOverlayView: some View {
HStack(alignment: .bottom, spacing: 12) { HStack(alignment: .bottom, spacing: 12) {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: fullItem Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem .PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
@ -212,7 +227,8 @@ struct SeasonItemView: View {
.resizable() .resizable()
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
}.aspectRatio(contentMode: .fill) }
.contentMode(.aspectFill)
.frame(width: 120, height: 180) .frame(width: 120, height: 180)
.cornerRadius(10) .cornerRadius(10)
VStack(alignment: .leading) { VStack(alignment: .leading) {
@ -237,31 +253,155 @@ struct SeasonItemView: View {
.padding(.bottom, -22) .padding(.bottom, -22)
} }
var body: some View { @ViewBuilder
VStack(alignment: .leading) { var innerBody: some View {
LoadingView(isShowing: $isLoading) { if orientationInfo.orientation == .portrait {
VStack(alignment: .leading) { ParallaxHeaderScrollView(header: portraitHeaderView,
if orientationInfo.orientation == .portrait { staticOverlayView: portraitHeaderOverlayView,
ParallaxHeaderScrollView(header: portraitHeaderView, overlayAlignment: .bottomLeading,
staticOverlayView: portraitHeaderOverlayView, headerHeight: UIScreen.main.bounds.width * 0.5625) {
overlayAlignment: .bottomLeading, LazyVStack(alignment: .leading) {
headerHeight: UIScreen.main.bounds.width * 0.5625) { Spacer()
VStack(alignment: .leading) { .frame(height: 22)
Spacer() if fullItem.Tagline != "" {
.frame(height: 22) Text(fullItem.Tagline).font(.body).italic().padding(.top, 7)
.fixedSize(horizontal: false, vertical: true).padding(.leading, 16)
.padding(.trailing, 16)
}
Text(fullItem.Overview).font(.footnote).padding(.top, 3)
.fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16)
.padding(.trailing, 16)
ForEach(episodes, id: \.Id) { episode in
NavigationLink(destination: ItemView(item: episode.ResumeItem ?? ResumeItem())) {
HStack {
LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(episode.Id)/Images/Primary?maxWidth=300&quality=90&tag=\(episode.Poster)"))
.placeholder {
Image(uiImage: UIImage(blurHash: episode
.PosterBlurHash == "" ?
"W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
.PosterBlurHash,
size: CGSize(width: 32, height: 32))!)
.resizable()
.frame(width: 150, height: 90)
.cornerRadius(10)
}
.contentMode(.aspectFill)
.shadow(radius: 5)
.frame(width: 150, height: 90)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10, style: .circular)
.fill(Color(red: 172 / 255, green: 92 / 255, blue: 195 / 255)
.opacity(0.4))
.frame(width: CGFloat((episode.Progress / Double(episode.RuntimeTicks)) *
150),
height: 90)
.padding(0), alignment: .bottomLeading)
VStack(alignment: .leading) {
HStack {
Text(episode.Name).font(.subheadline)
.fontWeight(.semibold)
.foregroundColor(.primary)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(1)
Spacer()
Text(episode.Runtime).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
.lineLimit(1)
}
Spacer()
Text(episode.Overview).font(.footnote).foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true).lineLimit(4)
Spacer()
}.padding(.trailing, 20).offset(y: 2)
}.offset(x: 12, y: 0)
}
}
if !fullItem.Directors.isEmpty {
HStack {
Text("Directors:").font(.callout).fontWeight(.semibold)
Text(fullItem.Directors.joined(separator: ", ")).font(.footnote).lineLimit(1)
.foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16)
}
if !fullItem.Writers.isEmpty {
HStack {
Text("Writers:").font(.callout).fontWeight(.semibold)
Text(fullItem.Writers.joined(separator: ", ")).font(.footnote).lineLimit(1)
.foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16)
}
if !fullItem.Studios.isEmpty {
HStack {
Text("Studios:").font(.callout).fontWeight(.semibold)
Text(fullItem.Studios.joined(separator: ", ")).font(.footnote).lineLimit(1)
.foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16)
}
Spacer().frame(height: 3)
}
}
} else {
GeometryReader { geometry in
ZStack {
LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Backdrop?maxWidth=\(String(Int(geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing)))&quality=80&tag=\(item.SeasonImage ?? "")"))
.placeholder {
Image(uiImage: UIImage(blurHash: item
.SeasonImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item
.SeasonImageBlurHash ?? "",
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)
.opacity(0.4)
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing,
height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom)
.edgesIgnoringSafeArea(.all)
.blur(radius: 2)
HStack {
VStack(alignment: .leading) {
LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)"))
.placeholder {
Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" :
fullItem.PosterBlurHash,
size: CGSize(width: 32, height: 32))!)
.resizable()
.frame(width: 120, height: 180)
.cornerRadius(10)
}
.contentMode(.aspectFill)
.frame(width: 120, height: 180)
.cornerRadius(10)
Spacer().frame(height: 4)
if fullItem.ProductionYear != 0 {
Text(String(fullItem.ProductionYear)).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
}
Spacer()
}
ScrollView {
LazyVStack(alignment: .leading) {
if fullItem.Tagline != "" { if fullItem.Tagline != "" {
Text(fullItem.Tagline).font(.body).italic().padding(.top, 7) Text(fullItem.Tagline).font(.body).italic().padding(.top, 3)
.fixedSize(horizontal: false, vertical: true).padding(.leading, 16) .fixedSize(horizontal: false, vertical: true).padding(.leading, 16)
.padding(.trailing, 16) .padding(.trailing, 16)
} }
Text(fullItem.Overview).font(.footnote).padding(.top, 3) if fullItem.Overview != "" {
.fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16) Text(fullItem.Overview).font(.footnote).padding(.top, 3)
.padding(.trailing, 16) .fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16)
.padding(.trailing, 16)
}
ForEach(episodes, id: \.Id) { episode in ForEach(episodes, id: \.Id) { episode in
NavigationLink(destination: ItemView(item: episode.ResumeItem ?? ResumeItem())) { NavigationLink(destination: ItemView(item: episode.ResumeItem ?? ResumeItem())) {
HStack { HStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(episode.Id)/Images/Primary?maxWidth=300&quality=90&tag=\(episode.Poster)")!) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(episode.Id)/Images/Primary?maxWidth=300&quality=90&tag=\(episode.Poster)"))
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: episode Image(uiImage: UIImage(blurHash: episode
.PosterBlurHash == "" ? .PosterBlurHash == "" ?
@ -271,7 +411,8 @@ struct SeasonItemView: View {
.resizable() .resizable()
.frame(width: 150, height: 90) .frame(width: 150, height: 90)
.cornerRadius(10) .cornerRadius(10)
}.aspectRatio(contentMode: .fill) }
.contentMode(.aspectFill)
.shadow(radius: 5) .shadow(radius: 5)
.frame(width: 150, height: 90) .frame(width: 150, height: 90)
.cornerRadius(10) .cornerRadius(10)
@ -289,11 +430,30 @@ struct SeasonItemView: View {
.foregroundColor(.primary) .foregroundColor(.primary)
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
.lineLimit(1) .lineLimit(1)
Spacer()
Text(episode.Runtime).font(.subheadline) Text(episode.Runtime).font(.subheadline)
.fontWeight(.medium) .fontWeight(.medium)
.foregroundColor(.secondary) .foregroundColor(.secondary)
.lineLimit(1) .lineLimit(1)
if episode.OfficialRating != "" {
Text(episode.OfficialRating).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
.lineLimit(1)
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
.overlay(RoundedRectangle(cornerRadius: 2)
.stroke(Color.secondary, lineWidth: 1))
}
if episode.CommunityRating != "" {
HStack {
Image(systemName: "star").foregroundColor(.secondary)
Text(episode.CommunityRating).font(.subheadline)
.fontWeight(.semibold)
.foregroundColor(.secondary)
.lineLimit(1)
.offset(x: -6, y: 0)
}
}
Spacer()
} }
Spacer() Spacer()
Text(episode.Overview).font(.footnote).foregroundColor(.secondary) Text(episode.Overview).font(.footnote).foregroundColor(.secondary)
@ -324,163 +484,19 @@ struct SeasonItemView: View {
.foregroundColor(Color.secondary) .foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16) }.padding(.leading, 16).padding(.trailing, 16)
} }
Spacer().frame(height: 3) Spacer().frame(height: 125)
} }.frame(maxHeight: .infinity)
} }.padding(.trailing, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 55)
} else { }.padding(.top, 16).padding(.leading, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 0)
GeometryReader { geometry in
ZStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.SeriesId ?? "")/Images/Backdrop?maxWidth=\(String(Int(geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing)))&quality=80&tag=\(item.SeasonImage ?? "")")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
Image(uiImage: UIImage(blurHash: item
.SeasonImageBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item
.SeasonImageBlurHash ?? "",
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)
}
.opacity(0.4)
.aspectRatio(contentMode: .fill)
.frame(width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing,
height: geometry.size.height + geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom)
.edgesIgnoringSafeArea(.all)
.blur(radius: 2)
HStack {
VStack(alignment: .leading) {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(fullItem.Id)/Images/Primary?maxWidth=250&quality=90&tag=\(fullItem.Poster)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
Image(uiImage: UIImage(blurHash: fullItem
.PosterBlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" :
fullItem.PosterBlurHash,
size: CGSize(width: 32, height: 32))!)
.resizable()
.frame(width: 120, height: 180)
.cornerRadius(10)
}.aspectRatio(contentMode: .fill)
.frame(width: 120, height: 180)
.cornerRadius(10)
Spacer().frame(height: 4)
if fullItem.ProductionYear != 0 {
Text(String(fullItem.ProductionYear)).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
}
Spacer()
}
ScrollView {
VStack(alignment: .leading) {
if fullItem.Tagline != "" {
Text(fullItem.Tagline).font(.body).italic().padding(.top, 3)
.fixedSize(horizontal: false, vertical: true).padding(.leading, 16)
.padding(.trailing, 16)
}
if fullItem.Overview != "" {
Text(fullItem.Overview).font(.footnote).padding(.top, 3)
.fixedSize(horizontal: false, vertical: true).padding(.bottom, 3).padding(.leading, 16)
.padding(.trailing, 16)
}
ForEach(episodes, id: \.Id) { episode in
NavigationLink(destination: ItemView(item: episode.ResumeItem ?? ResumeItem())) {
HStack {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(episode.Id)/Images/Primary?maxWidth=300&quality=90&tag=\(episode.Poster)")!)
.resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size
.placeholder {
Image(uiImage: UIImage(blurHash: episode
.PosterBlurHash == "" ?
"W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : fullItem
.PosterBlurHash,
size: CGSize(width: 32, height: 32))!)
.resizable()
.frame(width: 150, height: 90)
.cornerRadius(10)
}.aspectRatio(contentMode: .fill)
.shadow(radius: 5)
.frame(width: 150, height: 90)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10, style: .circular)
.fill(Color(red: 172 / 255, green: 92 / 255, blue: 195 / 255)
.opacity(0.4))
.frame(width: CGFloat((episode.Progress / Double(episode.RuntimeTicks)) *
150),
height: 90)
.padding(0), alignment: .bottomLeading)
VStack(alignment: .leading) {
HStack {
Text(episode.Name).font(.subheadline)
.fontWeight(.semibold)
.foregroundColor(.primary)
.fixedSize(horizontal: false, vertical: true)
.lineLimit(1)
Text(episode.Runtime).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
.lineLimit(1)
if episode.OfficialRating != "" {
Text(episode.OfficialRating).font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.secondary)
.lineLimit(1)
.padding(EdgeInsets(top: 1, leading: 4, bottom: 1, trailing: 4))
.overlay(RoundedRectangle(cornerRadius: 2)
.stroke(Color.secondary, lineWidth: 1))
}
if episode.CommunityRating != "" {
HStack {
Image(systemName: "star").foregroundColor(.secondary)
Text(episode.CommunityRating).font(.subheadline)
.fontWeight(.semibold)
.foregroundColor(.secondary)
.lineLimit(1)
.offset(x: -6, y: 0)
}
}
Spacer()
}
Spacer()
Text(episode.Overview).font(.footnote).foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true).lineLimit(4)
Spacer()
}.padding(.trailing, 20).offset(y: 2)
}.offset(x: 12, y: 0)
}
}
if !fullItem.Directors.isEmpty {
HStack {
Text("Directors:").font(.callout).fontWeight(.semibold)
Text(fullItem.Directors.joined(separator: ", ")).font(.footnote).lineLimit(1)
.foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16)
}
if !fullItem.Writers.isEmpty {
HStack {
Text("Writers:").font(.callout).fontWeight(.semibold)
Text(fullItem.Writers.joined(separator: ", ")).font(.footnote).lineLimit(1)
.foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16)
}
if !fullItem.Studios.isEmpty {
HStack {
Text("Studios:").font(.callout).fontWeight(.semibold)
Text(fullItem.Studios.joined(separator: ", ")).font(.footnote).lineLimit(1)
.foregroundColor(Color.secondary)
}.padding(.leading, 16).padding(.trailing, 16)
}
Spacer().frame(height: 125)
}.frame(maxHeight: .infinity)
}.padding(.trailing, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 55)
}.padding(.top, 16).padding(.leading, UIDevice.current.userInterfaceIdiom == .pad ? 16 : 0)
}
}
}
} }
} }
} }
}
var body: some View {
LoadingView(isShowing: $isLoading) {
innerBody
}
.onAppear(perform: loadData) .onAppear(perform: loadData)
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.navigationTitle("\(item.Name) - \(item.SeriesName ?? "")") .navigationTitle("\(item.Name) - \(item.SeriesName ?? "")")

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
import SwiftyRequest import SwiftyRequest
import SwiftyJSON import SwiftyJSON
import SDWebImageSwiftUI import NukeUI
struct SeriesItemView: View { struct SeriesItemView: View {
@EnvironmentObject var globalData: GlobalData @EnvironmentObject var globalData: GlobalData
@ -96,8 +96,7 @@ struct SeriesItemView: View {
ForEach(items, id: \.Id) { item in ForEach(items, id: \.Id) { item in
NavigationLink(destination: ItemView(item: item )) { NavigationLink(destination: ItemView(item: item )) {
VStack(alignment: .leading) { VStack(alignment: .leading) {
WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=90&tag=\(item.Image)")) LazyImage(source: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=250&quality=90&tag=\(item.Image)"))
.resizable()
.placeholder { .placeholder {
Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!) Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 32, height: 32))!)
.resizable() .resizable()