From 8c0cbe4d5c2adc8df4adbc8052feea88abdcc701 Mon Sep 17 00:00:00 2001 From: Vincent Neo <23420208+vincentneo@users.noreply.github.com> Date: Sat, 16 Sep 2023 16:56:19 +0800 Subject: [PATCH] merge ios and watchos codebase into one --- Package.swift | 2 +- Sources/DeviceFamily.swift | 3 + Sources/DeviceModel.swift | 66 ++++++- Sources/Identifier.swift | 97 +++++++++++ Sources/Screen.swift | 42 ++++- Sources/UIDeviceComplete.swift | 8 + Sources/UIDeviceExtensions.swift | 19 +- UIDeviceComplete.xcodeproj/project.pbxproj | 44 ++--- WKDeviceComplete/DeviceModel.swift | 77 --------- WKDeviceComplete/Identifier.swift | 162 ------------------ WKDeviceComplete/Screen.swift | 62 ------- WKDeviceComplete/WKDeviceComplete.h | 19 -- WKDeviceComplete/WKDeviceComplete.swift | 46 ----- .../WKInterfaceDeviceExtensions.swift | 54 ------ 14 files changed, 238 insertions(+), 463 deletions(-) delete mode 100644 WKDeviceComplete/DeviceModel.swift delete mode 100644 WKDeviceComplete/Identifier.swift delete mode 100644 WKDeviceComplete/Screen.swift delete mode 100644 WKDeviceComplete/WKDeviceComplete.h delete mode 100644 WKDeviceComplete/WKDeviceComplete.swift delete mode 100644 WKDeviceComplete/WKInterfaceDeviceExtensions.swift diff --git a/Package.swift b/Package.swift index 3ac5ed8..4e31a0b 100644 --- a/Package.swift +++ b/Package.swift @@ -25,7 +25,7 @@ import PackageDescription let package = Package( name: "UIDeviceComplete", platforms: [ - .iOS(.v11) + .iOS(.v11), .watchOS(.v4) ], products: [ .library(name: "UIDeviceComplete", targets: ["UIDeviceComplete"]) diff --git a/Sources/DeviceFamily.swift b/Sources/DeviceFamily.swift index 545ede2..1e353ec 100644 --- a/Sources/DeviceFamily.swift +++ b/Sources/DeviceFamily.swift @@ -26,6 +26,7 @@ public enum DeviceFamily: String { case iPhone case iPod case iPad + case watch case unknown public init(rawValue: String) { @@ -36,6 +37,8 @@ public enum DeviceFamily: String { self = .iPod case "iPad": self = .iPad + case "Watch": + self = .watch default: self = .unknown } diff --git a/Sources/DeviceModel.swift b/Sources/DeviceModel.swift index c9b5682..96ca16b 100644 --- a/Sources/DeviceModel.swift +++ b/Sources/DeviceModel.swift @@ -23,6 +23,7 @@ public enum DeviceModel: CaseIterable { + #if os(iOS) case iPhone4, iPhone4S case iPhone5, iPhone5C, iPhone5S case iPhone6, iPhone6Plus @@ -62,7 +63,24 @@ public enum DeviceModel: CaseIterable { case iPodTouchFirstGen, iPodTouchSecondGen, iPodTouchThirdGen, iPodTouchFourthGen, iPodTouchFifthGen, iPodTouchSixthGen, iPodTouchSeventhGen - + + #elseif os(watchOS) + case firstGen + case series1 + case series2 + case series3 + case series4 + case series5 + case se + case series6 + case series7 + case series8 + case se2 + case ultra + case series9 + case ultra2 + #endif + case unknown } @@ -72,19 +90,24 @@ public enum DeviceModel: CaseIterable { extension DeviceModel { init(identifier: Identifier) { switch identifier.type { + #if os(iOS) case .iPhone: self = DeviceModel.detectIphoneModel(with: identifier) case .iPad: self = DeviceModel.detectIpadModel(with: identifier) case .iPod: self = DeviceModel.detectIpodModel(with: identifier) + #elseif os(watchOS) + case .watch: + self = DeviceModel.detectWatchModel(with: identifier) + #endif default: self = .unknown } } } - +#if os(iOS) // MARK: Detecting iPhone Models extension DeviceModel { @@ -154,8 +177,9 @@ extension DeviceModel { } } } +#endif - +#if os(iOS) // MARK: Detecting iPad Models extension DeviceModel { @@ -207,8 +231,9 @@ extension DeviceModel { } } } +#endif - +#if os(iOS) // MARK: Detecting iPod Models extension DeviceModel { @@ -230,8 +255,40 @@ extension DeviceModel { } } } +#endif +#if os(watchOS) +// MARK: Detecting Apple Watch Models + +extension DeviceModel { + fileprivate static func detectWatchModel(with identifier: Identifier) -> DeviceModel { + guard let major = identifier.version.major, + let minor = identifier.version.minor + else { return .unknown } + + switch (major, minor) { + case (1, _): return .firstGen + case (2, 3), (2, 4): return .series2 + case (2, 6), (2, 7): return .series1 + case (3, _): return .series3 + case (4, _): return .series4 + case (5, 1), (5, 2), (5, 3), (5, 4): return .series5 + case (5, 9), (5, 10), (5, 11), (5, 12): return .se + case (6, 1), (6, 2), (6, 3), (6, 4): return .series6 + case (6, 6), (6, 7), (6, 8), (6, 9): return .series7 + case (6, 10), (6, 11), (6, 12), (6, 13): return .se2 + case (6, 14), (6, 15), (6, 16), (6, 17): return .series8 + case (6, 18): return .ultra + case (7, 1), (7, 2), (7, 3), (7, 4): return .series9 + case (7, 5): return .ultra2 + + default: return .unknown + } + } +} +#endif +#if os(iOS) // MARK: Detecting the Notch extension DeviceModel { @@ -266,3 +323,4 @@ extension DeviceModel { } } } +#endif diff --git a/Sources/Identifier.swift b/Sources/Identifier.swift index ff73c67..20e5f84 100644 --- a/Sources/Identifier.swift +++ b/Sources/Identifier.swift @@ -69,6 +69,8 @@ extension Identifier: CustomStringConvertible { return iPadStringRepresentation(major: major, minor: minor) case .iPod: return iPodStringRepresentation(major: major, minor: minor) + case .watch: + return watchStringRepresentable(major: major, minor: minor) case .unknown: return "unknown" } @@ -384,4 +386,99 @@ extension Identifier: CustomStringConvertible { return "unknown" } } + + private func watchStringRepresentable(major: Int, minor: Int) -> String { + switch (major, minor) { + case (1, 1): + return "Apple Watch (1st generation), 38mm case" + case (1, 2): + return "Apple Watch (1st generation), 42mm case" + case (2, 3): + return "Apple Watch Series 2, 38mm case" + case (2, 4): + return "Apple Watch Series 2, 42mm case" + case (2, 6): + return "Apple Watch Series 1, 38mm case" + case (2, 7): + return "Apple Watch Series 1, 42mm case" + case (3, 1): + return "Apple Watch Series 3, 38mm case (GPS + Cellular)" + case (3, 2): + return "Apple Watch Series 3, 42mm case (GPS + Cellular)" + case (3, 3): + return "Apple Watch Series 3, 38mm case (GPS)" + case (3, 4): + return "Apple Watch Series 3, 42mm case (GPS)" + case (4, 1): + return "Apple Watch Series 4, 40mm case (GPS)" + case (4, 2): + return "Apple Watch Series 4, 44mm case (GPS)" + case (4, 3): + return "Apple Watch Series 4, 40mm case (GPS + Cellular)" + case (4, 4): + return "Apple Watch Series 4, 44mm case (GPS + Cellular)" + case (5, 1): + return "Apple Watch Series 5, 40mm case (GPS)" + case (5, 2): + return "Apple Watch Series 5, 44mm case (GPS)" + case (5, 3): + return "Apple Watch Series 5, 40mm case (GPS + Cellular)" + case (5, 4): + return "Apple Watch Series 5, 44mm case (GPS + Cellular)" + case (5, 9): + return "Apple Watch SE, 40mm case (GPS)" + case (5, 10): + return "Apple Watch SE, 44mm case (GPS)" + case (5, 11): + return "Apple Watch SE, 40mm case (GPS + Cellular)" + case (5, 12): + return "Apple Watch SE, 44mm case (GPS + Cellular)" + case (6, 1): + return "Apple Watch Series 6, 40mm case (GPS)" + case (6, 2): + return "Apple Watch Series 6, 44mm case (GPS)" + case (6, 3): + return "Apple Watch Series 6, 40mm case (GPS + Cellular)" + case (6, 4): + return "Apple Watch Series 6, 44mm case (GPS + Cellular)" + case (6, 6): + return "Apple Watch Series 7, 41mm case (GPS)" + case (6, 7): + return "Apple Watch Series 7, 45mm case (GPS)" + case (6, 8): + return "Apple Watch Series 7, 41mm case (GPS + Cellular)" + case (6, 9): + return "Apple Watch Series 7, 45mm case (GPS + Cellular)" + case (6, 10): + return "Apple Watch SE (2nd Generation), 40mm case (GPS)" + case (6, 11): + return "Apple Watch SE (2nd Generation), 44mm case (GPS)" + case (6, 12): + return "Apple Watch SE (2nd Generation), 40mm case (GPS + Cellular)" + case (6, 13): + return "Apple Watch SE (2nd Generation), 44mm case (GPS + Cellular)" + case (6, 14): + return "Apple Watch Series 8, 41mm case (GPS)" + case (6, 15): + return "Apple Watch Series 8, 45mm case (GPS)" + case (6, 16): + return "Apple Watch Series 8, 41mm case (GPS + Cellular)" + case (6, 17): + return "Apple Watch Series 8, 45mm case (GPS + Cellular)" + case (6, 18): + return "Apple Watch Ultra" + case (7, 1): + return "Apple Watch Series 9, 41mm case (GPS)" + case (7, 2): + return "Apple Watch Series 9, 45mm case (GPS)" + case (7, 3): + return "Apple Watch Series 9, 41mm case (GPS + Cellular)" + case (7, 4): + return "Apple Watch Series 9, 45mm case (GPS + Cellular)" + case (7, 5): + return "Apple Watch Ultra 2" + default: + return "unknown" + } + } } diff --git a/Sources/Screen.swift b/Sources/Screen.swift index 5534a67..f6b9175 100644 --- a/Sources/Screen.swift +++ b/Sources/Screen.swift @@ -21,9 +21,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#if os(iOS) import UIKit +#endif public struct Screen { + #if os(iOS) init(width: Double, height: Double, scale: Double) { self.width = width self.height = height @@ -37,9 +40,16 @@ public struct Screen { public var adjustedScale: Double { return 1.0 / scale } + #elseif os(watchOS) + init(identifier: Identifier) { + self.identifier = identifier + } + + let identifier: Identifier + #endif } - +#if os(iOS) // MARK: - Detecting Screen size in Inches extension Screen { @@ -89,3 +99,33 @@ extension Screen { } } +#endif + +#if os(watchOS) +extension Screen { + public var caseSize: Int? { + guard let major = identifier.version.major, + let minor = identifier.version.minor + else { return nil } + + switch (major, minor) { + case (1, 1), (2, 3), (2, 6), (3, 1), (3, 3): return 38 + case (1, 2), (2, 4), (2, 7), (3, 2), (3, 4): return 42 + + case (4, 1), (4, 3), (5, 1), (5, 3), (5, 9), + (5, 11), (6, 1), (6, 3), (6, 10), (6, 12): return 40 + case (4, 2), (4, 4), (5, 2), (5, 4), (5, 10), + (5, 12), (6, 2), (6, 4), (6, 11), (6, 13): return 44 + + case (6, 6), (6, 8), (6, 14), (6, 16), + (7, 1), (7, 3): return 41 + case (6, 7), (6, 9), (6, 15), (6, 17), + (7, 2), (7, 4): return 45 + + case (6, 18), (7, 5): return 49 + + default: return nil + } + } +} +#endif diff --git a/Sources/UIDeviceComplete.swift b/Sources/UIDeviceComplete.swift index c84baa7..f95503f 100644 --- a/Sources/UIDeviceComplete.swift +++ b/Sources/UIDeviceComplete.swift @@ -21,7 +21,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#if os(iOS) import UIKit +#elseif os(watchOS) +import WatchKit +#endif public final class UIDeviceComplete { let base: Base @@ -42,4 +46,8 @@ public extension UIDeviceCompleteCompatible { } } +#if os(iOS) extension UIDevice: UIDeviceCompleteCompatible { } +#elseif os(watchOS) +extension WKInterfaceDevice: UIDeviceCompleteCompatible { } +#endif diff --git a/Sources/UIDeviceExtensions.swift b/Sources/UIDeviceExtensions.swift index e95c2a5..6142ad7 100644 --- a/Sources/UIDeviceExtensions.swift +++ b/Sources/UIDeviceExtensions.swift @@ -21,9 +21,15 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#if os(iOS) import UIKit +public typealias DCDevice = UIDevice +#elseif os(watchOS) +import WatchKit +public typealias DCDevice = WKInterfaceDevice +#endif -public extension UIDeviceComplete where Base == UIDevice { +public extension UIDeviceComplete where Base == DCDevice { private var identifier: Identifier? { return System.name.flatMap { @@ -45,7 +51,8 @@ public extension UIDeviceComplete where Base == UIDevice { var commonDeviceName: String { return identifier?.description ?? "unknown" } - + + #if os(iOS) /// Device family iPhone var isIphone: Bool { return deviceFamily == .iPhone @@ -60,13 +67,14 @@ public extension UIDeviceComplete where Base == UIDevice { var isIpod: Bool { return deviceFamily == .iPod } - + #endif + } - +#if os(iOS) // MARK: - Screen Size Detection -public extension UIDeviceComplete where Base == UIDevice { +public extension UIDeviceComplete where Base == DCDevice { var screenSize: Screen { let scale: Double = Double(UIScreen.main.scale) let width: Double = Double(UIScreen.main.bounds.width) @@ -75,3 +83,4 @@ public extension UIDeviceComplete where Base == UIDevice { return Screen(width: width, height: height, scale: scale) } } +#endif diff --git a/UIDeviceComplete.xcodeproj/project.pbxproj b/UIDeviceComplete.xcodeproj/project.pbxproj index 03fb1fd..4b73f4f 100644 --- a/UIDeviceComplete.xcodeproj/project.pbxproj +++ b/UIDeviceComplete.xcodeproj/project.pbxproj @@ -20,14 +20,14 @@ AA1C21AB1F385C2A0095BFBD /* UIDeviceExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C21A71F385C2A0095BFBD /* UIDeviceExtensionsTests.swift */; }; AAB1EF351F13866F003BBCF2 /* UIDeviceComplete.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AAB1EF2B1F13866F003BBCF2 /* UIDeviceComplete.framework */; }; AAB1EF3C1F13866F003BBCF2 /* UIDeviceComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = AAB1EF2E1F13866F003BBCF2 /* UIDeviceComplete.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BF72D63129880FAC00B70A2B /* WKDeviceComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = BF72D63029880FAC00B70A2B /* WKDeviceComplete.h */; settings = {ATTRIBUTES = (Public, ); }; }; BF72D63629880FCF00B70A2B /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C219A1F385BEC0095BFBD /* System.swift */; }; - BF72D638298810D700B70A2B /* DeviceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF72D637298810D700B70A2B /* DeviceModel.swift */; }; - BF72D63A2988115000B70A2B /* Identifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF72D6392988115000B70A2B /* Identifier.swift */; }; - BF72D63C29881D1A00B70A2B /* Screen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF72D63B29881D1A00B70A2B /* Screen.swift */; }; - BF72D63E2988206900B70A2B /* WKInterfaceDeviceExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF72D63D2988206900B70A2B /* WKInterfaceDeviceExtensions.swift */; }; - BF72D6402988209C00B70A2B /* WKDeviceComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF72D63F2988209C00B70A2B /* WKDeviceComplete.swift */; }; BFA9121C215B9881000CD8A8 /* DeviceModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA9121B215B9881000CD8A8 /* DeviceModelTests.swift */; }; + BFE460D02AB5A08700BE39DB /* Identifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C21981F385BEC0095BFBD /* Identifier.swift */; }; + BFE460D12AB5A08700BE39DB /* Screen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C21991F385BEC0095BFBD /* Screen.swift */; }; + BFE460D22AB5A08700BE39DB /* DeviceFamily.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C21961F385BEC0095BFBD /* DeviceFamily.swift */; }; + BFE460D32AB5A08700BE39DB /* DeviceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C21971F385BEC0095BFBD /* DeviceModel.swift */; }; + BFE460D42AB5A08C00BE39DB /* UIDeviceExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C219C1F385BEC0095BFBD /* UIDeviceExtensions.swift */; }; + BFE460D52AB5A08C00BE39DB /* UIDeviceComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1C219B1F385BEC0095BFBD /* UIDeviceComplete.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -58,12 +58,6 @@ AAB1EF341F13866F003BBCF2 /* UIDeviceCompleteTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIDeviceCompleteTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; AAB1EF3B1F13866F003BBCF2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BF72D62E29880FAC00B70A2B /* WKDeviceComplete.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WKDeviceComplete.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - BF72D63029880FAC00B70A2B /* WKDeviceComplete.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKDeviceComplete.h; sourceTree = ""; }; - BF72D637298810D700B70A2B /* DeviceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceModel.swift; sourceTree = ""; }; - BF72D6392988115000B70A2B /* Identifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identifier.swift; sourceTree = ""; }; - BF72D63B29881D1A00B70A2B /* Screen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Screen.swift; sourceTree = ""; }; - BF72D63D2988206900B70A2B /* WKInterfaceDeviceExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKInterfaceDeviceExtensions.swift; sourceTree = ""; }; - BF72D63F2988209C00B70A2B /* WKDeviceComplete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDeviceComplete.swift; sourceTree = ""; }; BFA9121B215B9881000CD8A8 /* DeviceModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DeviceModelTests.swift; path = Tests/DeviceModelTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -98,7 +92,6 @@ children = ( AAB1EF2D1F13866F003BBCF2 /* UIDeviceComplete */, AAB1EF381F13866F003BBCF2 /* UIDeviceCompleteTests */, - BF72D62F29880FAC00B70A2B /* WKDeviceComplete */, AAB1EF2C1F13866F003BBCF2 /* Products */, ); sourceTree = ""; @@ -150,19 +143,6 @@ name = Sources; sourceTree = ""; }; - BF72D62F29880FAC00B70A2B /* WKDeviceComplete */ = { - isa = PBXGroup; - children = ( - BF72D63029880FAC00B70A2B /* WKDeviceComplete.h */, - BF72D637298810D700B70A2B /* DeviceModel.swift */, - BF72D6392988115000B70A2B /* Identifier.swift */, - BF72D63B29881D1A00B70A2B /* Screen.swift */, - BF72D63F2988209C00B70A2B /* WKDeviceComplete.swift */, - BF72D63D2988206900B70A2B /* WKInterfaceDeviceExtensions.swift */, - ); - path = WKDeviceComplete; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -178,7 +158,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - BF72D63129880FAC00B70A2B /* WKDeviceComplete.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -340,12 +319,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BF72D63E2988206900B70A2B /* WKInterfaceDeviceExtensions.swift in Sources */, + BFE460D02AB5A08700BE39DB /* Identifier.swift in Sources */, + BFE460D52AB5A08C00BE39DB /* UIDeviceComplete.swift in Sources */, + BFE460D42AB5A08C00BE39DB /* UIDeviceExtensions.swift in Sources */, BF72D63629880FCF00B70A2B /* System.swift in Sources */, - BF72D63A2988115000B70A2B /* Identifier.swift in Sources */, - BF72D638298810D700B70A2B /* DeviceModel.swift in Sources */, - BF72D6402988209C00B70A2B /* WKDeviceComplete.swift in Sources */, - BF72D63C29881D1A00B70A2B /* Screen.swift in Sources */, + BFE460D32AB5A08700BE39DB /* DeviceModel.swift in Sources */, + BFE460D12AB5A08700BE39DB /* Screen.swift in Sources */, + BFE460D22AB5A08700BE39DB /* DeviceFamily.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WKDeviceComplete/DeviceModel.swift b/WKDeviceComplete/DeviceModel.swift deleted file mode 100644 index 3d80f1a..0000000 --- a/WKDeviceComplete/DeviceModel.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// DeviceModel.swift -// -// Copyright (c) 2017-2023 Nicholas Maccharoli -// Copyright (c) 2023 Vincent Neo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -public enum DeviceModel: CaseIterable { - case firstGen - case series1 - case series2 - case series3 - case series4 - case series5 - case se - case series6 - case series7 - case series8 - case se2 - case ultra - case series9 - case ultra2 - - case unknown -} - -// MARK: - init - -extension DeviceModel { - init(identifier: Identifier) { - self = DeviceModel.detectWatchModel(with: identifier) - } -} - -extension DeviceModel { - fileprivate static func detectWatchModel(with identifier: Identifier) -> DeviceModel { - guard let major = identifier.version.major, - let minor = identifier.version.minor - else { return .unknown } - - switch (major, minor) { - case (1, _): return .firstGen - case (2, 3), (2, 4): return .series2 - case (2, 6), (2, 7): return .series1 - case (3, _): return .series3 - case (4, _): return .series4 - case (5, 1), (5, 2), (5, 3), (5, 4): return .series5 - case (5, 9), (5, 10), (5, 11), (5, 12): return .se - case (6, 1), (6, 2), (6, 3), (6, 4): return .series6 - case (6, 6), (6, 7), (6, 8), (6, 9): return .series7 - case (6, 10), (6, 11), (6, 12), (6, 13): return .se2 - case (6, 14), (6, 15), (6, 16), (6, 17): return .series8 - case (6, 18): return .ultra - case (7, 1), (7, 2), (7, 3), (7, 4): return .series9 - case (7, 5): return .ultra2 - - default: return .unknown - } - } -} diff --git a/WKDeviceComplete/Identifier.swift b/WKDeviceComplete/Identifier.swift deleted file mode 100644 index b282b74..0000000 --- a/WKDeviceComplete/Identifier.swift +++ /dev/null @@ -1,162 +0,0 @@ -// -// Identifier.swift -// -// Copyright (c) 2017-2023 Nicholas Maccharoli -// Copyright (c) 2023 Vincent Neo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -struct Identifier { - let version: (major: Int?, minor: Int?) - - init(_ identifier: String) { - let (major, minor) = Identifier.typeVersionComponents(with: identifier) - self.version = (major, minor) - } -} - - -// MARK: - Identifier String parsing - -extension Identifier { - static func typeVersionComponents(with identifierString: String) -> (major: Int?, minor: Int?) { - - let numericCharacters: [String] = (0...9).map { "\($0)" } - let type = identifierString.prefix(while: { !numericCharacters.contains(String($0))}) - - let version = identifierString.suffix(from: type.endIndex) - .split(separator: ",") - .map { Int($0) } - - let major: Int? = !version.isEmpty ? version[0] : nil - let minor: Int? = version.count > 1 ? version[1] : nil - - return (major, minor) - } -} - - -// MARK: - String Representation - Watch - -extension Identifier: CustomStringConvertible { - var description: String { - - guard let major = version.major, - let minor = version.minor - else { return "unknown" } - - return watchStringRepresentable(major: major, minor: minor) - } - - private func watchStringRepresentable(major: Int, minor: Int) -> String { - switch (major, minor) { - case (1, 1): - return "Apple Watch (1st generation), 38mm case" - case (1, 2): - return "Apple Watch (1st generation), 42mm case" - case (2, 3): - return "Apple Watch Series 2, 38mm case" - case (2, 4): - return "Apple Watch Series 2, 42mm case" - case (2, 6): - return "Apple Watch Series 1, 38mm case" - case (2, 7): - return "Apple Watch Series 1, 42mm case" - case (3, 1): - return "Apple Watch Series 3, 38mm case (GPS + Cellular)" - case (3, 2): - return "Apple Watch Series 3, 42mm case (GPS + Cellular)" - case (3, 3): - return "Apple Watch Series 3, 38mm case (GPS)" - case (3, 4): - return "Apple Watch Series 3, 42mm case (GPS)" - case (4, 1): - return "Apple Watch Series 4, 40mm case (GPS)" - case (4, 2): - return "Apple Watch Series 4, 44mm case (GPS)" - case (4, 3): - return "Apple Watch Series 4, 40mm case (GPS + Cellular)" - case (4, 4): - return "Apple Watch Series 4, 44mm case (GPS + Cellular)" - case (5, 1): - return "Apple Watch Series 5, 40mm case (GPS)" - case (5, 2): - return "Apple Watch Series 5, 44mm case (GPS)" - case (5, 3): - return "Apple Watch Series 5, 40mm case (GPS + Cellular)" - case (5, 4): - return "Apple Watch Series 5, 44mm case (GPS + Cellular)" - case (5, 9): - return "Apple Watch SE, 40mm case (GPS)" - case (5, 10): - return "Apple Watch SE, 44mm case (GPS)" - case (5, 11): - return "Apple Watch SE, 40mm case (GPS + Cellular)" - case (5, 12): - return "Apple Watch SE, 44mm case (GPS + Cellular)" - case (6, 1): - return "Apple Watch Series 6, 40mm case (GPS)" - case (6, 2): - return "Apple Watch Series 6, 44mm case (GPS)" - case (6, 3): - return "Apple Watch Series 6, 40mm case (GPS + Cellular)" - case (6, 4): - return "Apple Watch Series 6, 44mm case (GPS + Cellular)" - case (6, 6): - return "Apple Watch Series 7, 41mm case (GPS)" - case (6, 7): - return "Apple Watch Series 7, 45mm case (GPS)" - case (6, 8): - return "Apple Watch Series 7, 41mm case (GPS + Cellular)" - case (6, 9): - return "Apple Watch Series 7, 45mm case (GPS + Cellular)" - case (6, 10): - return "Apple Watch SE (2nd Generation), 40mm case (GPS)" - case (6, 11): - return "Apple Watch SE (2nd Generation), 44mm case (GPS)" - case (6, 12): - return "Apple Watch SE (2nd Generation), 40mm case (GPS + Cellular)" - case (6, 13): - return "Apple Watch SE (2nd Generation), 44mm case (GPS + Cellular)" - case (6, 14): - return "Apple Watch Series 8, 41mm case (GPS)" - case (6, 15): - return "Apple Watch Series 8, 45mm case (GPS)" - case (6, 16): - return "Apple Watch Series 8, 41mm case (GPS + Cellular)" - case (6, 17): - return "Apple Watch Series 8, 45mm case (GPS + Cellular)" - case (6, 18): - return "Apple Watch Ultra" - case (7, 1): - return "Apple Watch Series 9, 41mm case (GPS)" - case (7, 2): - return "Apple Watch Series 9, 45mm case (GPS)" - case (7, 3): - return "Apple Watch Series 9, 41mm case (GPS + Cellular)" - case (7, 4): - return "Apple Watch Series 9, 45mm case (GPS + Cellular)" - case (7, 5): - return "Apple Watch Ultra 2" - default: - return "unknown" - } - } - -} diff --git a/WKDeviceComplete/Screen.swift b/WKDeviceComplete/Screen.swift deleted file mode 100644 index c5856de..0000000 --- a/WKDeviceComplete/Screen.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// Screen.swift -// -// Copyright (c) 2017-2023 Nicholas Maccharoli -// Copyright (c) 2023 Vincent Neo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -public struct Screen { - let caseSize: Int? -} - -extension Screen { - init(identifier: Identifier) { - self.caseSize = Screen.detectCaseSize(with: identifier) - } -} - -// MARK: - Detecting Screen size by model, in mm - -extension Screen { - fileprivate static func detectCaseSize(with identifier: Identifier) -> Int? { - guard let major = identifier.version.major, - let minor = identifier.version.minor - else { return nil } - - switch (major, minor) { - case (1, 1), (2, 3), (2, 6), (3, 1), (3, 3): return 38 - case (1, 2), (2, 4), (2, 7), (3, 2), (3, 4): return 42 - - case (4, 1), (4, 3), (5, 1), (5, 3), (5, 9), - (5, 11), (6, 1), (6, 3), (6, 10), (6, 12): return 40 - case (4, 2), (4, 4), (5, 2), (5, 4), (5, 10), - (5, 12), (6, 2), (6, 4), (6, 11), (6, 13): return 44 - - case (6, 6), (6, 8), (6, 14), (6, 16), - (7, 1), (7, 3): return 41 - case (6, 7), (6, 9), (6, 15), (6, 17), - (7, 2), (7, 4): return 45 - - case (6, 18), (7, 5): return 49 - - default: return nil - } - } -} diff --git a/WKDeviceComplete/WKDeviceComplete.h b/WKDeviceComplete/WKDeviceComplete.h deleted file mode 100644 index 6b75725..0000000 --- a/WKDeviceComplete/WKDeviceComplete.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// WKDeviceComplete.h -// WKDeviceComplete -// -// Created by Vincent Neo on 30/1/23. -// Copyright © 2023 Nicholas Maccharoli. All rights reserved. -// - -#import - -//! Project version number for WKDeviceComplete. -FOUNDATION_EXPORT double WKDeviceCompleteVersionNumber; - -//! Project version string for WKDeviceComplete. -FOUNDATION_EXPORT const unsigned char WKDeviceCompleteVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/WKDeviceComplete/WKDeviceComplete.swift b/WKDeviceComplete/WKDeviceComplete.swift deleted file mode 100644 index a4312be..0000000 --- a/WKDeviceComplete/WKDeviceComplete.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// WKDeviceComplete.swift -// -// Copyright (c) 2017-2023 Nicholas Maccharoli -// Copyright (c) 2023 Vincent Neo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import WatchKit - -public final class WKDeviceComplete { - let base: Base - public init(_ base: Base) { - self.base = base - } -} - -public protocol WKDeviceCompleteCompatible { - associatedtype CompatibleType - - var dc: CompatibleType { get } -} - -public extension WKDeviceCompleteCompatible { - var dc: WKDeviceComplete { - return WKDeviceComplete(self) - } -} - -extension WKInterfaceDevice: WKDeviceCompleteCompatible { } diff --git a/WKDeviceComplete/WKInterfaceDeviceExtensions.swift b/WKDeviceComplete/WKInterfaceDeviceExtensions.swift deleted file mode 100644 index cf19473..0000000 --- a/WKDeviceComplete/WKInterfaceDeviceExtensions.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// WKInterfaceDeviceExtensions.swift -// -// Copyright (c) 2017-2023 Nicholas Maccharoli -// Copyright (c) 2023 Vincent Neo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import WatchKit - -public extension WKDeviceComplete where Base == WKInterfaceDevice { - - private var identifier: Identifier? { - return System.name.flatMap { - return Identifier($0) - } - } - - /// Specific model i.e iphone7 or iPhone7s - var deviceModel: DeviceModel { - return identifier.flatMap { DeviceModel(identifier: $0) } ?? .unknown - } - - /// Common name for device i.e "iPhone 7 Plus" - var commonDeviceName: String { - return identifier?.description ?? "unknown" - } - -} - -// MARK: - Screen Size Detection - -public extension WKDeviceComplete where Base == WKInterfaceDevice { - var screenSize: Screen? { - guard let identifier else { return nil } - return Screen(identifier: identifier) - } -}