fix(ios): enable strict concurrency checks

This commit is contained in:
Peter Steinberger
2026-01-10 16:03:38 +00:00
parent e4fea2b80b
commit f428ed9038
6 changed files with 47 additions and 8 deletions

View File

@@ -115,7 +115,7 @@ final class BridgeConnectionController {
self.didAutoConnect = true self.didAutoConnect = true
let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(manualHost), port: port) let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(manualHost), port: port)
self.startAutoConnect(endpoint: endpoint, token: token, instanceId: instanceId) self.startAutoConnect(endpoint: endpoint, bridgeStableID: nil, token: token, instanceId: instanceId)
return return
} }
@@ -132,7 +132,11 @@ final class BridgeConnectionController {
guard let target = self.bridges.first(where: { $0.stableID == targetStableID }) else { return } guard let target = self.bridges.first(where: { $0.stableID == targetStableID }) else { return }
self.didAutoConnect = true self.didAutoConnect = true
self.startAutoConnect(endpoint: target.endpoint, token: token, instanceId: instanceId) self.startAutoConnect(
endpoint: target.endpoint,
bridgeStableID: target.stableID,
token: token,
instanceId: instanceId)
} }
private func updateLastDiscoveredBridge(from bridges: [BridgeDiscoveryModel.DiscoveredBridge]) { private func updateLastDiscoveredBridge(from bridges: [BridgeDiscoveryModel.DiscoveredBridge]) {
@@ -171,7 +175,12 @@ final class BridgeConnectionController {
"bridge-token.\(instanceId)" "bridge-token.\(instanceId)"
} }
private func startAutoConnect(endpoint: NWEndpoint, token: String, instanceId: String) { private func startAutoConnect(
endpoint: NWEndpoint,
bridgeStableID: String?,
token: String,
instanceId: String)
{
guard let appModel else { return } guard let appModel else { return }
Task { [weak self] in Task { [weak self] in
guard let self else { return } guard let self else { return }
@@ -192,7 +201,10 @@ final class BridgeConnectionController {
service: "com.clawdbot.bridge", service: "com.clawdbot.bridge",
account: self.keychainAccount(instanceId: instanceId)) account: self.keychainAccount(instanceId: instanceId))
} }
appModel.connectToBridge(endpoint: endpoint, hello: self.makeHello(token: resolvedToken)) appModel.connectToBridge(
endpoint: endpoint,
bridgeStableID: bridgeStableID,
hello: self.makeHello(token: resolvedToken))
} catch { } catch {
await MainActor.run { await MainActor.run {
appModel.bridgeStatusText = "Bridge error: \(error.localizedDescription)" appModel.bridgeStatusText = "Bridge error: \(error.localizedDescription)"

View File

@@ -35,10 +35,10 @@
<string>Clawdbot can capture photos or short video clips when requested via the bridge.</string> <string>Clawdbot can capture photos or short video clips when requested via the bridge.</string>
<key>NSLocalNetworkUsageDescription</key> <key>NSLocalNetworkUsageDescription</key>
<string>Clawdbot discovers and connects to your Clawdbot bridge on the local network.</string> <string>Clawdbot discovers and connects to your Clawdbot bridge on the local network.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Clawdbot uses your location when you allow location sharing.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Clawdbot can share your location in the background when you enable Always.</string> <string>Clawdbot can share your location in the background when you enable Always.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Clawdbot uses your location when you allow location sharing.</string>
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>
<string>Clawdbot needs microphone access for voice wake.</string> <string>Clawdbot needs microphone access for voice wake.</string>
<key>NSSpeechRecognitionUsageDescription</key> <key>NSSpeechRecognitionUsageDescription</key>

View File

@@ -204,12 +204,14 @@ final class NodeAppModel {
func connectToBridge( func connectToBridge(
endpoint: NWEndpoint, endpoint: NWEndpoint,
bridgeStableID: String? = nil,
hello: BridgeHello) hello: BridgeHello)
{ {
self.bridgeTask?.cancel() self.bridgeTask?.cancel()
self.bridgeServerName = nil self.bridgeServerName = nil
self.bridgeRemoteAddress = nil self.bridgeRemoteAddress = nil
self.connectedBridgeID = BridgeEndpointID.stableID(endpoint) let id = (bridgeStableID ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
self.connectedBridgeID = id.isEmpty ? BridgeEndpointID.stableID(endpoint) : id
self.voiceWakeSyncTask?.cancel() self.voiceWakeSyncTask?.cancel()
self.voiceWakeSyncTask = nil self.voiceWakeSyncTask = nil

View File

@@ -425,6 +425,7 @@ struct SettingsTab: View {
self.appModel.connectToBridge( self.appModel.connectToBridge(
endpoint: bridge.endpoint, endpoint: bridge.endpoint,
bridgeStableID: bridge.stableID,
hello: BridgeHello( hello: BridgeHello(
nodeId: self.instanceId, nodeId: self.instanceId,
displayName: self.displayName, displayName: self.displayName,
@@ -499,6 +500,7 @@ struct SettingsTab: View {
self.appModel.connectToBridge( self.appModel.connectToBridge(
endpoint: endpoint, endpoint: endpoint,
bridgeStableID: nil,
hello: BridgeHello( hello: BridgeHello(
nodeId: self.instanceId, nodeId: self.instanceId,
displayName: self.displayName, displayName: self.displayName,

View File

@@ -175,7 +175,6 @@ private func withKeychainValues<T>(
} }
@Test @MainActor func makeHelloBuildsCapsAndCommands() { @Test @MainActor func makeHelloBuildsCapsAndCommands() {
let defaults = UserDefaults.standard
let voiceWakeKey = VoiceWakePreferences.enabledKey let voiceWakeKey = VoiceWakePreferences.enabledKey
withKeychainValues([instanceIdEntry: nil, preferredBridgeEntry: nil, lastBridgeEntry: nil]) { withKeychainValues([instanceIdEntry: nil, preferredBridgeEntry: nil, lastBridgeEntry: nil]) {

View File

@@ -5,6 +5,10 @@ options:
iOS: "17.0" iOS: "17.0"
xcodeVersion: "16.0" xcodeVersion: "16.0"
settings:
base:
SWIFT_VERSION: "6.0"
packages: packages:
ClawdbotKit: ClawdbotKit:
path: ../shared/ClawdbotKit path: ../shared/ClawdbotKit
@@ -68,11 +72,15 @@ targets:
PRODUCT_BUNDLE_IDENTIFIER: com.clawdbot.ios PRODUCT_BUNDLE_IDENTIFIER: com.clawdbot.ios
PROVISIONING_PROFILE_SPECIFIER: "com.clawdbot.ios Development" PROVISIONING_PROFILE_SPECIFIER: "com.clawdbot.ios Development"
SWIFT_VERSION: "6.0" SWIFT_VERSION: "6.0"
SWIFT_STRICT_CONCURRENCY: complete
ENABLE_APPINTENTS_METADATA: NO
info: info:
path: Sources/Info.plist path: Sources/Info.plist
properties: properties:
CFBundleDisplayName: Clawdbot CFBundleDisplayName: Clawdbot
CFBundleIconName: AppIcon CFBundleIconName: AppIcon
CFBundleShortVersionString: "2026.1.9"
CFBundleVersion: "20260109"
UILaunchScreen: {} UILaunchScreen: {}
UIApplicationSceneManifest: UIApplicationSceneManifest:
UIApplicationSupportsMultipleScenes: false UIApplicationSupportsMultipleScenes: false
@@ -84,8 +92,20 @@ targets:
NSBonjourServices: NSBonjourServices:
- _clawdbot-bridge._tcp - _clawdbot-bridge._tcp
NSCameraUsageDescription: Clawdbot can capture photos or short video clips when requested via the bridge. NSCameraUsageDescription: Clawdbot can capture photos or short video clips when requested via the bridge.
NSLocationWhenInUseUsageDescription: Clawdbot uses your location when you allow location sharing.
NSLocationAlwaysAndWhenInUseUsageDescription: Clawdbot can share your location in the background when you enable Always.
NSMicrophoneUsageDescription: Clawdbot needs microphone access for voice wake. NSMicrophoneUsageDescription: Clawdbot needs microphone access for voice wake.
NSSpeechRecognitionUsageDescription: Clawdbot uses on-device speech recognition for voice wake. NSSpeechRecognitionUsageDescription: Clawdbot uses on-device speech recognition for voice wake.
UISupportedInterfaceOrientations:
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad:
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
ClawdbotTests: ClawdbotTests:
type: bundle.unit-test type: bundle.unit-test
@@ -96,13 +116,17 @@ targets:
- target: Clawdbot - target: Clawdbot
- package: Swabble - package: Swabble
product: SwabbleKit product: SwabbleKit
- sdk: AppIntents.framework
settings: settings:
base: base:
PRODUCT_BUNDLE_IDENTIFIER: com.clawdbot.ios.tests PRODUCT_BUNDLE_IDENTIFIER: com.clawdbot.ios.tests
SWIFT_VERSION: "6.0" SWIFT_VERSION: "6.0"
SWIFT_STRICT_CONCURRENCY: complete
TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Clawdbot.app/Clawdbot" TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Clawdbot.app/Clawdbot"
BUNDLE_LOADER: "$(TEST_HOST)" BUNDLE_LOADER: "$(TEST_HOST)"
info: info:
path: Tests/Info.plist path: Tests/Info.plist
properties: properties:
CFBundleDisplayName: ClawdbotTests CFBundleDisplayName: ClawdbotTests
CFBundleShortVersionString: "2026.1.9"
CFBundleVersion: "20260109"