194 lines
6.3 KiB
Swift
194 lines
6.3 KiB
Swift
//
|
|
/*
|
|
* 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
|
|
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]
|
|
|
|
return imageBlurHashes?.backdrop?[imgTag] ?? "001fC^"
|
|
}
|
|
|
|
func getSeriesPrimaryImageBlurHash() -> String {
|
|
let rawImgURL = getSeriesPrimaryImage(maxWidth: 1).absoluteString
|
|
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1]
|
|
|
|
return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
|
|
}
|
|
|
|
func getPrimaryImageBlurHash() -> String {
|
|
let rawImgURL = getPrimaryImage(maxWidth: 1).absoluteString
|
|
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1]
|
|
|
|
return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
|
|
}
|
|
|
|
func getBackdropImageBlurHash() -> String {
|
|
let rawImgURL = getBackdropImage(maxWidth: 1).absoluteString
|
|
let imgTag = rawImgURL.components(separatedBy: "&tag=")[1]
|
|
|
|
if rawImgURL.contains("Backdrop") {
|
|
return imageBlurHashes?.backdrop?[imgTag] ?? "001fC^"
|
|
} else {
|
|
return imageBlurHashes?.primary?[imgTag] ?? "001fC^"
|
|
}
|
|
}
|
|
|
|
func getBackdropImage(maxWidth: Int) -> URL {
|
|
var imageType = ""
|
|
var imageTag = ""
|
|
var imageItemId = id ?? ""
|
|
|
|
if primaryImageAspectRatio ?? 0.0 < 1.0 {
|
|
imageType = "Backdrop"
|
|
if !(backdropImageTags?.isEmpty ?? true) {
|
|
imageTag = (backdropImageTags ?? [""])[0]
|
|
}
|
|
} else {
|
|
imageType = "Primary"
|
|
imageTag = imageTags?["Primary"] ?? ""
|
|
}
|
|
|
|
if imageTag == "" || imageItemId == "" {
|
|
imageType = "Backdrop"
|
|
if !(parentBackdropImageTags?.isEmpty ?? true) {
|
|
imageTag = (parentBackdropImageTags ?? [""])[0]
|
|
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)"
|
|
return URL(string: urlString)!
|
|
}
|
|
|
|
func getEpisodeLocator() -> String? {
|
|
if let seasonNo = parentIndexNumber, let episodeNo = indexNumber {
|
|
return L10n.seasonAndEpisode(String(seasonNo), String(episodeNo))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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)"
|
|
return URL(string: urlString)!
|
|
}
|
|
|
|
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)"
|
|
return URL(string: urlString)!
|
|
}
|
|
|
|
func getPrimaryImage(maxWidth: Int) -> URL {
|
|
let imageType = "Primary"
|
|
var imageTag = imageTags?["Primary"] ?? ""
|
|
var imageItemId = id ?? ""
|
|
|
|
if imageTag == "" || imageItemId == "" {
|
|
imageTag = seriesPrimaryImageTag ?? ""
|
|
imageItemId = seriesId ?? ""
|
|
}
|
|
|
|
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)"
|
|
// print(urlString)
|
|
return URL(string: urlString)!
|
|
}
|
|
|
|
// MARK: Calculations
|
|
|
|
func getItemRuntime() -> String {
|
|
let timeHMSFormatter: DateComponentsFormatter = {
|
|
let formatter = DateComponentsFormatter()
|
|
formatter.unitsStyle = .abbreviated
|
|
formatter.allowedUnits = [.hour, .minute]
|
|
return formatter
|
|
}()
|
|
|
|
guard let runTimeTicks = runTimeTicks,
|
|
let text = timeHMSFormatter.string(from: Double(runTimeTicks / 10_000_000)) else { return "" }
|
|
|
|
return text
|
|
}
|
|
|
|
func getItemProgressString() -> String {
|
|
if userData?.playbackPositionTicks == nil || userData?.playbackPositionTicks == 0 {
|
|
return ""
|
|
}
|
|
|
|
let remainingSecs = ((runTimeTicks ?? 0) - (userData?.playbackPositionTicks ?? 0)) / 10_000_000
|
|
let proghours = Int(remainingSecs / 3600)
|
|
let progminutes = Int((Int(remainingSecs) - (proghours * 3600)) / 60)
|
|
if proghours != 0 {
|
|
return "\(proghours)h \(String(progminutes).leftPad(toWidth: 2, withString: "0"))m"
|
|
} else {
|
|
return "\(String(progminutes))m"
|
|
}
|
|
}
|
|
|
|
// MARK: ItemType
|
|
|
|
enum ItemType: String {
|
|
case movie = "Movie"
|
|
case season = "Season"
|
|
case episode = "Episode"
|
|
case series = "Series"
|
|
|
|
case unknown
|
|
|
|
var showDetails: Bool {
|
|
switch self {
|
|
case .season, .series:
|
|
return false
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
var itemType: ItemType {
|
|
guard let originalType = self.type, let knownType = ItemType(rawValue: originalType) else { return .unknown }
|
|
return knownType
|
|
}
|
|
|
|
// MARK: PortraitHeaderViewURL
|
|
|
|
func portraitHeaderViewURL(maxWidth: Int) -> URL {
|
|
switch self.itemType {
|
|
case .movie, .season, .series:
|
|
return getPrimaryImage(maxWidth: maxWidth)
|
|
case .episode:
|
|
return getSeriesPrimaryImage(maxWidth: maxWidth)
|
|
case .unknown:
|
|
return getPrimaryImage(maxWidth: maxWidth)
|
|
}
|
|
}
|
|
}
|