Swiftgram/submodules/Display/Source/DeviceMetrics.swift
2023-06-20 18:05:20 +04:00

369 lines
14 KiB
Swift

import UIKit
public enum DeviceType {
case phone
case tablet
}
public enum DeviceMetrics: CaseIterable, Equatable {
public struct Performance {
public let isGraphicallyCapable: Bool
init() {
var length: Int = 4
var cpuCount: UInt32 = 0
sysctlbyname("hw.ncpu", &cpuCount, &length, nil, 0)
self.isGraphicallyCapable = cpuCount >= 4
}
}
case iPhone4
case iPhone5
case iPhone6
case iPhone6Plus
case iPhoneX
case iPhoneXSMax
case iPhoneXr
case iPhone12Mini
case iPhone12
case iPhone12ProMax
case iPhone13Mini
case iPhone13
case iPhone13Pro
case iPhone13ProMax
case iPhone14Pro
case iPhone14ProZoomed
case iPhone14ProMax
case iPhone14ProMaxZoomed
case iPad
case iPadMini
case iPad102Inch
case iPadPro10Inch
case iPadPro11Inch
case iPadPro
case iPadPro3rdGen
case iPadMini6thGen
case unknown(screenSize: CGSize, statusBarHeight: CGFloat, onScreenNavigationHeight: CGFloat?)
public static let performance = Performance()
public static var allCases: [DeviceMetrics] {
return [
.iPhone4,
.iPhone5,
.iPhone6,
.iPhone6Plus,
.iPhoneX,
.iPhoneXSMax,
.iPhoneXr,
.iPhone12Mini,
.iPhone12,
.iPhone12ProMax,
.iPhone13Mini,
.iPhone13,
.iPhone13Pro,
.iPhone13ProMax,
.iPhone14Pro,
.iPhone14ProZoomed,
.iPhone14ProMax,
.iPhone14ProMaxZoomed,
.iPad,
.iPadMini,
.iPad102Inch,
.iPadPro10Inch,
.iPadPro11Inch,
.iPadPro,
.iPadPro3rdGen,
.iPadMini6thGen
]
}
public init(screenSize: CGSize, scale: CGFloat, statusBarHeight: CGFloat, onScreenNavigationHeight: CGFloat?) {
var screenSize = screenSize
if screenSize.width > screenSize.height {
screenSize = CGSize(width: screenSize.height, height: screenSize.width)
}
let additionalSize = CGSize(width: screenSize.width, height: screenSize.height + 20.0)
for device in DeviceMetrics.allCases {
if let _ = onScreenNavigationHeight, device.onScreenNavigationHeight(inLandscape: false, systemOnScreenNavigationHeight: nil) == nil {
if case .tablet = device.type {
if screenSize.height == 1024.0 && screenSize.width == 768.0 {
} else {
continue
}
} else {
continue
}
}
let width = device.screenSize.width
let height = device.screenSize.height
if ((screenSize.width.isEqual(to: width) && screenSize.height.isEqual(to: height)) || (additionalSize.width.isEqual(to: width) && additionalSize.height.isEqual(to: height))) {
if case .iPhoneX = device, statusBarHeight == 47.0 {
self = .iPhone14ProMaxZoomed
} else if case .iPhoneXSMax = device, scale == 2.0 {
self = .iPhoneXr
} else {
self = device
}
return
}
}
self = .unknown(screenSize: screenSize, statusBarHeight: statusBarHeight, onScreenNavigationHeight: onScreenNavigationHeight)
}
public var type: DeviceType {
switch self {
case .iPad, .iPad102Inch, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen:
return .tablet
case let .unknown(screenSize, _, _) where screenSize.width >= 744.0 && screenSize.height >= 1024.0:
return .tablet
default:
return .phone
}
}
public var screenSize: CGSize {
switch self {
case .iPhone4:
return CGSize(width: 320.0, height: 480.0)
case .iPhone5:
return CGSize(width: 320.0, height: 568.0)
case .iPhone6:
return CGSize(width: 375.0, height: 667.0)
case .iPhone6Plus:
return CGSize(width: 414.0, height: 736.0)
case .iPhoneX:
return CGSize(width: 375.0, height: 812.0)
case .iPhoneXSMax, .iPhoneXr:
return CGSize(width: 414.0, height: 896.0)
case .iPhone12Mini:
return CGSize(width: 360.0, height: 780.0)
case .iPhone12:
return CGSize(width: 390.0, height: 844.0)
case .iPhone12ProMax:
return CGSize(width: 428.0, height: 926.0)
case .iPhone13Mini:
return CGSize(width: 375.0, height: 812.0)
case .iPhone13:
return CGSize(width: 390.0, height: 844.0)
case .iPhone13Pro:
return CGSize(width: 390.0, height: 844.0)
case .iPhone13ProMax:
return CGSize(width: 428.0, height: 926.0)
case .iPhone14Pro:
return CGSize(width: 393.0, height: 852.0)
case .iPhone14ProZoomed:
return CGSize(width: 320.0, height: 693.0)
case .iPhone14ProMax:
return CGSize(width: 430.0, height: 932.0)
case .iPhone14ProMaxZoomed:
return CGSize(width: 375.0, height: 812.0)
case .iPad:
return CGSize(width: 768.0, height: 1024.0)
case .iPadMini:
return CGSize(width: 744.0, height: 1133.0)
case .iPad102Inch:
return CGSize(width: 810.0, height: 1080.0)
case .iPadPro10Inch:
return CGSize(width: 834.0, height: 1112.0)
case .iPadPro11Inch:
return CGSize(width: 834.0, height: 1194.0)
case .iPadPro, .iPadPro3rdGen:
return CGSize(width: 1024.0, height: 1366.0)
case .iPadMini6thGen:
return CGSize(width: 744.0, height: 1133.0)
case let .unknown(screenSize, _, _):
return screenSize
}
}
public var screenCornerRadius: CGFloat {
switch self {
case .iPhoneX, .iPhoneXSMax:
return 39.0
case .iPhoneXr:
return 41.5
case .iPhone12Mini:
return 44.0
case .iPhone12, .iPhone13, .iPhone13Pro, .iPhone14ProZoomed:
return 47.0 + UIScreenPixel
case .iPhone12ProMax, .iPhone13ProMax, .iPhone14ProMaxZoomed:
return 53.0 + UIScreenPixel
case .iPhone14Pro, .iPhone14ProMax:
return 55.0
case let .unknown(_, _, onScreenNavigationHeight):
if let _ = onScreenNavigationHeight {
return 39.0
} else {
return 0.0
}
default:
return 0.0
}
}
func safeInsets(inLandscape: Bool) -> UIEdgeInsets {
switch self {
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed:
return inLandscape ? UIEdgeInsets(top: 0.0, left: 44.0, bottom: 0.0, right: 44.0) : UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)
default:
return UIEdgeInsets.zero
}
}
public func onScreenNavigationHeight(inLandscape: Bool, systemOnScreenNavigationHeight: CGFloat?) -> CGFloat? {
switch self {
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax:
return inLandscape ? 21.0 : 34.0
case .iPhone14ProZoomed:
return inLandscape ? 21.0 : 28.0
case .iPhone14ProMaxZoomed:
return inLandscape ? 21.0 : 31.0
case .iPadPro3rdGen, .iPadPro11Inch:
return 21.0
case .iPad, .iPadPro, .iPadPro10Inch, .iPadMini, .iPadMini6thGen:
if let systemOnScreenNavigationHeight = systemOnScreenNavigationHeight, !systemOnScreenNavigationHeight.isZero {
return 21.0
} else {
return nil
}
case let .unknown(_, _, onScreenNavigationHeight):
return onScreenNavigationHeight
default:
return nil
}
}
func statusBarHeight(for size: CGSize) -> CGFloat? {
let value = self.statusBarHeight
if self.type == .tablet {
return value
} else {
if size.width < size.height {
return value
} else {
return nil
}
}
}
var statusBarHeight: CGFloat {
switch self {
case .iPhone14Pro, .iPhone14ProMax:
return 54.0
case .iPhone14ProMaxZoomed:
return 47.0
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax:
return 44.0
case .iPadPro11Inch, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen:
return 24.0
case let .unknown(_, statusBarHeight, _):
return statusBarHeight
default:
return 20.0
}
}
public func keyboardHeight(inLandscape: Bool) -> CGFloat {
if inLandscape {
switch self {
case .iPhone4, .iPhone5:
return 162.0
case .iPhone6, .iPhone6Plus:
return 163.0
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed:
return 172.0
case .iPad, .iPad102Inch, .iPadPro10Inch:
return 348.0
case .iPadPro11Inch, .iPadMini, .iPadMini6thGen:
return 368.0
case .iPadPro:
return 421.0
case .iPadPro3rdGen:
return 441.0
case .unknown:
return 216.0
}
} else {
switch self {
case .iPhone4, .iPhone5, .iPhone6:
return 216.0
case .iPhone6Plus:
return 226.0
case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed:
return 292.0
case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax, .iPhone13ProMax, .iPhone14ProMax:
return 302.0
case .iPad, .iPad102Inch, .iPadPro10Inch:
return 263.0
case .iPadPro11Inch:
return 283.0
case .iPadPro, .iPadMini, .iPadMini6thGen:
return 328.0
case .iPadPro3rdGen:
return 348.0
case .unknown:
return 216.0
}
}
}
func predictiveInputHeight(inLandscape: Bool) -> CGFloat {
if inLandscape {
switch self {
case .iPhone4, .iPhone5, .iPhone6, .iPhone6Plus, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed:
return 37.0
case .iPad, .iPad102Inch, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen:
return 50.0
case .unknown:
return 37.0
}
} else {
switch self {
case .iPhone4, .iPhone5:
return 37.0
case .iPhone6, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed:
return 44.0
case .iPhone6Plus:
return 45.0
case .iPad, .iPad102Inch, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen:
return 50.0
case .unknown:
return 44.0
}
}
}
public func standardInputHeight(inLandscape: Bool) -> CGFloat {
return self.keyboardHeight(inLandscape: inLandscape) + predictiveInputHeight(inLandscape: inLandscape)
}
public var hasTopNotch: Bool {
switch self {
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax:
return true
default:
return false
}
}
public var hasDynamicIsland: Bool {
switch self {
case .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed:
return true
default:
return false
}
}
public var showAppBadge: Bool {
if case .iPhoneX = self {
return false
}
return self.hasTopNotch
}
}