mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
fix: harden ios app build hygiene
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
import UserNotifications
|
||||
@preconcurrency import UserNotifications
|
||||
|
||||
struct ExecApprovalNotificationPrompt: Sendable, Equatable {
|
||||
struct ExecApprovalNotificationPrompt: Equatable {
|
||||
let approvalId: String
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ enum ExecApprovalNotificationBridge {
|
||||
|
||||
static func parsePrompt(
|
||||
actionIdentifier: String,
|
||||
userInfo: [AnyHashable: Any]
|
||||
) -> ExecApprovalNotificationPrompt?
|
||||
userInfo: [AnyHashable: Any]) -> ExecApprovalNotificationPrompt?
|
||||
{
|
||||
guard actionIdentifier == UNNotificationDefaultActionIdentifier
|
||||
|| actionIdentifier == self.reviewActionIdentifier
|
||||
@@ -54,8 +53,7 @@ enum ExecApprovalNotificationBridge {
|
||||
@MainActor
|
||||
static func handleResolvedPushIfNeeded(
|
||||
userInfo: [AnyHashable: Any],
|
||||
notificationCenter: NotificationCentering
|
||||
) async -> Bool
|
||||
notificationCenter: NotificationCentering) async -> Bool
|
||||
{
|
||||
guard self.payloadKind(userInfo: userInfo) == self.resolvedKind,
|
||||
let approvalId = self.approvalID(from: userInfo)
|
||||
@@ -70,8 +68,8 @@ enum ExecApprovalNotificationBridge {
|
||||
@MainActor
|
||||
static func removeNotifications(
|
||||
forApprovalID approvalId: String,
|
||||
notificationCenter: NotificationCentering
|
||||
) async {
|
||||
notificationCenter: NotificationCentering) async
|
||||
{
|
||||
let normalizedID = approvalId.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !normalizedID.isEmpty else { return }
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ actor PushRegistrationManager {
|
||||
}
|
||||
guard let installationId = GatewaySettingsStore.loadStableInstanceID()?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!installationId.isEmpty
|
||||
!installationId.isEmpty
|
||||
else {
|
||||
throw PushRelayError.relayMisconfigured("Missing stable installation ID for relay registration")
|
||||
}
|
||||
@@ -145,7 +145,7 @@ actor PushRegistrationManager {
|
||||
guard let expiresAtMs else { return true }
|
||||
let nowMs = Int64(Date().timeIntervalSince1970 * 1000)
|
||||
// Refresh shortly before expiry so reconnect-path republishes a live handle.
|
||||
return expiresAtMs <= nowMs + 60_000
|
||||
return expiresAtMs <= nowMs + 60000
|
||||
}
|
||||
|
||||
private static func sha256Hex(_ value: String) -> String {
|
||||
|
||||
@@ -24,7 +24,7 @@ enum PushRelayError: LocalizedError {
|
||||
case .unsupportedAppAttest:
|
||||
"App Attest unavailable on this device"
|
||||
case .missingReceipt:
|
||||
"App Store receipt missing after refresh"
|
||||
"App Store app transaction missing after refresh"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,33 +85,6 @@ private struct RelayErrorResponse: Decodable {
|
||||
var reason: String?
|
||||
}
|
||||
|
||||
private final class PushRelayReceiptRefreshCoordinator: NSObject, SKRequestDelegate {
|
||||
private var continuation: CheckedContinuation<Void, Error>?
|
||||
private var activeRequest: SKReceiptRefreshRequest?
|
||||
|
||||
func refresh() async throws {
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
self.continuation = continuation
|
||||
let request = SKReceiptRefreshRequest()
|
||||
self.activeRequest = request
|
||||
request.delegate = self
|
||||
request.start()
|
||||
}
|
||||
}
|
||||
|
||||
func requestDidFinish(_ request: SKRequest) {
|
||||
self.continuation?.resume(returning: ())
|
||||
self.continuation = nil
|
||||
self.activeRequest = nil
|
||||
}
|
||||
|
||||
func request(_ request: SKRequest, didFailWithError error: Error) {
|
||||
self.continuation?.resume(throwing: error)
|
||||
self.continuation = nil
|
||||
self.activeRequest = nil
|
||||
}
|
||||
}
|
||||
|
||||
private struct PushRelayAppAttestProof {
|
||||
var keyId: String
|
||||
var attestationObject: String?
|
||||
@@ -197,25 +170,27 @@ private final class PushRelayAppAttestService {
|
||||
|
||||
private final class PushRelayReceiptProvider {
|
||||
func loadReceiptBase64() async throws -> String {
|
||||
if let receipt = self.readReceiptData() {
|
||||
return receipt.base64EncodedString()
|
||||
do {
|
||||
let result = try await AppTransaction.shared
|
||||
return try Self.appTransactionBase64(result)
|
||||
} catch {
|
||||
let refreshed = try await AppTransaction.refresh()
|
||||
return try Self.appTransactionBase64(refreshed)
|
||||
}
|
||||
let refreshCoordinator = PushRelayReceiptRefreshCoordinator()
|
||||
try await refreshCoordinator.refresh()
|
||||
if let refreshed = self.readReceiptData() {
|
||||
return refreshed.base64EncodedString()
|
||||
}
|
||||
throw PushRelayError.missingReceipt
|
||||
}
|
||||
|
||||
private func readReceiptData() -> Data? {
|
||||
guard let url = Bundle.main.appStoreReceiptURL else { return nil }
|
||||
guard let data = try? Data(contentsOf: url), !data.isEmpty else { return nil }
|
||||
return data
|
||||
private static func appTransactionBase64(
|
||||
_ result: StoreKit.VerificationResult<AppTransaction>) throws -> String
|
||||
{
|
||||
let jws = result.jwsRepresentation.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !jws.isEmpty else {
|
||||
throw PushRelayError.missingReceipt
|
||||
}
|
||||
return Data(jws.utf8).base64EncodedString()
|
||||
}
|
||||
}
|
||||
|
||||
// The client is constructed once and used behind PushRegistrationManager actor isolation.
|
||||
/// The client is constructed once and used behind PushRegistrationManager actor isolation.
|
||||
final class PushRelayClient: @unchecked Sendable {
|
||||
private let baseURL: URL
|
||||
private let session: URLSession
|
||||
@@ -294,8 +269,7 @@ final class PushRelayClient: @unchecked Sendable {
|
||||
status: status,
|
||||
message: Self.decodeErrorMessage(data: data))
|
||||
}
|
||||
let decoded = try self.decode(PushRelayRegisterResponse.self, from: data)
|
||||
return decoded
|
||||
return try self.decode(PushRelayRegisterResponse.self, from: data)
|
||||
}
|
||||
|
||||
private func fetchChallenge() async throws -> PushRelayChallengeResponse {
|
||||
|
||||
Reference in New Issue
Block a user