expo-invoke 1.3.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/expo/modules/invoke/InteractiveWidgetReceiver.kt +47 -0
- package/android/src/main/java/expo/modules/invoke/InvokeSliceProvider.kt +83 -0
- package/android/src/main/java/expo/modules/invoke/ShortcutsHelper.kt +38 -32
- package/build/plugin/android/withAndroidInvoke.d.ts +3 -1
- package/build/plugin/android/withAndroidInvoke.js +71 -15
- package/build/plugin/android/withAndroidInvoke.js.map +1 -1
- package/build/plugin/codegen/generateSwiftAppClip.d.ts +2 -0
- package/build/plugin/codegen/generateSwiftAppClip.js +20 -0
- package/build/plugin/codegen/generateSwiftAppClip.js.map +1 -0
- package/build/plugin/codegen/generateSwiftEntities.d.ts +2 -0
- package/build/plugin/codegen/generateSwiftEntities.js +91 -0
- package/build/plugin/codegen/generateSwiftEntities.js.map +1 -0
- package/build/plugin/codegen/generateSwiftFocusFilters.d.ts +2 -0
- package/build/plugin/codegen/generateSwiftFocusFilters.js +42 -0
- package/build/plugin/codegen/generateSwiftFocusFilters.js.map +1 -0
- package/build/plugin/codegen/generateSwiftIntents.d.ts +2 -0
- package/build/plugin/codegen/generateSwiftIntents.js +43 -13
- package/build/plugin/codegen/generateSwiftIntents.js.map +1 -1
- package/build/plugin/codegen/generateSwiftWidget.d.ts +35 -0
- package/build/plugin/codegen/generateSwiftWidget.js +379 -0
- package/build/plugin/codegen/generateSwiftWidget.js.map +1 -0
- package/build/plugin/ios/withIOSInvoke.d.ts +25 -1
- package/build/plugin/ios/withIOSInvoke.js +83 -10
- package/build/plugin/ios/withIOSInvoke.js.map +1 -1
- package/build/plugin/ios/withWidgetExtension.d.ts +14 -0
- package/build/plugin/ios/withWidgetExtension.js +185 -0
- package/build/plugin/ios/withWidgetExtension.js.map +1 -0
- package/build/plugin/src/withInvoke.d.ts +45 -3
- package/build/plugin/src/withInvoke.js +30 -4
- package/build/plugin/src/withInvoke.js.map +1 -1
- package/build/src/components/AddToSiriButton.d.ts +1 -1
- package/build/src/components/AddToSiriButton.d.ts.map +1 -1
- package/build/src/components/InvokeDebugger.d.ts +1 -1
- package/build/src/components/InvokeDebugger.d.ts.map +1 -1
- package/build/src/components/ShortcutChip.d.ts +1 -1
- package/build/src/components/ShortcutChip.d.ts.map +1 -1
- package/build/src/hooks/useBackgroundIntent.d.ts +15 -0
- package/build/src/hooks/useBackgroundIntent.d.ts.map +1 -0
- package/build/src/hooks/useBackgroundIntent.js +41 -0
- package/build/src/hooks/useBackgroundIntent.js.map +1 -0
- package/build/src/hooks/useEntityQuery.d.ts +26 -0
- package/build/src/hooks/useEntityQuery.d.ts.map +1 -0
- package/build/src/hooks/useEntityQuery.js +47 -0
- package/build/src/hooks/useEntityQuery.js.map +1 -0
- package/build/src/hooks/useFocusFilter.d.ts +1 -1
- package/build/src/hooks/useFocusFilter.d.ts.map +1 -1
- package/build/src/hooks/useFocusFilter.js.map +1 -1
- package/build/src/hooks/useFocusFilterState.d.ts +28 -0
- package/build/src/hooks/useFocusFilterState.d.ts.map +1 -0
- package/build/src/hooks/useFocusFilterState.js +47 -0
- package/build/src/hooks/useFocusFilterState.js.map +1 -0
- package/build/src/hooks/useInvoke.d.ts.map +1 -1
- package/build/src/hooks/useInvoke.js +3 -0
- package/build/src/hooks/useInvoke.js.map +1 -1
- package/build/src/hooks/useInvokeAnalytics.d.ts +10 -14
- package/build/src/hooks/useInvokeAnalytics.d.ts.map +1 -1
- package/build/src/hooks/useInvokeAnalytics.js +21 -14
- package/build/src/hooks/useInvokeAnalytics.js.map +1 -1
- package/build/src/hooks/useInvokeQueue.d.ts +32 -0
- package/build/src/hooks/useInvokeQueue.d.ts.map +1 -0
- package/build/src/hooks/useInvokeQueue.js +77 -0
- package/build/src/hooks/useInvokeQueue.js.map +1 -0
- package/build/src/hooks/useLiveActivity.d.ts +37 -0
- package/build/src/hooks/useLiveActivity.d.ts.map +1 -0
- package/build/src/hooks/useLiveActivity.js +74 -0
- package/build/src/hooks/useLiveActivity.js.map +1 -0
- package/build/src/hooks/useOTAConfig.d.ts +24 -0
- package/build/src/hooks/useOTAConfig.d.ts.map +1 -0
- package/build/src/hooks/useOTAConfig.js +40 -0
- package/build/src/hooks/useOTAConfig.js.map +1 -0
- package/build/src/hooks/usePushToTalk.d.ts +35 -0
- package/build/src/hooks/usePushToTalk.d.ts.map +1 -0
- package/build/src/hooks/usePushToTalk.js +101 -0
- package/build/src/hooks/usePushToTalk.js.map +1 -0
- package/build/src/hooks/useSlice.d.ts +19 -0
- package/build/src/hooks/useSlice.d.ts.map +1 -0
- package/build/src/hooks/useSlice.js +22 -0
- package/build/src/hooks/useSlice.js.map +1 -0
- package/build/src/index.d.ts +19 -3
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +16 -1
- package/build/src/index.js.map +1 -1
- package/build/src/module.d.ts +18 -3
- package/build/src/module.d.ts.map +1 -1
- package/build/src/module.js +77 -0
- package/build/src/module.js.map +1 -1
- package/build/src/types/index.d.ts +117 -4
- package/build/src/types/index.d.ts.map +1 -1
- package/build/src/utils/analytics.d.ts +1 -7
- package/build/src/utils/analytics.d.ts.map +1 -1
- package/build/src/utils/analytics.js +9 -0
- package/build/src/utils/analytics.js.map +1 -1
- package/build/src/utils/invokeError.d.ts +28 -0
- package/build/src/utils/invokeError.d.ts.map +1 -0
- package/build/src/utils/invokeError.js +57 -0
- package/build/src/utils/invokeError.js.map +1 -0
- package/build/src/utils/otaConfig.d.ts +9 -0
- package/build/src/utils/otaConfig.d.ts.map +1 -0
- package/build/src/utils/otaConfig.js +45 -0
- package/build/src/utils/otaConfig.js.map +1 -0
- package/build/src/utils/persistentAnalytics.d.ts +5 -0
- package/build/src/utils/persistentAnalytics.d.ts.map +1 -0
- package/build/src/utils/persistentAnalytics.js +52 -0
- package/build/src/utils/persistentAnalytics.js.map +1 -0
- package/build/src/utils/validation.d.ts +12 -0
- package/build/src/utils/validation.d.ts.map +1 -1
- package/build/src/utils/validation.js +81 -1
- package/build/src/utils/validation.js.map +1 -1
- package/build/src/web/index.d.ts +39 -0
- package/build/src/web/index.d.ts.map +1 -0
- package/build/src/web/index.js +37 -0
- package/build/src/web/index.js.map +1 -0
- package/build/src/web/module.d.ts +40 -0
- package/build/src/web/module.d.ts.map +1 -0
- package/build/src/web/module.js +46 -0
- package/build/src/web/module.js.map +1 -0
- package/ios/AppClip/AppClipHandler.swift +41 -0
- package/ios/Background/BackgroundIntentBridge.swift +56 -0
- package/ios/Entities/EntityQueryBridge.swift +40 -0
- package/ios/FocusFilter/FocusFilterRegistrar.swift +40 -0
- package/ios/LiveActivity/LiveActivityManager.swift +83 -0
- package/ios/PTT/PTTManager.swift +51 -0
- package/package.json +2 -1
|
@@ -38,18 +38,45 @@ const config_plugins_1 = require("@expo/config-plugins");
|
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
40
|
const generateSwiftIntents_1 = require("../codegen/generateSwiftIntents");
|
|
41
|
+
const generateSwiftEntities_1 = require("../codegen/generateSwiftEntities");
|
|
42
|
+
const generateSwiftFocusFilters_1 = require("../codegen/generateSwiftFocusFilters");
|
|
43
|
+
const generateSwiftAppClip_1 = require("../codegen/generateSwiftAppClip");
|
|
44
|
+
const withWidgetExtension_1 = require("./withWidgetExtension");
|
|
41
45
|
const withIOSInvoke = (config, options) => {
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
const { intents, voiceUsageDescription, appGroupId, entities = [], focusFilters = [], appClips = [], enablePushToTalk = false, pttUsageDescription, enableLiveActivities = false, enableWidget = false, widgetTitle, widgetDescription = 'Quick access from your home screen.', widgetDataKey = 'invokeWidgetData', widgetAccentColor = '#267AD9', widgetDeepLink = '', widgetSizes = ['small', 'medium'], } = options;
|
|
48
|
+
// 1. Info.plist usage descriptions + feature flags
|
|
44
49
|
config = (0, config_plugins_1.withInfoPlist)(config, (cfg) => {
|
|
50
|
+
var _a;
|
|
45
51
|
cfg.modResults.NSSiriUsageDescription =
|
|
46
52
|
voiceUsageDescription !== null && voiceUsageDescription !== void 0 ? voiceUsageDescription : 'This app uses Siri to perform quick actions.';
|
|
47
53
|
cfg.modResults.NSVoiceUsageDescription =
|
|
48
54
|
voiceUsageDescription !== null && voiceUsageDescription !== void 0 ? voiceUsageDescription : 'This app uses voice commands to perform quick actions.';
|
|
55
|
+
if (enablePushToTalk) {
|
|
56
|
+
cfg.modResults.NSPushToTalkUsageDescription =
|
|
57
|
+
pttUsageDescription !== null && pttUsageDescription !== void 0 ? pttUsageDescription : 'This app uses Push to Talk for voice communication.';
|
|
58
|
+
// Add voip background mode
|
|
59
|
+
const modes = (_a = cfg.modResults.UIBackgroundModes) !== null && _a !== void 0 ? _a : [];
|
|
60
|
+
if (!modes.includes('voip')) {
|
|
61
|
+
cfg.modResults.UIBackgroundModes = [...modes, 'voip'];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (enableLiveActivities) {
|
|
65
|
+
cfg.modResults.NSSupportsLiveActivities = true;
|
|
66
|
+
cfg.modResults.NSSupportsLiveActivitiesFrequentUpdates = true;
|
|
67
|
+
}
|
|
68
|
+
if (appClips.length > 0) {
|
|
69
|
+
cfg.modResults.NSAppClip = {
|
|
70
|
+
NSAppClipRequestEphemeralUserNotification: true,
|
|
71
|
+
NSAppClipRequestLocationConfirmation: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (focusFilters.length > 0) {
|
|
75
|
+
cfg.modResults.NSFocusFilterEnabled = true;
|
|
76
|
+
}
|
|
49
77
|
return cfg;
|
|
50
78
|
});
|
|
51
|
-
// 2. App Groups entitlement (
|
|
52
|
-
// plist values are typed as a union — cast the existing array explicitly
|
|
79
|
+
// 2. App Groups entitlement (widget data sharing + App Clips)
|
|
53
80
|
if (appGroupId) {
|
|
54
81
|
config = (0, config_plugins_1.withEntitlementsPlist)(config, (cfg) => {
|
|
55
82
|
var _a;
|
|
@@ -60,23 +87,69 @@ const withIOSInvoke = (config, options) => {
|
|
|
60
87
|
return cfg;
|
|
61
88
|
});
|
|
62
89
|
}
|
|
63
|
-
// 3. Generate
|
|
90
|
+
// 3. Generate Swift files via withDangerousMod
|
|
64
91
|
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
65
92
|
'ios',
|
|
66
93
|
async (cfg) => {
|
|
67
94
|
var _a;
|
|
68
95
|
const appName = (_a = cfg.modRequest.projectName) !== null && _a !== void 0 ? _a : 'app';
|
|
69
96
|
const iosDir = path.join(cfg.modRequest.platformProjectRoot, appName);
|
|
70
|
-
|
|
71
|
-
if (!fs.existsSync(iosDir)) {
|
|
97
|
+
try {
|
|
72
98
|
fs.mkdirSync(iosDir, { recursive: true });
|
|
73
99
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
100
|
+
catch (e) {
|
|
101
|
+
throw new Error(`[expo-invoke] Could not create iOS project directory at "${iosDir}".\n` +
|
|
102
|
+
`Cause: ${e instanceof Error ? e.message : e}\n` +
|
|
103
|
+
`Fix: Ensure the path is writable. Try running \`npx expo prebuild --clean\`.`);
|
|
104
|
+
}
|
|
105
|
+
const writeSwift = (filename, content) => {
|
|
106
|
+
const filePath = path.join(iosDir, filename);
|
|
107
|
+
try {
|
|
108
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
throw new Error(`[expo-invoke] Failed to write ${filename} to "${iosDir}".\n` +
|
|
112
|
+
`Cause: ${e instanceof Error ? e.message : e}\n` +
|
|
113
|
+
`Fix: Ensure the iOS project directory is writable. Run \`npx expo prebuild --clean\`.`);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
// InvokeIntents.swift — AppIntent structs + AppShortcutsProvider
|
|
117
|
+
writeSwift('InvokeIntents.swift', (0, generateSwiftIntents_1.generateSwiftIntents)(intents));
|
|
118
|
+
// InvokeEntities.swift — AppEntity + EntityQuery structs
|
|
119
|
+
const entityCode = (0, generateSwiftEntities_1.generateSwiftEntities)(entities);
|
|
120
|
+
if (entityCode)
|
|
121
|
+
writeSwift('InvokeEntities.swift', entityCode);
|
|
122
|
+
// InvokeFocusFilters.swift — SetFocusFilterIntent structs
|
|
123
|
+
const focusCode = (0, generateSwiftFocusFilters_1.generateSwiftFocusFilters)(focusFilters);
|
|
124
|
+
if (focusCode)
|
|
125
|
+
writeSwift('InvokeFocusFilters.swift', focusCode);
|
|
126
|
+
// InvokeAppClip.swift — App Clip URL → intent registrations
|
|
127
|
+
const clipCode = (0, generateSwiftAppClip_1.generateSwiftAppClip)(appClips);
|
|
128
|
+
if (clipCode)
|
|
129
|
+
writeSwift('InvokeAppClip.swift', clipCode);
|
|
77
130
|
return cfg;
|
|
78
131
|
},
|
|
79
132
|
]);
|
|
133
|
+
// 4. Widget Extension (opt-in — requires appGroupId)
|
|
134
|
+
if (enableWidget) {
|
|
135
|
+
if (!appGroupId) {
|
|
136
|
+
console.warn('[expo-invoke] enableWidget is true but appGroupId is missing.\n' +
|
|
137
|
+
'Fix: Add appGroupId to your expo-invoke plugin config, e.g. "group.com.myapp.invoke".');
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const bundleIdentifier = ((_b = (_a = config.ios) === null || _a === void 0 ? void 0 : _a.bundleIdentifier) !== null && _b !== void 0 ? _b : 'com.example.app') + '.InvokeWidget';
|
|
141
|
+
config = (0, withWidgetExtension_1.withWidgetExtension)(config, {
|
|
142
|
+
appGroupId,
|
|
143
|
+
bundleId: bundleIdentifier,
|
|
144
|
+
widgetTitle: widgetTitle !== null && widgetTitle !== void 0 ? widgetTitle : ((_c = config.name) !== null && _c !== void 0 ? _c : 'My App'),
|
|
145
|
+
widgetDescription,
|
|
146
|
+
widgetDataKey,
|
|
147
|
+
widgetAccentColor,
|
|
148
|
+
widgetDeepLink,
|
|
149
|
+
widgetSizes,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
80
153
|
return config;
|
|
81
154
|
};
|
|
82
155
|
exports.withIOSInvoke = withIOSInvoke;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withIOSInvoke.js","sourceRoot":"","sources":["../../../plugin/ios/withIOSInvoke.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAK8B;AAC9B,uCAAyB;AACzB,2CAA6B;AAC7B,0EAAuE;
|
|
1
|
+
{"version":3,"file":"withIOSInvoke.js","sourceRoot":"","sources":["../../../plugin/ios/withIOSInvoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
import { type WidgetCodegenOptions } from '../codegen/generateSwiftWidget';
|
|
3
|
+
export interface WidgetExtensionOptions extends WidgetCodegenOptions {
|
|
4
|
+
bundleId: string;
|
|
5
|
+
deploymentTarget?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Adds a WidgetKit extension target to the iOS Xcode project.
|
|
9
|
+
* Called automatically by withIOSInvoke when enableWidget: true.
|
|
10
|
+
*
|
|
11
|
+
* Developers never call this directly — it's wired up through the expo-invoke
|
|
12
|
+
* app.json plugin config.
|
|
13
|
+
*/
|
|
14
|
+
export declare const withWidgetExtension: ConfigPlugin<WidgetExtensionOptions>;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.withWidgetExtension = void 0;
|
|
37
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const generateSwiftWidget_1 = require("../codegen/generateSwiftWidget");
|
|
41
|
+
const WIDGET_TARGET = 'InvokeWidget';
|
|
42
|
+
/**
|
|
43
|
+
* Adds a WidgetKit extension target to the iOS Xcode project.
|
|
44
|
+
* Called automatically by withIOSInvoke when enableWidget: true.
|
|
45
|
+
*
|
|
46
|
+
* Developers never call this directly — it's wired up through the expo-invoke
|
|
47
|
+
* app.json plugin config.
|
|
48
|
+
*/
|
|
49
|
+
const withWidgetExtension = (config, opts) => {
|
|
50
|
+
const { appGroupId, bundleId, deploymentTarget = '16.0' } = opts;
|
|
51
|
+
// 1. Add App Group entitlement to the main app
|
|
52
|
+
config = (0, config_plugins_1.withEntitlementsPlist)(config, (cfg) => {
|
|
53
|
+
var _a;
|
|
54
|
+
const key = 'com.apple.security.application-groups';
|
|
55
|
+
const existing = (_a = cfg.modResults[key]) !== null && _a !== void 0 ? _a : [];
|
|
56
|
+
if (!existing.includes(appGroupId)) {
|
|
57
|
+
cfg.modResults[key] = [...existing, appGroupId];
|
|
58
|
+
}
|
|
59
|
+
return cfg;
|
|
60
|
+
});
|
|
61
|
+
// 2. Generate widget Swift source file + support files into ios/InvokeWidget/
|
|
62
|
+
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
63
|
+
'ios',
|
|
64
|
+
async (cfg) => {
|
|
65
|
+
const widgetDir = path.join(cfg.modRequest.platformProjectRoot, WIDGET_TARGET);
|
|
66
|
+
try {
|
|
67
|
+
fs.mkdirSync(widgetDir, { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
throw new Error(`[expo-invoke] Could not create widget directory at "${widgetDir}".\n` +
|
|
71
|
+
`Cause: ${e instanceof Error ? e.message : e}\n` +
|
|
72
|
+
`Fix: Ensure the iOS project root is writable. Try \`npx expo prebuild --clean\`.`);
|
|
73
|
+
}
|
|
74
|
+
const write = (filename, content) => {
|
|
75
|
+
try {
|
|
76
|
+
fs.writeFileSync(path.join(widgetDir, filename), content, 'utf8');
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
throw new Error(`[expo-invoke] Failed to write widget file "${filename}".\n` +
|
|
80
|
+
`Cause: ${e instanceof Error ? e.message : e}\n` +
|
|
81
|
+
`Fix: Check write permissions on the iOS project directory.`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
write('InvokeWidget.swift', (0, generateSwiftWidget_1.generateSwiftWidget)(opts));
|
|
85
|
+
write('Info.plist', (0, generateSwiftWidget_1.generateWidgetInfoPlist)());
|
|
86
|
+
write(`${WIDGET_TARGET}.entitlements`, (0, generateSwiftWidget_1.generateWidgetEntitlements)(appGroupId));
|
|
87
|
+
console.log(`[expo-invoke] Widget extension files written to ${widgetDir}`);
|
|
88
|
+
return cfg;
|
|
89
|
+
},
|
|
90
|
+
]);
|
|
91
|
+
// 3. Add widget target to the Xcode project
|
|
92
|
+
config = (0, config_plugins_1.withXcodeProject)(config, (cfg) => {
|
|
93
|
+
var _a;
|
|
94
|
+
const proj = cfg.modResults;
|
|
95
|
+
// Idempotency — skip if the target already exists
|
|
96
|
+
const existingTargets = proj.pbxNativeTargetSection();
|
|
97
|
+
const already = Object.values(existingTargets).some((t) => t && typeof t === 'object' && t.name === WIDGET_TARGET);
|
|
98
|
+
if (already) {
|
|
99
|
+
console.log('[expo-invoke] Widget target already in Xcode project, skipping');
|
|
100
|
+
return cfg;
|
|
101
|
+
}
|
|
102
|
+
// ── Add the extension target ─────────────────────────────────────────────
|
|
103
|
+
const widgetTarget = proj.addTarget(WIDGET_TARGET, 'app_extension', WIDGET_TARGET, bundleId);
|
|
104
|
+
if (!widgetTarget) {
|
|
105
|
+
console.error('[expo-invoke] addTarget() returned null — Xcode widget target NOT added');
|
|
106
|
+
return cfg;
|
|
107
|
+
}
|
|
108
|
+
const widgetUuid = widgetTarget.uuid;
|
|
109
|
+
// ── Build phases ─────────────────────────────────────────────────────────
|
|
110
|
+
proj.addBuildPhase(['InvokeWidget.swift'], 'PBXSourcesBuildPhase', 'Sources', widgetUuid);
|
|
111
|
+
proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', widgetUuid);
|
|
112
|
+
// ── Frameworks ───────────────────────────────────────────────────────────
|
|
113
|
+
proj.addFramework('WidgetKit.framework', { target: widgetUuid });
|
|
114
|
+
proj.addFramework('SwiftUI.framework', { target: widgetUuid });
|
|
115
|
+
// ── Build settings ───────────────────────────────────────────────────────
|
|
116
|
+
const configurations = proj.pbxXCBuildConfigurationSection();
|
|
117
|
+
for (const [, cfgObj] of Object.entries(configurations)) {
|
|
118
|
+
const settings = cfgObj === null || cfgObj === void 0 ? void 0 : cfgObj.buildSettings;
|
|
119
|
+
if (!settings)
|
|
120
|
+
continue;
|
|
121
|
+
const prodName = settings.PRODUCT_NAME;
|
|
122
|
+
if (prodName !== `"${WIDGET_TARGET}"` && prodName !== WIDGET_TARGET)
|
|
123
|
+
continue;
|
|
124
|
+
settings.PRODUCT_BUNDLE_IDENTIFIER = `"${bundleId}"`;
|
|
125
|
+
settings.SWIFT_VERSION = '5.0';
|
|
126
|
+
settings.IPHONEOS_DEPLOYMENT_TARGET = deploymentTarget;
|
|
127
|
+
settings.INFOPLIST_FILE = `"${WIDGET_TARGET}/Info.plist"`;
|
|
128
|
+
settings.CODE_SIGN_ENTITLEMENTS = `"${WIDGET_TARGET}/${WIDGET_TARGET}.entitlements"`;
|
|
129
|
+
settings.SKIP_INSTALL = 'YES';
|
|
130
|
+
settings.TARGETED_DEVICE_FAMILY = '"1,2"';
|
|
131
|
+
settings.LD_RUNPATH_SEARCH_PATHS = '"$(inherited) @executable_path/../../Frameworks"';
|
|
132
|
+
settings.ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = 'NO';
|
|
133
|
+
}
|
|
134
|
+
// ── Embed widget in main app (Embed App Extensions phase) ────────────────
|
|
135
|
+
const mainTarget = proj.getFirstTarget();
|
|
136
|
+
if (mainTarget) {
|
|
137
|
+
const mainUuid = mainTarget.uuid;
|
|
138
|
+
// Add widget as a build dependency (builds first)
|
|
139
|
+
proj.addTargetDependency(mainUuid, [widgetUuid]);
|
|
140
|
+
// Add PBXCopyFilesBuildPhase with dstSubfolderSpec = 13 (PlugIns/Extensions)
|
|
141
|
+
const embedPhase = proj.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Embed App Extensions', mainUuid, 'application');
|
|
142
|
+
// Patch dstSubfolderSpec to 13 (Xcode extension slot)
|
|
143
|
+
if (embedPhase === null || embedPhase === void 0 ? void 0 : embedPhase.uuid) {
|
|
144
|
+
const phases = proj.hash.project.objects['PBXCopyFilesBuildPhase'];
|
|
145
|
+
if (phases === null || phases === void 0 ? void 0 : phases[embedPhase.uuid]) {
|
|
146
|
+
phases[embedPhase.uuid].dstSubfolderSpec = 13;
|
|
147
|
+
phases[embedPhase.uuid].name = '"Embed App Extensions"';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Find the .appex product file reference and add it to the embed phase
|
|
151
|
+
const buildFiles = proj.pbxBuildFileSection();
|
|
152
|
+
for (const [fileKey, fileMeta] of Object.entries(buildFiles)) {
|
|
153
|
+
if (fileKey.endsWith('_comment'))
|
|
154
|
+
continue;
|
|
155
|
+
const meta = fileMeta;
|
|
156
|
+
const comment = (_a = buildFiles[`${fileKey}_comment`]) !== null && _a !== void 0 ? _a : '';
|
|
157
|
+
if (!comment.includes(`${WIDGET_TARGET}.appex`))
|
|
158
|
+
continue;
|
|
159
|
+
// Mark as code-sign-on-copy
|
|
160
|
+
if (!meta.settings) {
|
|
161
|
+
buildFiles[fileKey].settings = {};
|
|
162
|
+
}
|
|
163
|
+
buildFiles[fileKey].settings.ATTRIBUTES = ['CodeSignOnCopy', 'RemoveHeadersOnCopy'];
|
|
164
|
+
// Add to embed phase
|
|
165
|
+
if (embedPhase === null || embedPhase === void 0 ? void 0 : embedPhase.uuid) {
|
|
166
|
+
const phases = proj.hash.project.objects['PBXCopyFilesBuildPhase'];
|
|
167
|
+
if (phases === null || phases === void 0 ? void 0 : phases[embedPhase.uuid]) {
|
|
168
|
+
if (!phases[embedPhase.uuid].files)
|
|
169
|
+
phases[embedPhase.uuid].files = [];
|
|
170
|
+
phases[embedPhase.uuid].files.push({
|
|
171
|
+
value: fileKey,
|
|
172
|
+
comment: `${WIDGET_TARGET}.appex in Embed App Extensions`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
console.log(`[expo-invoke] Widget target "${WIDGET_TARGET}" added to Xcode project ✓`);
|
|
180
|
+
return cfg;
|
|
181
|
+
});
|
|
182
|
+
return config;
|
|
183
|
+
};
|
|
184
|
+
exports.withWidgetExtension = withWidgetExtension;
|
|
185
|
+
//# sourceMappingURL=withWidgetExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withWidgetExtension.js","sourceRoot":"","sources":["../../../plugin/ios/withWidgetExtension.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { IntentDefinition, WidgetDefinition, NotificationCategoryDefinition } from '../../src/types';
|
|
1
|
+
import type { IntentDefinition, WidgetDefinition, NotificationCategoryDefinition, AppEntityDefinition, FocusFilterDefinition, AppClipDefinition, SliceDefinition } from '../../src/types';
|
|
3
2
|
export interface InvokePluginOptions {
|
|
4
3
|
/** Intent definitions. Each intent maps to Siri voice phrases, shortcuts, widget buttons, etc. */
|
|
5
4
|
intents: IntentDefinition[];
|
|
@@ -11,6 +10,49 @@ export interface InvokePluginOptions {
|
|
|
11
10
|
voiceUsageDescription?: string;
|
|
12
11
|
/** iOS App Group identifier for widget data sharing (e.g. "group.com.myapp.invoke") */
|
|
13
12
|
appGroupId?: string;
|
|
13
|
+
/** App Entity definitions for Siri parameter resolution (iOS 16.4+) */
|
|
14
|
+
entities?: AppEntityDefinition[];
|
|
15
|
+
/** Focus filter definitions — register the app as a Focus filter (iOS 16+) */
|
|
16
|
+
focusFilters?: FocusFilterDefinition[];
|
|
17
|
+
/** App Clip definitions (iOS 14+) */
|
|
18
|
+
appClips?: AppClipDefinition[];
|
|
19
|
+
/** Android Slice definitions for Google Search / Assistant inline content */
|
|
20
|
+
slices?: SliceDefinition[];
|
|
21
|
+
/** Enable interactive widget controls that fire without opening the app (iOS 17+ / Android 12+) */
|
|
22
|
+
enableInteractiveWidgets?: boolean;
|
|
23
|
+
/** Enable Push-to-Talk framework integration (iOS 16+) */
|
|
24
|
+
enablePushToTalk?: boolean;
|
|
25
|
+
/** NSPushToTalkUsageDescription — required if enablePushToTalk is true */
|
|
26
|
+
pttUsageDescription?: string;
|
|
27
|
+
/** Set NSSupportsLiveActivities in Info.plist */
|
|
28
|
+
enableLiveActivities?: boolean;
|
|
29
|
+
/** ActivityAttributes class names your app defines (for documentation / validation) */
|
|
30
|
+
liveActivityTypes?: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Add a built-in WidgetKit home screen widget to your app.
|
|
33
|
+
* Requires `appGroupId` to be set. No native code needed — the widget Swift
|
|
34
|
+
* file is generated automatically from your config.
|
|
35
|
+
*
|
|
36
|
+
* The widget reads display data from the shared App Group UserDefaults. Use
|
|
37
|
+
* setWidgetData(key, { count, badgeLabel, title, subtitle, detail }) from your
|
|
38
|
+
* app to populate it.
|
|
39
|
+
*/
|
|
40
|
+
enableWidget?: boolean;
|
|
41
|
+
/** Widget display name shown in the iOS widget picker (defaults to app name) */
|
|
42
|
+
widgetTitle?: string;
|
|
43
|
+
/** Widget description shown in the iOS widget picker */
|
|
44
|
+
widgetDescription?: string;
|
|
45
|
+
/**
|
|
46
|
+
* UserDefaults key the widget reads from.
|
|
47
|
+
* Must match the key you pass to setWidgetData(). Defaults to "invokeWidgetData".
|
|
48
|
+
*/
|
|
49
|
+
widgetDataKey?: string;
|
|
50
|
+
/** Hex accent colour for widget UI (defaults to "#267AD9") */
|
|
51
|
+
widgetAccentColor?: string;
|
|
52
|
+
/** URL scheme deep-link opened when the widget is tapped (e.g. "myapp://home") */
|
|
53
|
+
widgetDeepLink?: string;
|
|
54
|
+
/** Widget sizes to generate. Defaults to ["small", "medium"] */
|
|
55
|
+
widgetSizes?: ('small' | 'medium' | 'large')[];
|
|
14
56
|
}
|
|
15
|
-
declare const _default:
|
|
57
|
+
declare const _default: any;
|
|
16
58
|
export default _default;
|
|
@@ -3,11 +3,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
4
|
const withIOSInvoke_1 = require("../ios/withIOSInvoke");
|
|
5
5
|
const withAndroidInvoke_1 = require("../android/withAndroidInvoke");
|
|
6
|
+
const validation_1 = require("../../src/utils/validation");
|
|
6
7
|
const withInvoke = (config, options) => {
|
|
7
|
-
const { intents = [], widgets, notificationActions, voiceUsageDescription, appGroupId } = options;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const { intents = [], widgets: _widgets, notificationActions, voiceUsageDescription, appGroupId, entities = [], focusFilters = [], appClips = [], slices = [], enableInteractiveWidgets = false, enablePushToTalk = false, pttUsageDescription, enableLiveActivities = false, liveActivityTypes = [], enableWidget = false, widgetTitle, widgetDescription, widgetDataKey, widgetAccentColor, widgetDeepLink, widgetSizes, } = options;
|
|
9
|
+
// Validate options early — throws with a helpful message if misconfigured
|
|
10
|
+
(0, validation_1.validatePluginOptions)({ enablePushToTalk, pttUsageDescription, enableLiveActivities, liveActivityTypes });
|
|
11
|
+
config = (0, withIOSInvoke_1.withIOSInvoke)(config, {
|
|
12
|
+
intents,
|
|
13
|
+
voiceUsageDescription,
|
|
14
|
+
appGroupId,
|
|
15
|
+
entities,
|
|
16
|
+
focusFilters,
|
|
17
|
+
appClips,
|
|
18
|
+
enablePushToTalk,
|
|
19
|
+
pttUsageDescription,
|
|
20
|
+
enableLiveActivities,
|
|
21
|
+
liveActivityTypes,
|
|
22
|
+
enableWidget,
|
|
23
|
+
widgetTitle,
|
|
24
|
+
widgetDescription,
|
|
25
|
+
widgetDataKey,
|
|
26
|
+
widgetAccentColor,
|
|
27
|
+
widgetDeepLink,
|
|
28
|
+
widgetSizes,
|
|
29
|
+
});
|
|
30
|
+
config = (0, withAndroidInvoke_1.withAndroidInvoke)(config, {
|
|
31
|
+
intents,
|
|
32
|
+
notificationActions,
|
|
33
|
+
slices,
|
|
34
|
+
enableInteractiveWidgets,
|
|
35
|
+
});
|
|
10
36
|
return config;
|
|
11
37
|
};
|
|
12
|
-
exports.default = (0, config_plugins_1.createRunOncePlugin)(withInvoke, 'expo-invoke', '
|
|
38
|
+
exports.default = (0, config_plugins_1.createRunOncePlugin)(withInvoke, 'expo-invoke', '2.0.0');
|
|
13
39
|
//# sourceMappingURL=withInvoke.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withInvoke.js","sourceRoot":"","sources":["../../../plugin/src/withInvoke.ts"],"names":[],"mappings":";;AAAA,yDAA8E;AAC9E,wDAAqD;AACrD,oEAAiE;
|
|
1
|
+
{"version":3,"file":"withInvoke.js","sourceRoot":"","sources":["../../../plugin/src/withInvoke.ts"],"names":[],"mappings":";;AAAA,yDAA8E;AAC9E,wDAAqD;AACrD,oEAAiE;AACjE,2DAAmE;AAqEnE,MAAM,UAAU,GAAsC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IACxE,MAAM,EACJ,OAAO,GAAG,EAAE,EACZ,OAAO,EAAE,QAAQ,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,QAAQ,GAAG,EAAE,EACb,YAAY,GAAG,EAAE,EACjB,QAAQ,GAAG,EAAE,EACb,MAAM,GAAG,EAAE,EACX,wBAAwB,GAAG,KAAK,EAChC,gBAAgB,GAAG,KAAK,EACxB,mBAAmB,EACnB,oBAAoB,GAAG,KAAK,EAC5B,iBAAiB,GAAG,EAAE,EACtB,YAAY,GAAG,KAAK,EACpB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,WAAW,GACZ,GAAG,OAAO,CAAC;IAEZ,0EAA0E;IAC1E,IAAA,kCAAqB,EAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAE1G,MAAM,GAAG,IAAA,6BAAa,EAAC,MAAM,EAAE;QAC7B,OAAO;QACP,qBAAqB;QACrB,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,QAAQ;QACR,gBAAgB;QAChB,mBAAmB;QACnB,oBAAoB;QACpB,iBAAiB;QACjB,YAAY;QACZ,WAAW;QACX,iBAAiB;QACjB,aAAa;QACb,iBAAiB;QACjB,cAAc;QACd,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,GAAG,IAAA,qCAAiB,EAAC,MAAM,EAAE;QACjC,OAAO;QACP,mBAAmB;QACnB,MAAM;QACN,wBAAwB;KACzB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,kBAAe,IAAA,oCAAmB,EAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC"}
|
|
@@ -13,6 +13,6 @@ interface AddToSiriButtonProps {
|
|
|
13
13
|
* @example
|
|
14
14
|
* <AddToSiriButton intentId="create_errand" />
|
|
15
15
|
*/
|
|
16
|
-
export declare function AddToSiriButton({ intentId, style, labelStyle, onPress }: AddToSiriButtonProps):
|
|
16
|
+
export declare function AddToSiriButton({ intentId, style, labelStyle, onPress }: AddToSiriButtonProps): import("react").JSX.Element | null;
|
|
17
17
|
export {};
|
|
18
18
|
//# sourceMappingURL=AddToSiriButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddToSiriButton.d.ts","sourceRoot":"","sources":["../../../src/components/AddToSiriButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGhG,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"AddToSiriButton.d.ts","sourceRoot":"","sources":["../../../src/components/AddToSiriButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGhG,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,oBAAoB,sCAkB7F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvokeDebugger.d.ts","sourceRoot":"","sources":["../../../src/components/InvokeDebugger.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wBAAgB,cAAc,
|
|
1
|
+
{"version":3,"file":"InvokeDebugger.d.ts","sourceRoot":"","sources":["../../../src/components/InvokeDebugger.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wBAAgB,cAAc,uCAI7B"}
|
|
@@ -15,6 +15,6 @@ interface ShortcutChipProps {
|
|
|
15
15
|
* @example
|
|
16
16
|
* <ShortcutChip shortcutId="quick_errand" label="Quick Errand" icon="📦" />
|
|
17
17
|
*/
|
|
18
|
-
export declare function ShortcutChip({ shortcutId, label, icon, style, labelStyle, onPress }: ShortcutChipProps):
|
|
18
|
+
export declare function ShortcutChip({ shortcutId, label, icon, style, labelStyle, onPress }: ShortcutChipProps): import("react").JSX.Element;
|
|
19
19
|
export {};
|
|
20
20
|
//# sourceMappingURL=ShortcutChip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShortcutChip.d.ts","sourceRoot":"","sources":["../../../src/components/ShortcutChip.tsx"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGtF,UAAU,iBAAiB;IACzB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,iBAAiB
|
|
1
|
+
{"version":3,"file":"ShortcutChip.d.ts","sourceRoot":"","sources":["../../../src/components/ShortcutChip.tsx"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGtF,UAAU,iBAAiB;IACzB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,iBAAiB,+BAuBtG"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BackgroundIntentResult, ParameterValue } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Register a handler for a background intent — one that runs without opening the app.
|
|
4
|
+
* The intent must have `openAppWhenRun: false` in app.json.
|
|
5
|
+
*
|
|
6
|
+
* iOS 16+ only. On Android, the handler fires normally (app opens first).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* useBackgroundIntent('mark_complete', async ({ errandId }) => {
|
|
10
|
+
* await api.markComplete(errandId as string);
|
|
11
|
+
* return { success: true, spokenResponse: 'Errand marked as complete.' };
|
|
12
|
+
* });
|
|
13
|
+
*/
|
|
14
|
+
export declare function useBackgroundIntent(intentId: string, handler: (parameters: Record<string, ParameterValue>) => Promise<BackgroundIntentResult>): void;
|
|
15
|
+
//# sourceMappingURL=useBackgroundIntent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBackgroundIntent.d.ts","sourceRoot":"","sources":["../../../src/hooks/useBackgroundIntent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEvE;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,OAAO,CAAC,sBAAsB,CAAC,GACvF,IAAI,CAyBN"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { registerBackgroundHandler, reportBackgroundResult, addIntentListener } from '../module';
|
|
3
|
+
/**
|
|
4
|
+
* Register a handler for a background intent — one that runs without opening the app.
|
|
5
|
+
* The intent must have `openAppWhenRun: false` in app.json.
|
|
6
|
+
*
|
|
7
|
+
* iOS 16+ only. On Android, the handler fires normally (app opens first).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* useBackgroundIntent('mark_complete', async ({ errandId }) => {
|
|
11
|
+
* await api.markComplete(errandId as string);
|
|
12
|
+
* return { success: true, spokenResponse: 'Errand marked as complete.' };
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
export function useBackgroundIntent(intentId, handler) {
|
|
16
|
+
const handlerRef = useRef(handler);
|
|
17
|
+
handlerRef.current = handler;
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
registerBackgroundHandler(intentId);
|
|
20
|
+
const sub = addIntentListener(async (intent) => {
|
|
21
|
+
var _a;
|
|
22
|
+
if (intent.intentId !== intentId || intent.source !== 'background')
|
|
23
|
+
return;
|
|
24
|
+
try {
|
|
25
|
+
const result = await handlerRef.current((_a = intent.parameters) !== null && _a !== void 0 ? _a : {});
|
|
26
|
+
reportBackgroundResult(intentId, result);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
reportBackgroundResult(intentId, {
|
|
30
|
+
success: false,
|
|
31
|
+
error: e instanceof Error ? e.message : 'Handler error',
|
|
32
|
+
spokenResponse: 'Sorry, something went wrong.',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return () => sub.remove();
|
|
37
|
+
// intentId is stable — re-register only if it changes
|
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39
|
+
}, [intentId]);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=useBackgroundIntent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBackgroundIntent.js","sourceRoot":"","sources":["../../../src/hooks/useBackgroundIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGjG;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,OAAwF;IAExF,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,yBAAyB,CAAC,QAAQ,CAAC,CAAC;QAEpC,MAAM,GAAG,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;;YAC7C,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY;gBAAE,OAAO;YAC3E,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAA,MAAM,CAAC,UAAU,mCAAI,EAAE,CAAC,CAAC;gBACjE,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,sBAAsB,CAAC,QAAQ,EAAE;oBAC/B,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;oBACvD,cAAc,EAAE,8BAA8B;iBAC/C,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAC5B,sDAAsD;QACtD,uDAAuD;IACvD,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ParameterValue } from '../types';
|
|
2
|
+
import { type InvokeError } from '../utils/invokeError';
|
|
3
|
+
export interface UseEntityQueryOptions {
|
|
4
|
+
/** Called when the handler throws. Receives a structured InvokeError. */
|
|
5
|
+
onError?: (error: InvokeError) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Register a handler that Siri calls when it needs to resolve entity parameters.
|
|
9
|
+
* When the user says "Send my errand to [carrier name]", Siri fires this handler
|
|
10
|
+
* with the entity type and the user's spoken query — your app returns matching results.
|
|
11
|
+
*
|
|
12
|
+
* iOS 16.4+ only. No-op on Android.
|
|
13
|
+
*
|
|
14
|
+
* Errors from your handler are caught — Siri receives an empty result set instead of crashing.
|
|
15
|
+
*
|
|
16
|
+
* @param entityId - Must match an AppEntityDefinition id in app.json
|
|
17
|
+
* @param handler - Called with the user's query string, return matching entity records
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* useEntityQuery('carrier', async (query) => {
|
|
21
|
+
* const carriers = await api.searchCarriers(query);
|
|
22
|
+
* return carriers.map((c) => ({ id: c.id, name: c.name, rating: c.rating }));
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
export declare function useEntityQuery(entityId: string, handler: (query: string) => Promise<Record<string, ParameterValue>[]>, options?: UseEntityQueryOptions): void;
|
|
26
|
+
//# sourceMappingURL=useEntityQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEntityQuery.d.ts","sourceRoot":"","sources":["../../../src/hooks/useEntityQuery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC,EACrE,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAsBN"}
|