Skip to content

Commit 6bd84f4

Browse files
fix(ios): generate complete Watch companion
1 parent 611be12 commit 6bd84f4

5 files changed

Lines changed: 83 additions & 6 deletions

File tree

packages/ios/src/index.test.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,24 +229,37 @@ describe('Craft iOS builder', () => {
229229

230230
const project = readFileSync(join(output, 'project.yml'), 'utf8')
231231
const swift = readFileSync(join(output, 'Sources', 'WildLoopApp.swift'), 'utf8')
232-
const watch = readFileSync(join(output, 'WatchApp', 'WildLoopWatchApp.swift'), 'utf8')
232+
const watch = readFileSync(join(output, 'WatchExtension', 'WildLoopWatchApp.swift'), 'utf8')
233233
const watchInfo = readFileSync(join(output, 'WatchApp', 'Info.plist'), 'utf8')
234+
const watchExtensionInfo = readFileSync(join(output, 'WatchExtension', 'Info.plist'), 'utf8')
234235
expect(project).toContain('WildLoopWatch:')
235-
expect(project).toContain('type: application')
236+
expect(project).toContain('type: application.watchapp2')
237+
expect(project).toContain('WildLoopWatchExtension:')
238+
expect(project).toContain('type: watchkit2-extension')
239+
expect(project).toContain('target: WildLoopWatchExtension')
236240
expect(project).toContain('platform: watchOS')
237241
expect(project).toContain('embed: true')
238242
expect(project).toContain('TARGETED_DEVICE_FAMILY: "1"')
239243
expect(swift).toContain('setupWatchConnectivity()')
240244
expect(watch).toContain('recording-control')
241245
expect(watch).toContain('WCSessionDelegate')
246+
expect(watch).toContain('sessionDidBecomeInactive')
247+
expect(watch).toContain('sessionDidDeactivate')
248+
expect(watch).toContain('session.activate()')
242249
expect(watchInfo).toContain('<key>CFBundleIdentifier</key>')
243250
expect(watchInfo).toContain('<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>')
244251
expect(watchInfo).toContain('<key>CFBundleExecutable</key>')
245252
expect(watchInfo).toContain('<key>CFBundleShortVersionString</key>')
246253
expect(watchInfo).toContain('<string>org.wildloop.app</string>')
247-
expect(watchInfo).not.toContain('<key>WKWatchKitApp</key>')
254+
expect(watchInfo).toContain('<key>WKWatchKitApp</key>')
255+
expect(watchInfo).toContain('<true/>')
256+
expect(watchExtensionInfo).toContain('<string>com.apple.watchkit</string>')
257+
expect(watchExtensionInfo).toContain('<string>org.wildloop.app.watchkitapp</string>')
248258
expect(existsSync(join(output, 'WatchApp', 'Info.plist'))).toBe(true)
249259
expect(existsSync(join(output, 'WatchApp', 'Watch.entitlements'))).toBe(true)
260+
expect(existsSync(join(output, 'WatchApp', 'WildLoopWatchApp.swift'))).toBe(false)
261+
expect(existsSync(join(output, 'WatchExtension', 'WildLoopWatchApp.swift'))).toBe(true)
262+
expect(existsSync(join(output, 'WatchExtension', 'Watch.entitlements'))).toBe(true)
250263
})
251264
})
252265

packages/ios/src/index.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ export async function init(options: InitOptions): Promise<void> {
525525

526526
// Create directory structure
527527
const dirs = [output, join(output, 'Sources'), join(output, 'Shared'), join(output, 'dist')]
528-
if (options.config?.enableWatchApp) dirs.push(join(output, 'WatchApp'))
528+
if (options.config?.enableWatchApp) dirs.push(join(output, 'WatchApp'), join(output, 'WatchExtension'))
529529
for (const dir of dirs) {
530530
if (!existsSync(dir)) {
531531
mkdirSync(dir, { recursive: true })
@@ -596,7 +596,7 @@ export async function init(options: InitOptions): Promise<void> {
596596
}
597597
if (config.enableWatchApp) {
598598
nativeTargets.push(` ${name}Watch:
599-
type: application
599+
type: application.watchapp2
600600
platform: watchOS
601601
deploymentTarget: "${config.watchosVersion || '9.0'}"
602602
sources:
@@ -606,6 +606,21 @@ export async function init(options: InitOptions): Promise<void> {
606606
CODE_SIGN_ENTITLEMENTS: WatchApp/Watch.entitlements
607607
PRODUCT_BUNDLE_IDENTIFIER: ${finalBundleId}.watchkitapp
608608
SWIFT_VERSION: "5.0"
609+
SKIP_INSTALL: YES
610+
dependencies:
611+
- target: ${name}WatchExtension
612+
${name}WatchExtension:
613+
type: watchkit2-extension
614+
platform: watchOS
615+
deploymentTarget: "${config.watchosVersion || '9.0'}"
616+
sources:
617+
- WatchExtension
618+
settings:
619+
INFOPLIST_FILE: WatchExtension/Info.plist
620+
CODE_SIGN_ENTITLEMENTS: WatchExtension/Watch.entitlements
621+
PRODUCT_BUNDLE_IDENTIFIER: ${finalBundleId}.watchkitapp.watchkitextension
622+
SWIFT_VERSION: "5.0"
623+
APPLICATION_EXTENSION_API_ONLY: YES
609624
SKIP_INSTALL: YES`)
610625
}
611626

@@ -653,12 +668,17 @@ export async function init(options: InitOptions): Promise<void> {
653668
if (config.enableWatchApp) {
654669
const watchSource = readFileSync(join(TEMPLATES_DIR, 'CraftWatchApp.swift.template'), 'utf8')
655670
.replace(/\{\{APP_NAME\}\}/g, name)
656-
writeFileSync(join(output, 'WatchApp', `${name}WatchApp.swift`), watchSource)
671+
writeFileSync(join(output, 'WatchExtension', `${name}WatchApp.swift`), watchSource)
657672
const watchInfo = readFileSync(join(TEMPLATES_DIR, 'WatchApp.Info.plist.template'), 'utf8')
658673
.replace(/\{\{APP_NAME\}\}/g, name)
659674
.replace(/\{\{BUNDLE_ID\}\}/g, finalBundleId)
660675
writeFileSync(join(output, 'WatchApp', 'Info.plist'), watchInfo)
661676
writeFileSync(join(output, 'WatchApp', 'Watch.entitlements'), renderWatchEntitlements(config))
677+
const watchExtensionInfo = readFileSync(join(TEMPLATES_DIR, 'WatchExtension.Info.plist.template'), 'utf8')
678+
.replace(/\{\{APP_NAME\}\}/g, name)
679+
.replace(/\{\{BUNDLE_ID\}\}/g, finalBundleId)
680+
writeFileSync(join(output, 'WatchExtension', 'Info.plist'), watchExtensionInfo)
681+
writeFileSync(join(output, 'WatchExtension', 'Watch.entitlements'), renderWatchEntitlements(config))
662682
}
663683

664684
// Create placeholder index.html

packages/ios/templates/CraftWatchApp.swift.template

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ extension CraftWatchSession: WCSessionDelegate {
102102
nonisolated func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any] = [:]) {
103103
Task { @MainActor in apply(userInfo) }
104104
}
105+
106+
#if os(iOS)
107+
nonisolated func sessionDidBecomeInactive(_ session: WCSession) {}
108+
109+
nonisolated func sessionDidDeactivate(_ session: WCSession) {
110+
session.activate()
111+
}
112+
#endif
105113
}
106114

107115
struct CraftWatchRecordingView: View {

packages/ios/templates/WatchApp.Info.plist.template

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@
2222
<string>$(CURRENT_PROJECT_VERSION)</string>
2323
<key>WKCompanionAppBundleIdentifier</key>
2424
<string>{{BUNDLE_ID}}</string>
25+
<key>WKWatchKitApp</key>
26+
<true/>
2527
</dict>
2628
</plist>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>$(DEVELOPMENT_LANGUAGE)</string>
7+
<key>CFBundleDisplayName</key>
8+
<string>{{APP_NAME}}</string>
9+
<key>CFBundleExecutable</key>
10+
<string>$(EXECUTABLE_NAME)</string>
11+
<key>CFBundleIdentifier</key>
12+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13+
<key>CFBundleInfoDictionaryVersion</key>
14+
<string>6.0</string>
15+
<key>CFBundleName</key>
16+
<string>$(PRODUCT_NAME)</string>
17+
<key>CFBundlePackageType</key>
18+
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
19+
<key>CFBundleShortVersionString</key>
20+
<string>$(MARKETING_VERSION)</string>
21+
<key>CFBundleVersion</key>
22+
<string>$(CURRENT_PROJECT_VERSION)</string>
23+
<key>NSExtension</key>
24+
<dict>
25+
<key>NSExtensionAttributes</key>
26+
<dict>
27+
<key>WKAppBundleIdentifier</key>
28+
<string>{{BUNDLE_ID}}.watchkitapp</string>
29+
</dict>
30+
<key>NSExtensionPointIdentifier</key>
31+
<string>com.apple.watchkit</string>
32+
</dict>
33+
</dict>
34+
</plist>

0 commit comments

Comments
 (0)