diff --git a/apps/ios/.periphery.yml b/apps/ios/.periphery.yml index e9156a8170cb..d8aca1812330 100644 --- a/apps/ios/.periphery.yml +++ b/apps/ios/.periphery.yml @@ -12,7 +12,7 @@ report_include: - Sources/** - ShareExtension/** - ActivityWidget/** - - WatchExtension/Sources/** + - WatchApp/Sources/** build_arguments: - -destination - generic/platform=iOS Simulator diff --git a/apps/ios/Config/AppStoreSigning.json b/apps/ios/Config/AppStoreSigning.json index 00e1bf920dee..a884f95a6ee4 100644 --- a/apps/ios/Config/AppStoreSigning.json +++ b/apps/ios/Config/AppStoreSigning.json @@ -39,15 +39,6 @@ "profileKey": "OPENCLAW_WATCH_APP_PROFILE", "profileName": "OpenClaw App Store ai.openclawfoundation.app.watchkitapp", "capabilities": [] - }, - { - "target": "OpenClawWatchExtension", - "displayName": "OpenClaw Watch Extension", - "bundleId": "ai.openclawfoundation.app.watchkitapp.extension", - "platform": "IOS", - "profileKey": "OPENCLAW_WATCH_EXTENSION_PROFILE", - "profileName": "OpenClaw App Store ai.openclawfoundation.app.watchkitapp.extension", - "capabilities": [] } ] } diff --git a/apps/ios/Config/Signing.xcconfig b/apps/ios/Config/Signing.xcconfig index ae945ffe9599..b515822f1d9e 100644 --- a/apps/ios/Config/Signing.xcconfig +++ b/apps/ios/Config/Signing.xcconfig @@ -8,11 +8,9 @@ OPENCLAW_CODE_SIGN_STYLE = Automatic OPENCLAW_CODE_SIGN_IDENTITY = Apple Development OPENCLAW_APP_BUNDLE_ID = ai.openclawfoundation.app OPENCLAW_WATCH_APP_BUNDLE_ID = ai.openclawfoundation.app.watchkitapp -OPENCLAW_WATCH_EXTENSION_BUNDLE_ID = ai.openclawfoundation.app.watchkitapp.extension OPENCLAW_ACTIVITY_WIDGET_BUNDLE_ID = ai.openclawfoundation.app.activitywidget OPENCLAW_ACTIVITY_WIDGET_PROFILE = OPENCLAW_WATCH_APP_PROFILE = -OPENCLAW_WATCH_EXTENSION_PROFILE = // Local contributors can override this by running scripts/ios-configure-signing.sh. // Keep include after defaults: xcconfig is evaluated top-to-bottom. diff --git a/apps/ios/LocalSigning.xcconfig.example b/apps/ios/LocalSigning.xcconfig.example index 1eb12be9fc4c..e7db6c2e52a2 100644 --- a/apps/ios/LocalSigning.xcconfig.example +++ b/apps/ios/LocalSigning.xcconfig.example @@ -9,11 +9,9 @@ OPENCLAW_APP_BUNDLE_ID = ai.openclawfoundation.app OPENCLAW_SHARE_BUNDLE_ID = ai.openclawfoundation.app.share OPENCLAW_ACTIVITY_WIDGET_BUNDLE_ID = ai.openclawfoundation.app.activitywidget OPENCLAW_WATCH_APP_BUNDLE_ID = ai.openclawfoundation.app.watchkitapp -OPENCLAW_WATCH_EXTENSION_BUNDLE_ID = ai.openclawfoundation.app.watchkitapp.extension // Leave empty with automatic signing. OPENCLAW_APP_PROFILE = OPENCLAW_SHARE_PROFILE = OPENCLAW_ACTIVITY_WIDGET_PROFILE = OPENCLAW_WATCH_APP_PROFILE = -OPENCLAW_WATCH_EXTENSION_PROFILE = diff --git a/apps/ios/README.md b/apps/ios/README.md index 1f187bfc5d51..148309559788 100644 --- a/apps/ios/README.md +++ b/apps/ios/README.md @@ -155,7 +155,6 @@ This should create `apps/ios/fastlane/.env` with non-secret App Store Connect va - `ai.openclawfoundation.app.share` - `ai.openclawfoundation.app.activitywidget` - `ai.openclawfoundation.app.watchkitapp` - - `ai.openclawfoundation.app.watchkitapp.extension` Use `pnpm ios:release:signing:setup` for the initial portal setup, then `MATCH_PASSWORD=... pnpm ios:release:signing:sync:push` to publish encrypted Fastlane match assets to the shared private repo. diff --git a/apps/ios/Signing.xcconfig b/apps/ios/Signing.xcconfig index 7079f35f765e..d98da9d40174 100644 --- a/apps/ios/Signing.xcconfig +++ b/apps/ios/Signing.xcconfig @@ -11,7 +11,6 @@ OPENCLAW_DEVELOPMENT_TEAM = FWJYW4S8P8 OPENCLAW_APP_BUNDLE_ID = ai.openclawfoundation.app OPENCLAW_SHARE_BUNDLE_ID = ai.openclawfoundation.app.share OPENCLAW_WATCH_APP_BUNDLE_ID = ai.openclawfoundation.app.watchkitapp -OPENCLAW_WATCH_EXTENSION_BUNDLE_ID = ai.openclawfoundation.app.watchkitapp.extension OPENCLAW_ACTIVITY_WIDGET_BUNDLE_ID = ai.openclawfoundation.app.activitywidget OPENCLAW_APNS_ENTITLEMENT_ENVIRONMENT = development @@ -19,7 +18,6 @@ OPENCLAW_APP_PROFILE = ai.openclawfoundation.app Development OPENCLAW_SHARE_PROFILE = ai.openclawfoundation.app.share Development OPENCLAW_ACTIVITY_WIDGET_PROFILE = OPENCLAW_WATCH_APP_PROFILE = -OPENCLAW_WATCH_EXTENSION_PROFILE = // Keep local includes after defaults: xcconfig is evaluated top-to-bottom, // so later assignments in local files override the defaults above. diff --git a/apps/ios/SwiftSources.input.xcfilelist b/apps/ios/SwiftSources.input.xcfilelist index bcf39f7ad0bf..967286e17f62 100644 --- a/apps/ios/SwiftSources.input.xcfilelist +++ b/apps/ios/SwiftSources.input.xcfilelist @@ -109,10 +109,10 @@ Sources/Voice/VoiceWakePreferences.swift ShareExtension/ShareViewController.swift ActivityWidget/OpenClawActivityWidgetBundle.swift ActivityWidget/OpenClawLiveActivity.swift -WatchExtension/Sources/OpenClawWatchApp.swift -WatchExtension/Sources/WatchConnectivityReceiver.swift -WatchExtension/Sources/WatchInboxStore.swift -WatchExtension/Sources/WatchInboxView.swift +WatchApp/Sources/OpenClawWatchApp.swift +WatchApp/Sources/WatchConnectivityReceiver.swift +WatchApp/Sources/WatchInboxStore.swift +WatchApp/Sources/WatchInboxView.swift ../shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift ../shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownRenderer.swift ../shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownPreprocessor.swift diff --git a/apps/ios/WatchExtension/Assets.xcassets/OpenClawIcon.imageset/Contents.json b/apps/ios/WatchApp/Assets.xcassets/OpenClawIcon.imageset/Contents.json similarity index 100% rename from apps/ios/WatchExtension/Assets.xcassets/OpenClawIcon.imageset/Contents.json rename to apps/ios/WatchApp/Assets.xcassets/OpenClawIcon.imageset/Contents.json diff --git a/apps/ios/WatchExtension/Assets.xcassets/OpenClawIcon.imageset/openclaw-icon.png b/apps/ios/WatchApp/Assets.xcassets/OpenClawIcon.imageset/openclaw-icon.png similarity index 100% rename from apps/ios/WatchExtension/Assets.xcassets/OpenClawIcon.imageset/openclaw-icon.png rename to apps/ios/WatchApp/Assets.xcassets/OpenClawIcon.imageset/openclaw-icon.png diff --git a/apps/ios/WatchApp/Info.plist b/apps/ios/WatchApp/Info.plist index 3eea1e6ff090..13de3b357019 100644 --- a/apps/ios/WatchApp/Info.plist +++ b/apps/ios/WatchApp/Info.plist @@ -20,9 +20,9 @@ $(OPENCLAW_MARKETING_VERSION) CFBundleVersion $(OPENCLAW_BUILD_VERSION) + WKApplication + WKCompanionAppBundleIdentifier $(OPENCLAW_APP_BUNDLE_ID) - WKWatchKitApp - diff --git a/apps/ios/WatchExtension/Sources/OpenClawWatchApp.swift b/apps/ios/WatchApp/Sources/OpenClawWatchApp.swift similarity index 100% rename from apps/ios/WatchExtension/Sources/OpenClawWatchApp.swift rename to apps/ios/WatchApp/Sources/OpenClawWatchApp.swift diff --git a/apps/ios/WatchExtension/Sources/WatchConnectivityReceiver.swift b/apps/ios/WatchApp/Sources/WatchConnectivityReceiver.swift similarity index 100% rename from apps/ios/WatchExtension/Sources/WatchConnectivityReceiver.swift rename to apps/ios/WatchApp/Sources/WatchConnectivityReceiver.swift diff --git a/apps/ios/WatchExtension/Sources/WatchInboxStore.swift b/apps/ios/WatchApp/Sources/WatchInboxStore.swift similarity index 100% rename from apps/ios/WatchExtension/Sources/WatchInboxStore.swift rename to apps/ios/WatchApp/Sources/WatchInboxStore.swift diff --git a/apps/ios/WatchExtension/Sources/WatchInboxView.swift b/apps/ios/WatchApp/Sources/WatchInboxView.swift similarity index 100% rename from apps/ios/WatchExtension/Sources/WatchInboxView.swift rename to apps/ios/WatchApp/Sources/WatchInboxView.swift diff --git a/apps/ios/WatchExtension/Assets.xcassets/Contents.json b/apps/ios/WatchExtension/Assets.xcassets/Contents.json deleted file mode 100644 index 74d6a722cf39..000000000000 --- a/apps/ios/WatchExtension/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info": { - "author": "xcode", - "version": 1 - } -} diff --git a/apps/ios/WatchExtension/Info.plist b/apps/ios/WatchExtension/Info.plist deleted file mode 100644 index 873130649456..000000000000 --- a/apps/ios/WatchExtension/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - OpenClaw - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundleShortVersionString - $(OPENCLAW_MARKETING_VERSION) - CFBundleVersion - $(OPENCLAW_BUILD_VERSION) - NSExtension - - NSExtensionAttributes - - WKAppBundleIdentifier - $(OPENCLAW_WATCH_APP_BUNDLE_ID) - - NSExtensionPointIdentifier - com.apple.watchkit - - - diff --git a/apps/ios/fastlane/Fastfile b/apps/ios/fastlane/Fastfile index 7a6941eecfc3..40024a9032c7 100644 --- a/apps/ios/fastlane/Fastfile +++ b/apps/ios/fastlane/Fastfile @@ -293,6 +293,8 @@ def capture_watch_screenshot Dir[File.join(output_dir, "Apple Watch*-*.png")].each { |path| FileUtils.rm_f(path) } FileUtils.rm_rf(derived_data_path) + # Single-target watch apps only expose generic simulator build destinations in Xcode. + # Keep the selected UDID for install/launch/screenshot below. sh( xcodebuild_shell_join([ "xcodebuild", @@ -303,7 +305,7 @@ def capture_watch_screenshot "-configuration", "Debug", "-destination", - "platform=watchOS Simulator,id=#{udid}", + "generic/platform=watchOS Simulator", "-derivedDataPath", derived_data_path, "build", @@ -311,10 +313,8 @@ def capture_watch_screenshot ) UI.user_error!("Watch screenshot build did not produce #{app_path}.") unless File.exist?(app_path) - extension_path = File.join(app_path, "PlugIns", "OpenClawWatchExtension.appex") watch_app_identifier = bundle_identifier_for_product(app_path) - watch_extension_identifier = bundle_identifier_for_product(extension_path) - screenshot_mode_bundle_identifiers = [watch_app_identifier, watch_extension_identifier] + screenshot_mode_bundle_identifiers = [watch_app_identifier] sh("#{shell_join(["xcrun", "simctl", "boot", udid])} >/dev/null 2>&1 || true") sh(shell_join(["xcrun", "simctl", "bootstatus", udid, "-b"])) diff --git a/apps/ios/project.yml b/apps/ios/project.yml index f3bfc0f6a223..75584d9fea4e 100644 --- a/apps/ios/project.yml +++ b/apps/ios/project.yml @@ -88,7 +88,7 @@ targets: exit 1 fi swiftformat --lint --config "$SRCROOT/../../config/swiftformat" \ - --unexclude "$SRCROOT/Sources,$SRCROOT/ShareExtension,$SRCROOT/ActivityWidget,$SRCROOT/WatchExtension,$SRCROOT/../shared/OpenClawKit,$SRCROOT/../swabble" \ + --unexclude "$SRCROOT/Sources,$SRCROOT/ShareExtension,$SRCROOT/ActivityWidget,$SRCROOT/WatchApp,$SRCROOT/../shared/OpenClawKit,$SRCROOT/../swabble" \ --filelist "$SRCROOT/SwiftSources.input.xcfilelist" - name: SwiftLint basedOnDependencyAnalysis: false @@ -251,13 +251,17 @@ targets: NSExtensionPointIdentifier: com.apple.widgetkit-extension OpenClawWatchApp: - type: application.watchapp2 + type: application platform: watchOS deploymentTarget: "11.0" sources: - path: WatchApp + excludes: + - Info.plist dependencies: - - target: OpenClawWatchExtension + - sdk: AppIntents.framework + - sdk: WatchConnectivity.framework + - sdk: UserNotifications.framework configFiles: Debug: Config/Signing.xcconfig Release: Config/Signing.xcconfig @@ -274,6 +278,12 @@ targets: ENABLE_APP_INTENTS_METADATA_GENERATION: NO PRODUCT_BUNDLE_IDENTIFIER: "$(OPENCLAW_WATCH_APP_BUNDLE_ID)" PROVISIONING_PROFILE_SPECIFIER: "$(OPENCLAW_WATCH_APP_PROFILE)" + SWIFT_STRICT_CONCURRENCY: complete + SWIFT_VERSION: "6.0" + configs: + Debug: + ARCHS: "$(NATIVE_ARCH_ACTUAL)" + ONLY_ACTIVE_ARCH: YES info: path: WatchApp/Info.plist properties: @@ -281,42 +291,7 @@ targets: CFBundleShortVersionString: "$(OPENCLAW_MARKETING_VERSION)" CFBundleVersion: "$(OPENCLAW_BUILD_VERSION)" WKCompanionAppBundleIdentifier: "$(OPENCLAW_APP_BUNDLE_ID)" - WKWatchKitApp: true - - OpenClawWatchExtension: - type: watchkit2-extension - platform: watchOS - deploymentTarget: "11.0" - sources: - - path: WatchExtension/Sources - - path: WatchExtension/Assets.xcassets - dependencies: - - sdk: AppIntents.framework - - sdk: WatchConnectivity.framework - - sdk: UserNotifications.framework - configFiles: - Debug: Config/Signing.xcconfig - Release: Config/Signing.xcconfig - attributes: - DevelopmentTeam: "$(OPENCLAW_DEVELOPMENT_TEAM)" - ProvisioningStyle: "$(OPENCLAW_CODE_SIGN_STYLE)" - settings: - base: - CODE_SIGN_IDENTITY: "$(OPENCLAW_CODE_SIGN_IDENTITY)" - CODE_SIGN_STYLE: "$(OPENCLAW_CODE_SIGN_STYLE)" - DEVELOPMENT_TEAM: "$(OPENCLAW_DEVELOPMENT_TEAM)" - PRODUCT_BUNDLE_IDENTIFIER: "$(OPENCLAW_WATCH_EXTENSION_BUNDLE_ID)" - PROVISIONING_PROFILE_SPECIFIER: "$(OPENCLAW_WATCH_EXTENSION_PROFILE)" - info: - path: WatchExtension/Info.plist - properties: - CFBundleDisplayName: OpenClaw - CFBundleShortVersionString: "$(OPENCLAW_MARKETING_VERSION)" - CFBundleVersion: "$(OPENCLAW_BUILD_VERSION)" - NSExtension: - NSExtensionAttributes: - WKAppBundleIdentifier: "$(OPENCLAW_WATCH_APP_BUNDLE_ID)" - NSExtensionPointIdentifier: com.apple.watchkit + WKApplication: true OpenClawTests: type: bundle.unit-test diff --git a/scripts/ios-configure-signing.sh b/scripts/ios-configure-signing.sh index 0ee4e5cd5b74..b5dd1e2b33ef 100755 --- a/scripts/ios-configure-signing.sh +++ b/scripts/ios-configure-signing.sh @@ -70,7 +70,6 @@ bundle_base="$(normalize_bundle_id "${bundle_base}")" share_bundle_id="${OPENCLAW_IOS_SHARE_BUNDLE_ID:-${bundle_base}.share}" activity_widget_bundle_id="${OPENCLAW_IOS_ACTIVITY_WIDGET_BUNDLE_ID:-${bundle_base}.activitywidget}" watch_app_bundle_id="${OPENCLAW_IOS_WATCH_APP_BUNDLE_ID:-${bundle_base}.watchkitapp}" -watch_extension_bundle_id="${OPENCLAW_IOS_WATCH_EXTENSION_BUNDLE_ID:-${watch_app_bundle_id}.extension}" code_sign_style="${OPENCLAW_IOS_CODE_SIGN_STYLE:-Automatic}" code_sign_identity="${OPENCLAW_IOS_CODE_SIGN_IDENTITY:-Apple Development}" @@ -79,7 +78,6 @@ app_profile="${OPENCLAW_IOS_APP_PROFILE:-}" share_profile="${OPENCLAW_IOS_SHARE_PROFILE:-}" activity_widget_profile="${OPENCLAW_IOS_ACTIVITY_WIDGET_PROFILE:-}" watch_app_profile="${OPENCLAW_IOS_WATCH_APP_PROFILE:-}" -watch_extension_profile="${OPENCLAW_IOS_WATCH_EXTENSION_PROFILE:-}" tmp_file="$(mktemp "${TMPDIR:-/tmp}/openclaw-ios-configure-signing.XXXXXX")" cat >"${tmp_file}" <"${tmp_file}" < { expect(output).toContain( "OPENCLAW_WATCH_APP_PROFILE = OpenClaw App Store ai.openclawfoundation.app.watchkitapp", ); - expect(output).toContain( - "OPENCLAW_WATCH_EXTENSION_PROFILE = OpenClaw App Store ai.openclawfoundation.app.watchkitapp.extension", - ); + expect(output).not.toContain("OPENCLAW_WATCH_EXTENSION_PROFILE"); }); it("documents the canonical release signing plan", () => { @@ -40,9 +38,7 @@ describe("scripts/ios-release-signing.mjs", () => { expect(output).toContain("Signing repo: git@github.com:openclaw/apps-signing.git"); expect(output).toContain("Signing branch: main"); expect(output).toContain("Signing setup and sync: Fastlane match"); - expect(output).toContain( - "OpenClawWatchExtension: ai.openclawfoundation.app.watchkitapp.extension", - ); + expect(output).not.toContain("OpenClawWatchExtension"); expect(output).toContain("capabilities: PUSH_NOTIFICATIONS"); }); });