Merge branch 'main' into multi-server-url
This commit is contained in:
commit
9ba5ab8417
|
@ -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 */,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue