Merge branch 'main' into multi-server-url

This commit is contained in:
aiden 3 2021-11-21 12:42:05 -05:00 committed by GitHub
commit 9ba5ab8417
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 111 additions and 66 deletions

View File

@ -199,6 +199,9 @@
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */; }; 62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */; };
62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */; }; 62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */; };
62C29EA826D103D500C1D2E7 /* LibraryListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */; }; 62C29EA826D103D500C1D2E7 /* LibraryListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */; };
62E1DCC3273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
62E1DCC4273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
62E1DCC5273CE19800C9AE76 /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */; };
62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */; }; 62E632DA267D2BC40063E547 /* LatestMediaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */; };
62E632DC267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E632DB267D2E130063E547 /* LibrarySearchViewModel.swift */; }; 62E632DC267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E632DB267D2E130063E547 /* LibrarySearchViewModel.swift */; };
62E632DD267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E632DB267D2E130063E547 /* LibrarySearchViewModel.swift */; }; 62E632DD267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E632DB267D2E130063E547 /* LibrarySearchViewModel.swift */; };
@ -536,6 +539,7 @@
62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerCoodinator.swift; sourceTree = "<group>"; }; 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerCoodinator.swift; sourceTree = "<group>"; };
62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCoordinator.swift; sourceTree = "<group>"; }; 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCoordinator.swift; sourceTree = "<group>"; };
62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListCoordinator.swift; sourceTree = "<group>"; }; 62C29EA726D103D500C1D2E7 /* LibraryListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListCoordinator.swift; sourceTree = "<group>"; };
62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtensions.swift; sourceTree = "<group>"; };
62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestMediaViewModel.swift; sourceTree = "<group>"; }; 62E632D9267D2BC40063E547 /* LatestMediaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestMediaViewModel.swift; sourceTree = "<group>"; };
62E632DB267D2E130063E547 /* LibrarySearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibrarySearchViewModel.swift; sourceTree = "<group>"; }; 62E632DB267D2E130063E547 /* LibrarySearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibrarySearchViewModel.swift; sourceTree = "<group>"; };
62E632DF267D30CA0063E547 /* LibraryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryViewModel.swift; sourceTree = "<group>"; }; 62E632DF267D30CA0063E547 /* LibraryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryViewModel.swift; sourceTree = "<group>"; };
@ -1062,6 +1066,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5389277B263CC3DB0035E14B /* BlurHashDecode.swift */, 5389277B263CC3DB0035E14B /* BlurHashDecode.swift */,
62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */,
6267B3D526710B8900A7371D /* CollectionExtensions.swift */, 6267B3D526710B8900A7371D /* CollectionExtensions.swift */,
E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */, E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */,
6267B3D92671138200A7371D /* ImageExtensions.swift */, 6267B3D92671138200A7371D /* ImageExtensions.swift */,
@ -1823,6 +1828,7 @@
E1AD104E26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */, E1AD104E26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */,
62E632DD267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */, 62E632DD267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */,
536D3D81267BDFC60004248C /* PortraitItemElement.swift in Sources */, 536D3D81267BDFC60004248C /* PortraitItemElement.swift in Sources */,
62E1DCC4273CE19800C9AE76 /* URLExtensions.swift in Sources */,
5310695B2684E7EE00CFFDBA /* AudioView.swift in Sources */, 5310695B2684E7EE00CFFDBA /* AudioView.swift in Sources */,
5398514726B64E4100101B49 /* SearchBarView.swift in Sources */, 5398514726B64E4100101B49 /* SearchBarView.swift in Sources */,
091B5A8D268315D400D78B61 /* ServerDiscovery.swift in Sources */, 091B5A8D268315D400D78B61 /* ServerDiscovery.swift in Sources */,
@ -1983,6 +1989,7 @@
535870AD2669D8DD00D05A09 /* Typings.swift in Sources */, 535870AD2669D8DD00D05A09 /* Typings.swift in Sources */,
E1AD105F26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */, E1AD105F26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */,
E13DD3D5271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */, E13DD3D5271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */,
62E1DCC3273CE19800C9AE76 /* URLExtensions.swift in Sources */,
C4BE0769271FC164003F4AD1 /* TVLibrariesView.swift in Sources */, C4BE0769271FC164003F4AD1 /* TVLibrariesView.swift in Sources */,
E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */, E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */,
6220D0BA26D6092100B8E046 /* FilterCoordinator.swift in Sources */, 6220D0BA26D6092100B8E046 /* FilterCoordinator.swift in Sources */,
@ -2031,6 +2038,7 @@
E13DD3D7271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */, E13DD3D7271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */,
E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */, E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */,
E13DD3CA27164B80009D4DAF /* SwiftfinStore.swift in Sources */, E13DD3CA27164B80009D4DAF /* SwiftfinStore.swift in Sources */,
62E1DCC5273CE19800C9AE76 /* URLExtensions.swift in Sources */,
62EC353226766849000E9F2D /* SessionManager.swift in Sources */, 62EC353226766849000E9F2D /* SessionManager.swift in Sources */,
536D3D79267BD5D00004248C /* ViewModel.swift in Sources */, 536D3D79267BD5D00004248C /* ViewModel.swift in Sources */,
E1D4BF8C2719F39F00A11E64 /* AppAppearance.swift in Sources */, E1D4BF8C2719F39F00A11E64 /* AppAppearance.swift in Sources */,

View File

@ -15,25 +15,25 @@ struct ItemLandscapeMainView: View {
@Binding private var videoIsLoading: Bool @Binding private var videoIsLoading: Bool
@EnvironmentObject private var viewModel: ItemViewModel @EnvironmentObject private var viewModel: ItemViewModel
@EnvironmentObject private var videoPlayerItem: VideoPlayerItem @EnvironmentObject private var videoPlayerItem: VideoPlayerItem
init(videoIsLoading: Binding<Bool>) { init(videoIsLoading: Binding<Bool>) {
self._videoIsLoading = videoIsLoading self._videoIsLoading = videoIsLoading
} }
// MARK: innerBody // MARK: innerBody
private var innerBody: some View { private var innerBody: some View {
HStack { HStack {
// MARK: Sidebar Image // MARK: Sidebar Image
VStack { VStack {
ImageView(src: viewModel.item.getPrimaryImage(maxWidth: 130), ImageView(src: viewModel.item.getPrimaryImage(maxWidth: 130),
bh: viewModel.item.getPrimaryImageBlurHash()) bh: viewModel.item.getPrimaryImageBlurHash())
.frame(width: 130, height: 195) .frame(width: 130, height: 195)
.cornerRadius(10) .cornerRadius(10)
Spacer().frame(height: 15) Spacer().frame(height: 15)
Button { Button {
if let playButtonItem = viewModel.playButtonItem { if let playButtonItem = viewModel.playButtonItem {
self.videoPlayerItem.itemToPlay = playButtonItem self.videoPlayerItem.itemToPlay = playButtonItem
@ -41,7 +41,7 @@ struct ItemLandscapeMainView: View {
} }
} label: { } label: {
// MARK: Play // MARK: Play
HStack { HStack {
Image(systemName: "play.fill") Image(systemName: "play.fill")
.foregroundColor(viewModel.playButtonItem == nil ? Color(UIColor.secondaryLabel) : Color.white) .foregroundColor(viewModel.playButtonItem == nil ? Color(UIColor.secondaryLabel) : Color.white)
@ -55,19 +55,19 @@ struct ItemLandscapeMainView: View {
.background(viewModel.playButtonItem == nil ? Color(UIColor.secondarySystemFill) : Color.jellyfinPurple) .background(viewModel.playButtonItem == nil ? Color(UIColor.secondarySystemFill) : Color.jellyfinPurple)
.cornerRadius(10) .cornerRadius(10)
}.disabled(viewModel.playButtonItem == nil) }.disabled(viewModel.playButtonItem == nil)
Spacer() Spacer()
} }
ScrollView { ScrollView {
VStack(alignment: .leading) { VStack(alignment: .leading) {
// MARK: ItemLandscapeTopBarView // MARK: ItemLandscapeTopBarView
ItemLandscapeTopBarView() ItemLandscapeTopBarView()
.environmentObject(viewModel) .environmentObject(viewModel)
// MARK: ItemViewBody // MARK: ItemViewBody
if let episodeViewModel = viewModel as? SeasonItemViewModel { if let episodeViewModel = viewModel as? SeasonItemViewModel {
EpisodeCardVStackView(items: episodeViewModel.episodes) { episode in EpisodeCardVStackView(items: episodeViewModel.episodes) { episode in
itemRouter.route(to: \.item, episode) itemRouter.route(to: \.item, episode)
@ -80,9 +80,9 @@ struct ItemLandscapeMainView: View {
} }
} }
} }
// MARK: body // MARK: body
var body: some View { var body: some View {
VStack { VStack {
ZStack { ZStack {
@ -92,7 +92,8 @@ struct ItemLandscapeMainView: View {
bh: viewModel.item.getBackdropImageBlurHash()) bh: viewModel.item.getBackdropImageBlurHash())
.opacity(0.3) .opacity(0.3)
.edgesIgnoringSafeArea(.all) .edgesIgnoringSafeArea(.all)
.blur(radius: 4) .blur(radius: 8)
.layoutPriority(-1)
// iPadOS is making the view go all the way to the edge. // iPadOS is making the view go all the way to the edge.
// We have to accomodate this here // We have to accomodate this here

View File

@ -1,11 +1,11 @@
// //
/* /*
* SwiftFin is subject to the terms of the Mozilla Public * SwiftFin is subject to the terms of the Mozilla Public
* License, v2.0. If a copy of the MPL was not distributed with this * 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/. * file, you can obtain one at https://mozilla.org/MPL/2.0/.
* *
* Copyright 2021 Aiden Vigue & Jellyfin Contributors * Copyright 2021 Aiden Vigue & Jellyfin Contributors
*/ */
import Foundation import Foundation
import JellyfinAPI import JellyfinAPI
@ -14,35 +14,48 @@ import UIKit
// 001fC^ = dark grey plain blurhash // 001fC^ = dark grey plain blurhash
public extension BaseItemDto { public extension BaseItemDto {
// MARK: Images // MARK: Images
func getSeriesBackdropImageBlurHash() -> String { func getSeriesBackdropImageBlurHash() -> String {
let rawImgURL = getSeriesBackdropImage(maxWidth: 1).absoluteString let imgURL = getSeriesBackdropImage(maxWidth: 1)
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1] guard let imgTag = imgURL.queryParameters?["tag"],
let hash = imageBlurHashes?.backdrop?[imgTag]
else {
return "001fC^"
}
return imageBlurHashes?.backdrop?[imgTag] ?? "001fC^" return hash
} }
func getSeriesPrimaryImageBlurHash() -> String { func getSeriesPrimaryImageBlurHash() -> String {
let rawImgURL = getSeriesPrimaryImage(maxWidth: 1).absoluteString let imgURL = getSeriesPrimaryImage(maxWidth: 1)
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1] guard let imgTag = imgURL.queryParameters?["tag"],
let hash = imageBlurHashes?.primary?[imgTag]
else {
return "001fC^"
}
return imageBlurHashes?.primary?[imgTag] ?? "001fC^" return hash
} }
func getPrimaryImageBlurHash() -> String { func getPrimaryImageBlurHash() -> String {
let rawImgURL = getPrimaryImage(maxWidth: 1).absoluteString let imgURL = getPrimaryImage(maxWidth: 1)
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1] guard let imgTag = imgURL.queryParameters?["tag"],
let hash = imageBlurHashes?.primary?[imgTag]
else {
return "001fC^"
}
return imageBlurHashes?.primary?[imgTag] ?? "001fC^" return hash
} }
func getBackdropImageBlurHash() -> String { func getBackdropImageBlurHash() -> String {
let rawImgURL = getBackdropImage(maxWidth: 1).absoluteString let imgURL = getBackdropImage(maxWidth: 1)
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1] guard let imgTag = imgURL.queryParameters?["tag"] else {
return "001fC^"
}
if rawImgURL.contains("Backdrop") { if imgURL.queryParameters?[ImageType.backdrop.rawValue] == nil {
return imageBlurHashes?.backdrop?[imgTag] ?? "001fC^" return imageBlurHashes?.backdrop?[imgTag] ?? "001fC^"
} else { } else {
return imageBlurHashes?.primary?[imgTag] ?? "001fC^" return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
@ -50,31 +63,29 @@ public extension BaseItemDto {
} }
func getBackdropImage(maxWidth: Int) -> URL { func getBackdropImage(maxWidth: Int) -> URL {
var imageType = "" var imageType = ImageType.backdrop
var imageTag = "" var imageTag: String?
var imageItemId = id ?? "" var imageItemId = id ?? ""
if primaryImageAspectRatio ?? 0.0 < 1.0 { if primaryImageAspectRatio ?? 0.0 < 1.0 {
imageType = "Backdrop"
if !(backdropImageTags?.isEmpty ?? true) { if !(backdropImageTags?.isEmpty ?? true) {
imageTag = (backdropImageTags ?? [""])[0] imageTag = backdropImageTags?.first
} }
} else { } else {
imageType = "Primary" imageType = .primary
imageTag = imageTags?["Primary"] ?? "" imageTag = imageTags?[ImageType.primary.rawValue] ?? ""
} }
if imageTag == "" || imageItemId == "" { if imageTag == nil || imageItemId.isEmpty {
imageType = "Backdrop"
if !(parentBackdropImageTags?.isEmpty ?? true) { if !(parentBackdropImageTags?.isEmpty ?? true) {
imageTag = (parentBackdropImageTags ?? [""])[0] imageTag = parentBackdropImageTags?.first
imageItemId = parentBackdropItemId ?? "" imageItemId = parentBackdropItemId ?? ""
} }
} }
let x = UIScreen.main.nativeScale * CGFloat(maxWidth) let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = let urlString =
"\(SessionManager.main.currentLogin.server.currentURI)/Items/\(imageItemId)/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)" "\(SessionManager.main.currentLogin.server.currentURI)/Items/\(imageItemId)/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)"
return URL(string: urlString)! return URL(string: urlString)!
} }
@ -86,9 +97,6 @@ public extension BaseItemDto {
} }
func getSeriesBackdropImage(maxWidth: Int) -> URL { func getSeriesBackdropImage(maxWidth: Int) -> URL {
let imageType = "Backdrop"
let imageTag = (parentBackdropImageTags ?? [""])[0]
let x = UIScreen.main.nativeScale * CGFloat(maxWidth) let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = let urlString =
"\(SessionManager.main.currentLogin.server.currentURI)/Items/\(parentBackdropItemId ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)" "\(SessionManager.main.currentLogin.server.currentURI)/Items/\(parentBackdropItemId ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)"
@ -96,8 +104,6 @@ public extension BaseItemDto {
} }
func getSeriesPrimaryImage(maxWidth: Int) -> URL { func getSeriesPrimaryImage(maxWidth: Int) -> URL {
let imageType = "Primary"
let imageTag = seriesPrimaryImageTag ?? ""
let x = UIScreen.main.nativeScale * CGFloat(maxWidth) let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = let urlString =
"\(SessionManager.main.currentLogin.server.currentURI)/Items/\(seriesId ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)" "\(SessionManager.main.currentLogin.server.currentURI)/Items/\(seriesId ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)"
@ -105,11 +111,11 @@ public extension BaseItemDto {
} }
func getPrimaryImage(maxWidth: Int) -> URL { func getPrimaryImage(maxWidth: Int) -> URL {
let imageType = "Primary" let imageType = ImageType.primary
var imageTag = imageTags?["Primary"] ?? "" var imageTag = imageTags?[ImageType.primary.rawValue] ?? ""
var imageItemId = id ?? "" var imageItemId = id ?? ""
if imageTag == "" || imageItemId == "" { if imageTag.isEmpty || imageItemId.isEmpty {
imageTag = seriesPrimaryImageTag ?? "" imageTag = seriesPrimaryImageTag ?? ""
imageItemId = seriesId ?? "" imageItemId = seriesId ?? ""
} }
@ -118,7 +124,6 @@ public extension BaseItemDto {
let urlString = let urlString =
"\(SessionManager.main.currentLogin.server.currentURI)/Items/\(imageItemId)/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)" "\(SessionManager.main.currentLogin.server.currentURI)/Items/\(imageItemId)/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=96&tag=\(imageTag)"
// print(urlString)
return URL(string: urlString)! return URL(string: urlString)!
} }
@ -174,14 +179,14 @@ public extension BaseItemDto {
} }
var itemType: ItemType { var itemType: ItemType {
guard let originalType = self.type, let knownType = ItemType(rawValue: originalType) else { return .unknown } guard let originalType = type, let knownType = ItemType(rawValue: originalType) else { return .unknown }
return knownType return knownType
} }
// MARK: PortraitHeaderViewURL // MARK: PortraitHeaderViewURL
func portraitHeaderViewURL(maxWidth: Int) -> URL { func portraitHeaderViewURL(maxWidth: Int) -> URL {
switch self.itemType { switch itemType {
case .movie, .season, .series: case .movie, .season, .series:
return getPrimaryImage(maxWidth: maxWidth) return getPrimaryImage(maxWidth: maxWidth)
case .episode: case .episode:

View File

@ -10,23 +10,28 @@ import JellyfinAPI
import UIKit import UIKit
extension BaseItemPerson { extension BaseItemPerson {
// MARK: Get Image // MARK: Get Image
func getImage(baseURL: String, maxWidth: Int) -> URL { func getImage(baseURL: String, maxWidth: Int) -> URL {
let imageType = "Primary"
let imageTag = primaryImageTag ?? ""
let x = UIScreen.main.nativeScale * CGFloat(maxWidth) let x = UIScreen.main.nativeScale * CGFloat(maxWidth)
let urlString = "\(baseURL)/Items/\(id ?? "")/Images/\(imageType)?maxWidth=\(String(Int(x)))&quality=85&tag=\(imageTag)" let urlString = ImageAPI.getItemImageWithRequestBuilder(itemId: id ?? "",
imageType: .primary,
maxWidth: Int(x),
quality: 96,
tag: primaryImageTag).URLString
return URL(string: urlString)! return URL(string: urlString)!
} }
func getBlurHash() -> String { func getBlurHash() -> String {
let rawImgURL = getImage(baseURL: "", maxWidth: 1).absoluteString let imgURL = getImage(baseURL: "", maxWidth: 1)
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1] guard let imgTag = imgURL.queryParameters?["tag"],
let hash = imageBlurHashes?.primary?[imgTag]
else {
return "001fC^"
}
return imageBlurHashes?.primary?[imgTag] ?? "001fC^" return hash
} }
// MARK: First Role // MARK: First Role

View File

@ -0,0 +1,26 @@
//
/*
* 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
public extension URL {
/// Dictionary of the URL's query parameters
var queryParameters: [String: String]? {
guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems else { return nil }
var items: [String: String] = [:]
for queryItem in queryItems {
items[queryItem.name] = queryItem.value
}
return items
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.