Skip to content

Commit e2dc51e

Browse files
jkmasselclaude
andcommitted
Decouple WordPressKit from UIKit
Introduce DeviceInformation struct to replace direct UIDevice usage in NotificationSettingsServiceRemote. Use ProcessInfo for OS version in SessionDetails. Guard UIKit-only code with #if canImport(UIKit) in HTTPAuthenticationAlertController, UIDevice+Extensions, NSMutableParagraphStyle+extensions, GravatarServiceRemote (upload), PluginDirectoryEntry (HTML text extraction), and SiteDesignServiceRemote (screen scale). Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent 29e7345 commit e2dc51e

10 files changed

Lines changed: 66 additions & 22 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Foundation
2+
3+
/// Device metadata needed for push notification registration.
4+
///
5+
/// This protocol decouples networking code from UIKit, allowing WordPressKit to build on macOS.
6+
/// On iOS, `UIDevice` conforms to this protocol automatically.
7+
public protocol DeviceInformationProvider {
8+
var name: String { get }
9+
var systemVersion: String { get }
10+
var identifierForVendor: UUID? { get }
11+
}
12+
13+
extension DeviceInformationProvider {
14+
/// The hardware machine identifier (e.g. "iPhone15,2", "Mac14,6").
15+
public var hardwarePlatform: String {
16+
var size = 0
17+
sysctlbyname("hw.machine", nil, &size, nil, 0)
18+
var machine = [CChar](repeating: 0, count: size)
19+
sysctlbyname("hw.machine", &machine, &size, nil, 0)
20+
return String(cString: machine)
21+
}
22+
}
23+
24+
#if canImport(UIKit)
25+
import UIKit
26+
27+
extension UIDevice: DeviceInformationProvider {}
28+
#endif

Modules/Sources/WordPressKit/GravatarServiceRemote.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ open class GravatarServiceRemote {
7272
task.resume()
7373
}
7474

75+
#if canImport(UIKit)
7576
/// This method hits the Gravatar Endpoint, and uploads a new image, to be used as profile.
7677
///
7778
/// - Parameters:
@@ -105,6 +106,7 @@ open class GravatarServiceRemote {
105106

106107
task.resume()
107108
}
109+
#endif
108110

109111
// MARK: - Private Helpers
110112

Modules/Sources/WordPressKit/HTTPAuthenticationAlertController.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if canImport(UIKit)
12
import Foundation
23
import UIKit
34

@@ -102,3 +103,4 @@ open class HTTPAuthenticationAlertController {
102103
}
103104

104105
}
106+
#endif

Modules/Sources/WordPressKit/NSMutableParagraphStyle+extensions.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import Foundation
1+
#if canImport(AppKit)
2+
import AppKit
3+
#elseif canImport(UIKit)
4+
import UIKit
5+
#endif
26

37
extension NSMutableParagraphStyle {
48
@objc convenience public init(minLineHeight: CGFloat, lineBreakMode: NSLineBreakMode, alignment: NSTextAlignment) {

Modules/Sources/WordPressKit/NotificationSettingsServiceRemote.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,23 @@ open class NotificationSettingsServiceRemote: ServiceRemoteWordPressComREST {
5555
/// - Parameters:
5656
/// - token: The token of the device to be registered.
5757
/// - pushNotificationAppId: The app id to be registered.
58+
/// - deviceInformation: Metadata about the device being registered.
5859
/// - success: Optional closure to be called on success.
5960
/// - failure: Optional closure to be called on failure.
6061
///
61-
@objc open func registerDeviceForPushNotifications(_ token: String, pushNotificationAppId: String, success: ((_ deviceId: String) -> Void)?, failure: ((NSError) -> Void)?) {
62+
open func registerDeviceForPushNotifications(_ token: String, pushNotificationAppId: String, deviceInformation: some DeviceInformationProvider, success: ((_ deviceId: String) -> Void)?, failure: ((NSError) -> Void)?) {
6263
let endpoint = "devices/new"
6364
let requestUrl = path(forEndpoint: endpoint, withVersion: ._1_1)
6465

65-
let device = UIDevice.current
6666
let parameters = [
6767
"device_token": token,
6868
"device_family": "apple",
6969
"app_secret_key": pushNotificationAppId,
70-
"device_name": device.name,
71-
"device_model": device.platform,
72-
"os_version": device.systemVersion,
70+
"device_name": deviceInformation.name,
71+
"device_model": deviceInformation.hardwarePlatform,
72+
"os_version": deviceInformation.systemVersion,
7373
"app_version": Bundle.main.wpkit_bundleVersion(),
74-
"device_uuid": device.identifierForVendor?.uuidString
74+
"device_uuid": deviceInformation.identifierForVendor?.uuidString
7575
]
7676

7777
wordPressComRESTAPI.post(requestUrl,

Modules/Sources/WordPressKit/PluginDirectoryEntry.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import Foundation
2+
#if canImport(AppKit)
3+
import AppKit
4+
#elseif canImport(UIKit)
5+
import UIKit
6+
#endif
27

38
public struct PluginDirectoryEntry {
49
public let name: String
@@ -17,7 +22,7 @@ public struct PluginDirectoryEntry {
1722
let faqHTML: String?
1823
let changelogHTML: String?
1924

20-
public var descriptionText: NSAttributedString? {
25+
public var descriptionText: NSAttributedString? {
2126
return extractHTMLText(self.descriptionHTML)
2227
}
2328
public var installationText: NSAttributedString? {

Modules/Sources/WordPressKit/SessionDetails.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ extension SessionDetails: Encodable {
2525
self.buildNumber = bundle.infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"
2626
self.marketingVersion = bundle.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
2727
self.identifier = bundle.bundleIdentifier ?? "Unknown"
28-
self.osVersion = UIDevice.current.systemVersion
28+
let version = ProcessInfo.processInfo.operatingSystemVersion
29+
self.osVersion = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
2930
}
3031

3132
func dictionaryRepresentation() throws -> [String: AnyObject]? {

Modules/Sources/WordPressKit/SiteDesignServiceRemote.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import Foundation
2+
#if canImport(AppKit)
3+
import AppKit
4+
#elseif canImport(UIKit)
5+
import UIKit
6+
#endif
27

38
public struct SiteDesignRequest {
49
public enum TemplateGroup: String {
@@ -14,14 +19,22 @@ public struct SiteDesignRequest {
1419
parameters = [
1520
"preview_width": "\(thumbnailSize.width)" as AnyObject,
1621
"preview_height": "\(thumbnailSize.height)" as AnyObject,
17-
"scale": UIScreen.main.nativeScale as AnyObject
22+
"scale": Self.screenScale as AnyObject
1823
]
1924
if 0 < groups.count {
2025
let groups = groups.map { $0.rawValue }
2126
parameters["group"] = groups.joined(separator: ",") as AnyObject
2227
}
2328
self.parameters = parameters
2429
}
30+
31+
private static var screenScale: CGFloat {
32+
#if canImport(UIKit)
33+
return UIScreen.main.nativeScale
34+
#else
35+
return 1.0
36+
#endif
37+
}
2538
}
2639

2740
public class SiteDesignServiceRemote {

Modules/Sources/WordPressKit/UIDevice+Extensions.swift

Lines changed: 0 additions & 12 deletions
This file was deleted.

WordPress/Classes/Services/NotificationSettingsService.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class NotificationSettingsService {
148148
notificationsServiceRemote?.registerDeviceForPushNotifications(
149149
token,
150150
pushNotificationAppId: BuildSettings.current.pushNotificationAppID,
151+
deviceInformation: UIDevice.current,
151152
success: success,
152153
failure: failure
153154
)

0 commit comments

Comments
 (0)