Support new iPhone models

This commit is contained in:
Ilya Laktyushin 2025-09-24 21:54:47 +04:00
parent 672aff4eb5
commit 61ac2e9c21
5 changed files with 75 additions and 9 deletions

View File

@ -12,6 +12,9 @@ public extension Camera {
case iPhone15Plus case iPhone15Plus
case iPhone15Pro case iPhone15Pro
case iPhone15ProMax case iPhone15ProMax
case iPhone17
case iPhone17Pro
case iPhoneAir
case unknown case unknown
public init(model: DeviceModel) { public init(model: DeviceModel) {
@ -38,6 +41,12 @@ public extension Camera {
self = .iPhone15Pro self = .iPhone15Pro
case .iPhone16ProMax: case .iPhone16ProMax:
self = .iPhone15ProMax self = .iPhone15ProMax
case .iPhone17:
self = .iPhone17
case .iPhone17Pro, .iPhone17ProMax:
self = .iPhone17Pro
case .iPhoneAir:
self = .iPhoneAir
case .unknown: case .unknown:
self = .unknown self = .unknown
default: default:
@ -49,12 +58,16 @@ public extension Camera {
switch self { switch self {
case .singleCamera: case .singleCamera:
return [1.0] return [1.0]
case .iPhone14, .iPhone14Plus, .iPhone15, .iPhone15Plus: case .iPhone14, .iPhone14Plus, .iPhone15, .iPhone15Plus, .iPhone17:
return [0.5, 1.0, 2.0] return [0.5, 1.0, 2.0]
case .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro: case .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro:
return [0.5, 1.0, 2.0, 3.0] return [0.5, 1.0, 2.0, 3.0]
case .iPhone15ProMax: case .iPhone15ProMax:
return [0.5, 1.0, 2.0, 5.0] return [0.5, 1.0, 2.0, 5.0]
case .iPhone17Pro:
return [0.5, 1.0, 2.0, 8.0]
case .iPhoneAir:
return [1.0, 2.0]
case .unknown: case .unknown:
return [1.0, 2.0] return [1.0, 2.0]
} }

View File

@ -38,6 +38,7 @@ public enum DeviceMetrics: CaseIterable, Equatable {
case iPhone14ProMaxZoomed case iPhone14ProMaxZoomed
case iPhone16Pro case iPhone16Pro
case iPhone16ProMax case iPhone16ProMax
case iPhoneAir
case iPad case iPad
case iPadMini case iPadMini
case iPad102Inch case iPad102Inch
@ -72,6 +73,7 @@ public enum DeviceMetrics: CaseIterable, Equatable {
.iPhone14ProMaxZoomed, .iPhone14ProMaxZoomed,
.iPhone16Pro, .iPhone16Pro,
.iPhone16ProMax, .iPhone16ProMax,
.iPhoneAir,
.iPad, .iPad,
.iPadMini, .iPadMini,
.iPad102Inch, .iPad102Inch,
@ -179,6 +181,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
return CGSize(width: 402.0, height: 874.0) return CGSize(width: 402.0, height: 874.0)
case .iPhone16ProMax: case .iPhone16ProMax:
return CGSize(width: 440.0, height: 956.0) return CGSize(width: 440.0, height: 956.0)
case .iPhoneAir:
return CGSize(width: 420.0, height: 912.0)
case .iPad: case .iPad:
return CGSize(width: 768.0, height: 1024.0) return CGSize(width: 768.0, height: 1024.0)
case .iPadMini: case .iPadMini:
@ -214,6 +218,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
return 55.0 return 55.0
case .iPhone16Pro, .iPhone16ProMax: case .iPhone16Pro, .iPhone16ProMax:
return 55.0 return 55.0
case .iPhoneAir:
return 55.0
case let .unknown(_, _, _, screenCornerRadius): case let .unknown(_, _, _, screenCornerRadius):
return screenCornerRadius return screenCornerRadius
default: default:
@ -229,6 +235,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
return inLandscape ? UIEdgeInsets(top: 0.0, left: 47.0, bottom: 0.0, right: 47.0) : UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0) return inLandscape ? UIEdgeInsets(top: 0.0, left: 47.0, bottom: 0.0, right: 47.0) : UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)
case .iPhone14Pro, .iPhone14ProMax, .iPhone16Pro, .iPhone16ProMax: case .iPhone14Pro, .iPhone14ProMax, .iPhone16Pro, .iPhone16ProMax:
return inLandscape ? UIEdgeInsets(top: 0.0, left: 59.0, bottom: 0.0, right: 59.0) : UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0) return inLandscape ? UIEdgeInsets(top: 0.0, left: 59.0, bottom: 0.0, right: 59.0) : UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0)
case .iPhoneAir:
return inLandscape ? UIEdgeInsets(top: 0.0, left: 68.0, bottom: 0.0, right: 68.0) : UIEdgeInsets(top: 68.0, left: 0.0, bottom: 0.0, right: 0.0)
default: default:
return UIEdgeInsets.zero return UIEdgeInsets.zero
} }
@ -236,7 +244,7 @@ public enum DeviceMetrics: CaseIterable, Equatable {
public func onScreenNavigationHeight(inLandscape: Bool, systemOnScreenNavigationHeight: CGFloat?) -> CGFloat? { public func onScreenNavigationHeight(inLandscape: Bool, systemOnScreenNavigationHeight: CGFloat?) -> CGFloat? {
switch self { switch self {
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone16Pro, .iPhone16ProMax: case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhoneAir:
if #available(iOS 26.0, *) { if #available(iOS 26.0, *) {
return 20.0 return 20.0
} else { } else {
@ -282,6 +290,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
return 47.0 return 47.0
case .iPhone16Pro, .iPhone16ProMax: case .iPhone16Pro, .iPhone16ProMax:
return 54.0 return 54.0
case .iPhoneAir:
return 54.0
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax:
return 44.0 return 44.0
case .iPadPro11Inch, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen: case .iPadPro11Inch, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen:
@ -294,6 +304,16 @@ public enum DeviceMetrics: CaseIterable, Equatable {
} }
public func keyboardHeight(inLandscape: Bool) -> CGFloat { public func keyboardHeight(inLandscape: Bool) -> CGFloat {
var keyboardHeight = _keyboardHeight(inLandscape: inLandscape)
if #available(iOS 26.0, *) {
if !inLandscape {
keyboardHeight += 9.0
}
}
return keyboardHeight
}
private func _keyboardHeight(inLandscape: Bool) -> CGFloat {
if inLandscape { if inLandscape {
switch self { switch self {
case .iPhone4, .iPhone5: case .iPhone4, .iPhone5:
@ -302,6 +322,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
return 163.0 return 163.0
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax: case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax:
return 172.0 return 172.0
case .iPhoneAir:
return 172.0
case .iPad, .iPad102Inch, .iPadPro10Inch: case .iPad, .iPad102Inch, .iPadPro10Inch:
return 348.0 return 348.0
case .iPadPro11Inch, .iPadMini, .iPadMini6thGen: case .iPadPro11Inch, .iPadMini, .iPadMini6thGen:
@ -321,6 +343,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
return 226.0 return 226.0
case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed, .iPhone16Pro: case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed, .iPhone16Pro:
return 292.0 return 292.0
case .iPhoneAir:
return 292.0
case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax, .iPhone13ProMax, .iPhone14ProMax, .iPhone16ProMax: case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax, .iPhone13ProMax, .iPhone14ProMax, .iPhone16ProMax:
return 302.0 return 302.0
case .iPad, .iPad102Inch, .iPadPro10Inch: case .iPad, .iPad102Inch, .iPadPro10Inch:
@ -340,7 +364,7 @@ public enum DeviceMetrics: CaseIterable, Equatable {
func predictiveInputHeight(inLandscape: Bool) -> CGFloat { func predictiveInputHeight(inLandscape: Bool) -> CGFloat {
if inLandscape { if inLandscape {
switch self { switch self {
case .iPhone4, .iPhone5, .iPhone6, .iPhone6Plus, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax: case .iPhone4, .iPhone5, .iPhone6, .iPhone6Plus, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax, .iPhoneAir:
return 37.0 return 37.0
case .iPad, .iPad102Inch, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen: case .iPad, .iPad102Inch, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen:
return 50.0 return 50.0
@ -351,7 +375,7 @@ public enum DeviceMetrics: CaseIterable, Equatable {
switch self { switch self {
case .iPhone4, .iPhone5: case .iPhone4, .iPhone5:
return 37.0 return 37.0
case .iPhone6, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax: case .iPhone6, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax, .iPhoneAir:
return 44.0 return 44.0
case .iPhone6Plus: case .iPhone6Plus:
return 45.0 return 45.0
@ -378,7 +402,7 @@ public enum DeviceMetrics: CaseIterable, Equatable {
public var hasDynamicIsland: Bool { public var hasDynamicIsland: Bool {
switch self { switch self {
case .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax: case .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMax, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhone16ProMax, .iPhoneAir:
return true return true
default: default:
return false return false

View File

@ -544,6 +544,14 @@ NSString *suffix = @"";
return @"iPhone 16 Pro Max"; return @"iPhone 16 Pro Max";
if ([platform isEqualToString:@"iPhone17,5"]) if ([platform isEqualToString:@"iPhone17,5"])
return @"iPhone 16e"; return @"iPhone 16e";
if ([platform isEqualToString:@"iPhone18,3"])
return @"iPhone 17";
if ([platform isEqualToString:@"iPhone18,1"])
return @"iPhone 17 Pro";
if ([platform isEqualToString:@"iPhone18,2"])
return @"iPhone 17 Pro Max";
if ([platform isEqualToString:@"iPhone18,4"])
return @"iPhone Air";
if ([platform hasPrefix:@"iPod1"]) if ([platform hasPrefix:@"iPod1"])
return @"iPod touch 1G"; return @"iPod touch 1G";

View File

@ -67,7 +67,7 @@ struct PasscodeKeyboardLayout {
self.topOffset = 226.0 self.topOffset = 226.0
self.biometricsOffset = 30.0 self.biometricsOffset = 30.0
self.deleteOffset = 20.0 self.deleteOffset = 20.0
case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed, .iPhone16Pro: case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhoneAir:
self.buttonSize = 75.0 self.buttonSize = 75.0
self.horizontalSecond = 103.0 self.horizontalSecond = 103.0
self.horizontalThird = 206.0 self.horizontalThird = 206.0
@ -151,7 +151,7 @@ public struct PasscodeLayout {
self.titleOffset = 112.0 self.titleOffset = 112.0
self.subtitleOffset = -6.0 self.subtitleOffset = -6.0
self.inputFieldOffset = 156.0 self.inputFieldOffset = 156.0
case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed, .iPhone16Pro: case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone14Pro, .iPhone14ProZoomed, .iPhone14ProMaxZoomed, .iPhone16Pro, .iPhoneAir:
self.titleOffset = 162.0 self.titleOffset = 162.0
self.subtitleOffset = 0.0 self.subtitleOffset = 0.0
self.inputFieldOffset = 206.0 self.inputFieldOffset = 206.0

View File

@ -126,6 +126,11 @@ public enum DeviceModel: CaseIterable, Equatable {
case iPhone16ProMax case iPhone16ProMax
case iPhone16e case iPhone16e
case iPhone17
case iPhone17Pro
case iPhone17ProMax
case iPhoneAir
case unknown(String) case unknown(String)
public var modelId: [String] { public var modelId: [String] {
@ -238,6 +243,14 @@ public enum DeviceModel: CaseIterable, Equatable {
return ["iPhone17,2"] return ["iPhone17,2"]
case .iPhone16e: case .iPhone16e:
return ["iPhone17,5"] return ["iPhone17,5"]
case .iPhone17:
return ["iPhone18,3"]
case .iPhone17Pro:
return ["iPhone18,1"]
case .iPhone17ProMax:
return ["iPhone18,2"]
case .iPhoneAir:
return ["iPhone18,4"]
case let .unknown(modelId): case let .unknown(modelId):
return [modelId] return [modelId]
} }
@ -353,6 +366,14 @@ public enum DeviceModel: CaseIterable, Equatable {
return "iPhone 16 Pro Max" return "iPhone 16 Pro Max"
case .iPhone16e: case .iPhone16e:
return "iPhone 16e" return "iPhone 16e"
case .iPhone17:
return "iPhone 17"
case .iPhone17Pro:
return "iPhone 17 Pro"
case .iPhone17ProMax:
return "iPhone 17 Pro Max"
case .iPhoneAir:
return "iPhone Air"
case let .unknown(modelId): case let .unknown(modelId):
if modelId.hasPrefix("iPhone") { if modelId.hasPrefix("iPhone") {
return "Unknown iPhone" return "Unknown iPhone"