mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-20 03:34:50 +00:00
Restores first-use iOS authorization prompts for Contacts, Calendar, and Reminders by adding the missing usage descriptions, requesting access from `.notDetermined` in the service paths, and adding Settings Privacy & Access status/actions. Verification: - `plutil -lint apps/ios/Sources/Info.plist apps/ios/Tests/Info.plist apps/ios/ShareExtension/Info.plist apps/ios/ActivityWidget/Info.plist apps/ios/WatchApp/Info.plist apps/ios/WatchExtension/Info.plist` - `swiftformat --lint apps/ios/Sources/Permissions/PermissionRequestBridge.swift apps/ios/Sources/Contacts/ContactsService.swift apps/ios/Sources/Calendar/CalendarService.swift apps/ios/Sources/Reminders/RemindersService.swift apps/ios/Sources/Settings/PrivacyAccessSectionView.swift apps/ios/Sources/Settings/SettingsTab.swift apps/ios/Sources/Onboarding/GatewayOnboardingView.swift apps/shared/OpenClawKit/Sources/OpenClawKit/DeepLinks.swift --config config/swiftformat` - `swiftlint lint --config apps/ios/.swiftlint.yml apps/ios/Sources/Permissions/PermissionRequestBridge.swift apps/ios/Sources/Contacts/ContactsService.swift apps/ios/Sources/Calendar/CalendarService.swift apps/ios/Sources/Reminders/RemindersService.swift apps/ios/Sources/Settings/PrivacyAccessSectionView.swift apps/ios/Sources/Settings/SettingsTab.swift apps/ios/Sources/Onboarding/GatewayOnboardingView.swift apps/ios/Tests/PermissionRequestBridgeTests.swift` - `git diff --check origin/main...HEAD` - `rg '<<<<<<<|=======|>>>>>>>' CHANGELOG.md apps/ios apps/shared/OpenClawKit/Sources/OpenClawKit/DeepLinks.swift` - `pnpm ios:build` - `xcodebuild test -project apps/ios/OpenClaw.xcodeproj -scheme OpenClaw -destination 'platform=iOS Simulator,name=iPhone 17' -configuration Debug -only-testing:OpenClawTests/PermissionRequestBridgeTests` - Fresh-erased iPhone 17 simulator proof for Contacts denial/Open Settings, Calendar add-only/full-access upgrade, and Reminders authorization prompts. Not tested: physical device, or a paired gateway command invocation after onboarding.
65 lines
2.0 KiB
Swift
65 lines
2.0 KiB
Swift
import Foundation
|
|
|
|
enum PermissionRequestBridge {
|
|
final class Box: @unchecked Sendable {
|
|
private let lock = NSLock()
|
|
private var continuation: CheckedContinuation<Bool, Never>?
|
|
private var hasResumed = false
|
|
|
|
func install(_ continuation: CheckedContinuation<Bool, Never>) -> Bool {
|
|
self.lock.lock()
|
|
if self.hasResumed {
|
|
self.lock.unlock()
|
|
continuation.resume(returning: false)
|
|
return false
|
|
}
|
|
self.continuation = continuation
|
|
self.lock.unlock()
|
|
return true
|
|
}
|
|
|
|
func resume(_ value: Bool) {
|
|
self.lock.lock()
|
|
guard !self.hasResumed else {
|
|
self.lock.unlock()
|
|
return
|
|
}
|
|
self.hasResumed = true
|
|
let continuation = self.continuation
|
|
self.continuation = nil
|
|
self.lock.unlock()
|
|
continuation?.resume(returning: value)
|
|
}
|
|
|
|
func canStartRequest() -> Bool {
|
|
self.lock.lock()
|
|
let canStart = !self.hasResumed
|
|
self.lock.unlock()
|
|
return canStart
|
|
}
|
|
}
|
|
|
|
static func awaitRequest(
|
|
_ start: @escaping @Sendable (@escaping @Sendable (Bool) -> Void) -> Void) async -> Bool
|
|
{
|
|
let box = Box()
|
|
return await withTaskCancellationHandler {
|
|
await withCheckedContinuation(isolation: nil) { continuation in
|
|
guard !Task.isCancelled else {
|
|
continuation.resume(returning: false)
|
|
return
|
|
}
|
|
guard box.install(continuation) else { return }
|
|
Task { @MainActor in
|
|
guard box.canStartRequest() else { return }
|
|
start { granted in
|
|
box.resume(granted)
|
|
}
|
|
}
|
|
}
|
|
} onCancel: {
|
|
box.resume(false)
|
|
}
|
|
}
|
|
}
|