diff options
Diffstat (limited to 'Jel/Models')
-rw-r--r-- | Jel/Models/BlurHashDecode.swift | 153 | ||||
-rw-r--r-- | Jel/Models/JellyfinDateFormatter.swift | 33 | ||||
-rw-r--r-- | Jel/Models/JellyfinKitExtensions.swift | 28 | ||||
-rw-r--r-- | Jel/Models/UIScreenWidthExtension.swift | 15 | ||||
-rw-r--r-- | Jel/Models/ViewExtensions.swift | 31 |
5 files changed, 0 insertions, 260 deletions
diff --git a/Jel/Models/BlurHashDecode.swift b/Jel/Models/BlurHashDecode.swift deleted file mode 100644 index 93c4896..0000000 --- a/Jel/Models/BlurHashDecode.swift +++ /dev/null @@ -1,153 +0,0 @@ -// -// BlurHashDecode.swift -// Jel -// -// Created by zerocool on 12/22/23. -// - -import UIKit - -extension UIImage { - public convenience init?(blurHash: String, size: CGSize, punch: Float = 1) { - guard blurHash.count >= 6 else { return nil } - - let sizeFlag = String(blurHash[0]).decode83() - let numY = (sizeFlag / 9) + 1 - let numX = (sizeFlag % 9) + 1 - - let quantisedMaximumValue = String(blurHash[1]).decode83() - let maximumValue = Float(quantisedMaximumValue + 1) / 166 - - guard blurHash.count == 4 + 2 * numX * numY else { return nil } - - let colours: [(Float, Float, Float)] = (0 ..< numX * numY).map { i in - if i == 0 { - let value = String(blurHash[2 ..< 6]).decode83() - return decodeDC(value) - } else { - let value = String(blurHash[4 + i * 2 ..< 4 + i * 2 + 2]).decode83() - return decodeAC(value, maximumValue: maximumValue * punch) - } - } - - let width = Int(size.width) - let height = Int(size.height) - let bytesPerRow = width * 3 - guard let data = CFDataCreateMutable(kCFAllocatorDefault, bytesPerRow * height) else { return nil } - CFDataSetLength(data, bytesPerRow * height) - guard let pixels = CFDataGetMutableBytePtr(data) else { return nil } - - for y in 0 ..< height { - for x in 0 ..< width { - var r: Float = 0 - var g: Float = 0 - var b: Float = 0 - - for j in 0 ..< numY { - for i in 0 ..< numX { - let basis = cos(Float.pi * Float(x) * Float(i) / Float(width)) * cos(Float.pi * Float(y) * Float(j) / Float(height)) - let colour = colours[i + j * numX] - r += colour.0 * basis - g += colour.1 * basis - b += colour.2 * basis - } - } - - let intR = UInt8(linearTosRGB(r)) - let intG = UInt8(linearTosRGB(g)) - let intB = UInt8(linearTosRGB(b)) - - pixels[3 * x + 0 + y * bytesPerRow] = intR - pixels[3 * x + 1 + y * bytesPerRow] = intG - pixels[3 * x + 2 + y * bytesPerRow] = intB - } - } - - let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue) - - guard let provider = CGDataProvider(data: data) else { return nil } - guard let cgImage = CGImage(width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 24, bytesPerRow: bytesPerRow, - space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: bitmapInfo, provider: provider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else { return nil } - - self.init(cgImage: cgImage) - } -} - -private func decodeDC(_ value: Int) -> (Float, Float, Float) { - let intR = value >> 16 - let intG = (value >> 8) & 255 - let intB = value & 255 - return (sRGBToLinear(intR), sRGBToLinear(intG), sRGBToLinear(intB)) -} - -private func decodeAC(_ value: Int, maximumValue: Float) -> (Float, Float, Float) { - let quantR = value / (19 * 19) - let quantG = (value / 19) % 19 - let quantB = value % 19 - - let rgb = ( - signPow((Float(quantR) - 9) / 9, 2) * maximumValue, - signPow((Float(quantG) - 9) / 9, 2) * maximumValue, - signPow((Float(quantB) - 9) / 9, 2) * maximumValue - ) - - return rgb -} - -private func signPow(_ value: Float, _ exp: Float) -> Float { - return copysign(pow(abs(value), exp), value) -} - -private func linearTosRGB(_ value: Float) -> Int { - let v = max(0, min(1, value)) - if v <= 0.0031308 { return Int(v * 12.92 * 255 + 0.5) } - else { return Int((1.055 * pow(v, 1 / 2.4) - 0.055) * 255 + 0.5) } -} - -private func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float { - let v = Float(Int64(value)) / 255 - if v <= 0.04045 { return v / 12.92 } - else { return pow((v + 0.055) / 1.055, 2.4) } -} - -private let encodeCharacters: [String] = { - return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { String($0) } -}() - -private let decodeCharacters: [String: Int] = { - var dict: [String: Int] = [:] - for (index, character) in encodeCharacters.enumerated() { - dict[character] = index - } - return dict -}() - -extension String { - func decode83() -> Int { - var value: Int = 0 - for character in self { - if let digit = decodeCharacters[String(character)] { - value = value * 83 + digit - } - } - return value - } -} - -private extension String { - subscript (offset: Int) -> Character { - return self[index(startIndex, offsetBy: offset)] - } - - subscript (bounds: CountableClosedRange<Int>) -> Substring { - let start = index(startIndex, offsetBy: bounds.lowerBound) - let end = index(startIndex, offsetBy: bounds.upperBound) - return self[start...end] - } - - subscript (bounds: CountableRange<Int>) -> Substring { - let start = index(startIndex, offsetBy: bounds.lowerBound) - let end = index(startIndex, offsetBy: bounds.upperBound) - return self[start..<end] - } -} diff --git a/Jel/Models/JellyfinDateFormatter.swift b/Jel/Models/JellyfinDateFormatter.swift deleted file mode 100644 index 74b89d1..0000000 --- a/Jel/Models/JellyfinDateFormatter.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// JellyfinDateFormatter.swift -// Jel -// -// Created by zerocool on 12/12/23. -// - -import Foundation - -// from: https://stackoverflow.com/a/46458771 -extension Formatter { - static let iso8601withFractionalSeconds: ISO8601DateFormatter = { - let formatter = ISO8601DateFormatter() - formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] - return formatter - }() - static let iso8601: ISO8601DateFormatter = { - let formatter = ISO8601DateFormatter() - formatter.formatOptions = [.withInternetDateTime] - return formatter - }() -} - -extension JSONDecoder.DateDecodingStrategy { - static let iso8601withFractionalSeconds = custom { - let container = try $0.singleValueContainer() - let string = try container.decode(String.self) - if let date = Formatter.iso8601withFractionalSeconds.date(from: string) ?? Formatter.iso8601.date(from: string) { - return date - } - throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)") - } -} diff --git a/Jel/Models/JellyfinKitExtensions.swift b/Jel/Models/JellyfinKitExtensions.swift deleted file mode 100644 index 197731c..0000000 --- a/Jel/Models/JellyfinKitExtensions.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// JellyfinKitExtensions.swift -// Jel -// -// Created by zerocool on 12/24/23. -// - -import Foundation -import JellyfinKit - -extension BaseItemDto { - func getRuntime() -> String? { - let formatter: DateComponentsFormatter = { - let localFormatter = DateComponentsFormatter() - localFormatter.unitsStyle = .brief - localFormatter.allowedUnits = [.hour, .minute] - - return localFormatter - }() - - if let runTimeTicks = self.runTimeTicks { - let text = formatter.string(from: Double(runTimeTicks / 10_000_000)) - return text - } - - return nil - } -} diff --git a/Jel/Models/UIScreenWidthExtension.swift b/Jel/Models/UIScreenWidthExtension.swift deleted file mode 100644 index 6f2f5de..0000000 --- a/Jel/Models/UIScreenWidthExtension.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// UIScreenWidthExtension.swift -// Jel -// -// Created by zerocool on 2/14/24. -// - -import Foundation -import UIKit - -extension UIScreen{ - static let screenWidth = UIScreen.main.bounds.size.width - static let screenHeight = UIScreen.main.bounds.size.height - static let screenSize = UIScreen.main.bounds.size -} diff --git a/Jel/Models/ViewExtensions.swift b/Jel/Models/ViewExtensions.swift deleted file mode 100644 index 7f54865..0000000 --- a/Jel/Models/ViewExtensions.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// ViewExtensions.swift -// Jel -// -// Created by zerocool on 12/25/23. -// - -import SwiftUI - -extension View { - /// Applies the given transform if the given condition evaluates to `true`. - @ViewBuilder func `if`<Content: View>(_ condition: @autoclosure () -> Bool, transform: (Self) -> Content) -> some View { - if condition() { - transform(self) - } else { - self - } - } -} - -extension View { - /// Applies an inverse mask to the given view - public func inverseMask<Content: View>(_ mask: Content) -> some View { - let inverseMask = mask - .foregroundStyle(.black) - .background(.white) - .compositingGroup() - .luminanceToAlpha() - return self.mask(inverseMask) - } -} |