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 */; };
62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.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 */; };
62E632DC267D2E130063E547 /* 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>"; };
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>"; };
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>"; };
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>"; };
@ -1062,6 +1066,7 @@
isa = PBXGroup;
children = (
5389277B263CC3DB0035E14B /* BlurHashDecode.swift */,
62E1DCC2273CE19800C9AE76 /* URLExtensions.swift */,
6267B3D526710B8900A7371D /* CollectionExtensions.swift */,
E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */,
6267B3D92671138200A7371D /* ImageExtensions.swift */,
@ -1823,6 +1828,7 @@
E1AD104E26D96CE3003E4A08 /* BaseItemDtoExtensions.swift in Sources */,
62E632DD267D2E130063E547 /* LibrarySearchViewModel.swift in Sources */,
536D3D81267BDFC60004248C /* PortraitItemElement.swift in Sources */,
62E1DCC4273CE19800C9AE76 /* URLExtensions.swift in Sources */,
5310695B2684E7EE00CFFDBA /* AudioView.swift in Sources */,
5398514726B64E4100101B49 /* SearchBarView.swift in Sources */,
091B5A8D268315D400D78B61 /* ServerDiscovery.swift in Sources */,
@ -1983,6 +1989,7 @@
535870AD2669D8DD00D05A09 /* Typings.swift in Sources */,
E1AD105F26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */,
E13DD3D5271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */,
62E1DCC3273CE19800C9AE76 /* URLExtensions.swift in Sources */,
C4BE0769271FC164003F4AD1 /* TVLibrariesView.swift in Sources */,
E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */,
6220D0BA26D6092100B8E046 /* FilterCoordinator.swift in Sources */,
@ -2031,6 +2038,7 @@
E13DD3D7271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */,
E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */,
E13DD3CA27164B80009D4DAF /* SwiftfinStore.swift in Sources */,
62E1DCC5273CE19800C9AE76 /* URLExtensions.swift in Sources */,
62EC353226766849000E9F2D /* SessionManager.swift in Sources */,
536D3D79267BD5D00004248C /* ViewModel.swift in Sources */,
E1D4BF8C2719F39F00A11E64 /* AppAppearance.swift in Sources */,

View File

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

View File

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

View File

@ -10,23 +10,28 @@ import JellyfinAPI
import UIKit
extension BaseItemPerson {
// MARK: Get Image
func getImage(baseURL: String, maxWidth: Int) -> URL {
let imageType = "Primary"
let imageTag = primaryImageTag ?? ""
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)!
}
func getBlurHash() -> String {
let rawImgURL = getImage(baseURL: "", maxWidth: 1).absoluteString
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1]
let imgURL = getImage(baseURL: "", maxWidth: 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

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.