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
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.swiftWidgetFamily = swiftWidgetFamily;
|
|
3
4
|
exports.generateSwiftIntents = generateSwiftIntents;
|
|
5
|
+
/** Escape a string for safe embedding inside Swift double-quoted string literals. */
|
|
6
|
+
function escapeSwiftString(s) {
|
|
7
|
+
return s
|
|
8
|
+
.replace(/\\/g, '\\\\')
|
|
9
|
+
.replace(/"/g, '\\"')
|
|
10
|
+
.replace(/\n/g, '\\n')
|
|
11
|
+
.replace(/\r/g, '\\r')
|
|
12
|
+
.replace(/\t/g, '\\t');
|
|
13
|
+
}
|
|
4
14
|
function toPascalCase(id) {
|
|
5
15
|
return id.split(/[_\s-]+/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join('');
|
|
6
16
|
}
|
|
@@ -9,6 +19,7 @@ function toCamelCase(id) {
|
|
|
9
19
|
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
10
20
|
}
|
|
11
21
|
function swiftParamType(param) {
|
|
22
|
+
var _a;
|
|
12
23
|
switch (param.type) {
|
|
13
24
|
case 'text': return 'String';
|
|
14
25
|
case 'number': return 'Double';
|
|
@@ -24,6 +35,7 @@ function swiftParamType(param) {
|
|
|
24
35
|
case 'location': return '[LocationEntity]';
|
|
25
36
|
default: return '[String]';
|
|
26
37
|
}
|
|
38
|
+
case 'entity': return `${toPascalCase((_a = param.entityId) !== null && _a !== void 0 ? _a : 'app')}Entity`;
|
|
27
39
|
default: return 'String';
|
|
28
40
|
}
|
|
29
41
|
}
|
|
@@ -44,6 +56,8 @@ function paramToJSON(param) {
|
|
|
44
56
|
return `if let v = ${name} { params["${name}"] = v }`;
|
|
45
57
|
case 'array':
|
|
46
58
|
return `if let v = ${name} { params["${name}"] = v }`;
|
|
59
|
+
case 'entity':
|
|
60
|
+
return `if let v = ${name} { params["${name}"] = v.toJSON() }`;
|
|
47
61
|
default:
|
|
48
62
|
return `if let v = ${name} { params["${name}"] = v }`;
|
|
49
63
|
}
|
|
@@ -57,7 +71,7 @@ function generateIntentStruct(intent) {
|
|
|
57
71
|
const swiftType = swiftParamType(p);
|
|
58
72
|
const optional = p.optional !== false ? '?' : '';
|
|
59
73
|
const swiftName = toCamelCase(p.name);
|
|
60
|
-
return ` @Parameter(title: "${p.title}")
|
|
74
|
+
return ` @Parameter(title: "${escapeSwiftString(p.title)}")
|
|
61
75
|
var ${swiftName}: ${swiftType}${optional}`;
|
|
62
76
|
}).join('\n\n');
|
|
63
77
|
const paramExtraction = params.map((p) => {
|
|
@@ -67,27 +81,30 @@ function generateIntentStruct(intent) {
|
|
|
67
81
|
}).join('\n');
|
|
68
82
|
const spokenResult = intent.spokenResponse
|
|
69
83
|
? `
|
|
70
|
-
let spoken = "${intent.spokenResponse}"
|
|
84
|
+
let spoken = "${escapeSwiftString(intent.spokenResponse)}"
|
|
71
85
|
return .result(dialog: IntentDialog(full: .init(stringLiteral: spoken)))`
|
|
72
86
|
: `
|
|
73
87
|
return .result()`;
|
|
88
|
+
const backgroundCall = intent.openAppWhenRun === false
|
|
89
|
+
? ` await ExpoInvokeBackgroundBridge.shared.dispatch(intentId: "${escapeSwiftString(intent.id)}", parameters: params)`
|
|
90
|
+
: ` ExpoInvokeModule.writePendingIntent(
|
|
91
|
+
intentId: "${escapeSwiftString(intent.id)}",
|
|
92
|
+
source: "siri",
|
|
93
|
+
parameters: params,
|
|
94
|
+
spokenResponse: ${intent.spokenResponse ? `"${escapeSwiftString(intent.spokenResponse)}"` : 'nil'}
|
|
95
|
+
)`;
|
|
74
96
|
return `@available(iOS 16.0, *)
|
|
75
97
|
struct ${structName}: AppIntent {
|
|
76
|
-
static var title: LocalizedStringResource = "${intent.title}"
|
|
98
|
+
static var title: LocalizedStringResource = "${escapeSwiftString(intent.title)}"
|
|
77
99
|
static var openAppWhenRun: Bool = ${openApp}
|
|
78
|
-
static var description = IntentDescription("${(_b = intent.description) !== null && _b !== void 0 ? _b : intent.title}")
|
|
100
|
+
static var description = IntentDescription("${escapeSwiftString((_b = intent.description) !== null && _b !== void 0 ? _b : intent.title)}")
|
|
79
101
|
|
|
80
102
|
${paramDecls || ' // No parameters'}
|
|
81
103
|
|
|
82
104
|
func perform() async throws -> some IntentResult {
|
|
83
105
|
var params: [String: Any] = [:]
|
|
84
106
|
${paramExtraction}
|
|
85
|
-
|
|
86
|
-
intentId: "${intent.id}",
|
|
87
|
-
source: "siri",
|
|
88
|
-
parameters: params,
|
|
89
|
-
spokenResponse: ${intent.spokenResponse ? `"${intent.spokenResponse}"` : 'nil'}
|
|
90
|
-
)${spokenResult}
|
|
107
|
+
${backgroundCall}${spokenResult}
|
|
91
108
|
}
|
|
92
109
|
}`;
|
|
93
110
|
}
|
|
@@ -98,9 +115,9 @@ function generateShortcutsProvider(intents) {
|
|
|
98
115
|
var _a, _b;
|
|
99
116
|
return ` AppShortcut(
|
|
100
117
|
intent: ${structName}(),
|
|
101
|
-
phrases: ["${p}"],
|
|
102
|
-
shortTitle: "${(_a = i.shortTitle) !== null && _a !== void 0 ? _a : i.title}",
|
|
103
|
-
systemImageName: "${(_b = i.icon) !== null && _b !== void 0 ? _b : 'star'}"
|
|
118
|
+
phrases: ["${escapeSwiftString(p)}"],
|
|
119
|
+
shortTitle: "${escapeSwiftString((_a = i.shortTitle) !== null && _a !== void 0 ? _a : i.title)}",
|
|
120
|
+
systemImageName: "${escapeSwiftString((_b = i.icon) !== null && _b !== void 0 ? _b : 'star')}"
|
|
104
121
|
)`;
|
|
105
122
|
}).join(',\n');
|
|
106
123
|
return phrases;
|
|
@@ -114,6 +131,19 @@ ${intentRefs}
|
|
|
114
131
|
}
|
|
115
132
|
}`;
|
|
116
133
|
}
|
|
134
|
+
const WIDGET_SIZE_MAP = {
|
|
135
|
+
small: '.systemSmall',
|
|
136
|
+
medium: '.systemMedium',
|
|
137
|
+
large: '.systemLarge',
|
|
138
|
+
extraLarge: '.systemExtraLarge',
|
|
139
|
+
accessory: '.accessoryCircular',
|
|
140
|
+
accessoryStandBy: '.accessoryCorner',
|
|
141
|
+
};
|
|
142
|
+
/** Maps a WidgetSize string to its Swift WidgetFamily case */
|
|
143
|
+
function swiftWidgetFamily(size) {
|
|
144
|
+
var _a;
|
|
145
|
+
return (_a = WIDGET_SIZE_MAP[size]) !== null && _a !== void 0 ? _a : '.systemSmall';
|
|
146
|
+
}
|
|
117
147
|
function generateSwiftIntents(intents) {
|
|
118
148
|
const structs = intents.map(generateIntentStruct).join('\n\n');
|
|
119
149
|
const provider = generateShortcutsProvider(intents);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateSwiftIntents.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftIntents.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generateSwiftIntents.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftIntents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface WidgetCodegenOptions {
|
|
2
|
+
/** Display name shown in the widget picker */
|
|
3
|
+
widgetTitle: string;
|
|
4
|
+
/** Description shown in the widget picker */
|
|
5
|
+
widgetDescription: string;
|
|
6
|
+
/** UserDefaults key the app writes widget data to via setWidgetData() */
|
|
7
|
+
widgetDataKey: string;
|
|
8
|
+
/** Hex accent colour, e.g. "#267AD9" */
|
|
9
|
+
widgetAccentColor: string;
|
|
10
|
+
/** URL scheme deep-link opened when widget is tapped, e.g. "myapp://home" */
|
|
11
|
+
widgetDeepLink: string;
|
|
12
|
+
/** iOS App Group identifier shared between app and widget */
|
|
13
|
+
appGroupId: string;
|
|
14
|
+
/** Widget sizes to support */
|
|
15
|
+
widgetSizes: ('small' | 'medium' | 'large')[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generates a self-contained SwiftUI Widget Extension source file.
|
|
19
|
+
*
|
|
20
|
+
* The widget reads its display data from a JSON string in the shared App Group's
|
|
21
|
+
* UserDefaults under the key `widgetDataKey`.
|
|
22
|
+
*
|
|
23
|
+
* Expected JSON shape (written by the host app via setWidgetData()):
|
|
24
|
+
* {
|
|
25
|
+
* "count": number, // badge count shown prominently
|
|
26
|
+
* "badgeLabel": string, // label under the count, e.g. "Active Errands"
|
|
27
|
+
* "title": string | null, // main item title
|
|
28
|
+
* "subtitle": string | null, // status / secondary text
|
|
29
|
+
* "detail": string | null, // extra detail line (carrier name, assignee, etc.)
|
|
30
|
+
* "deepLink": string | null, // optional per-item URL override
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateSwiftWidget(opts: WidgetCodegenOptions): string;
|
|
34
|
+
export declare function generateWidgetInfoPlist(): string;
|
|
35
|
+
export declare function generateWidgetEntitlements(appGroupId: string): string;
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSwiftWidget = generateSwiftWidget;
|
|
4
|
+
exports.generateWidgetInfoPlist = generateWidgetInfoPlist;
|
|
5
|
+
exports.generateWidgetEntitlements = generateWidgetEntitlements;
|
|
6
|
+
function escapeSwift(s) {
|
|
7
|
+
return s
|
|
8
|
+
.replace(/\\/g, '\\\\')
|
|
9
|
+
.replace(/"/g, '\\"')
|
|
10
|
+
.replace(/\n/g, '\\n')
|
|
11
|
+
.replace(/\r/g, '\\r');
|
|
12
|
+
}
|
|
13
|
+
function hexToSwiftColor(hex) {
|
|
14
|
+
const clean = hex.replace('#', '');
|
|
15
|
+
const r = parseInt(clean.substring(0, 2), 16) / 255;
|
|
16
|
+
const g = parseInt(clean.substring(2, 4), 16) / 255;
|
|
17
|
+
const b = parseInt(clean.substring(4, 6), 16) / 255;
|
|
18
|
+
return `Color(red: ${r.toFixed(3)}, green: ${g.toFixed(3)}, blue: ${b.toFixed(3)})`;
|
|
19
|
+
}
|
|
20
|
+
function familiesClause(sizes) {
|
|
21
|
+
const map = {
|
|
22
|
+
small: '.systemSmall',
|
|
23
|
+
medium: '.systemMedium',
|
|
24
|
+
large: '.systemLarge',
|
|
25
|
+
};
|
|
26
|
+
return sizes.map((s) => { var _a; return (_a = map[s]) !== null && _a !== void 0 ? _a : `.systemSmall`; }).join(', ');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generates a self-contained SwiftUI Widget Extension source file.
|
|
30
|
+
*
|
|
31
|
+
* The widget reads its display data from a JSON string in the shared App Group's
|
|
32
|
+
* UserDefaults under the key `widgetDataKey`.
|
|
33
|
+
*
|
|
34
|
+
* Expected JSON shape (written by the host app via setWidgetData()):
|
|
35
|
+
* {
|
|
36
|
+
* "count": number, // badge count shown prominently
|
|
37
|
+
* "badgeLabel": string, // label under the count, e.g. "Active Errands"
|
|
38
|
+
* "title": string | null, // main item title
|
|
39
|
+
* "subtitle": string | null, // status / secondary text
|
|
40
|
+
* "detail": string | null, // extra detail line (carrier name, assignee, etc.)
|
|
41
|
+
* "deepLink": string | null, // optional per-item URL override
|
|
42
|
+
* }
|
|
43
|
+
*/
|
|
44
|
+
function generateSwiftWidget(opts) {
|
|
45
|
+
const { widgetTitle, widgetDescription, widgetDataKey, widgetAccentColor, widgetDeepLink, appGroupId, widgetSizes, } = opts;
|
|
46
|
+
const accentColor = hexToSwiftColor(widgetAccentColor);
|
|
47
|
+
const bgColor = `Color(red: 0.90, green: 0.96, blue: 1.00)`;
|
|
48
|
+
const families = familiesClause(widgetSizes);
|
|
49
|
+
const hasSmall = widgetSizes.includes('small');
|
|
50
|
+
const hasMedium = widgetSizes.includes('medium');
|
|
51
|
+
const hasLarge = widgetSizes.includes('large');
|
|
52
|
+
const smallCase = hasSmall ? 'case .systemSmall:\n SmallInvokeView(entry: entry)' : '';
|
|
53
|
+
const mediumCase = hasMedium ? 'case .systemMedium:\n MediumInvokeView(entry: entry)' : '';
|
|
54
|
+
const largeCase = hasLarge ? 'case .systemLarge:\n LargeInvokeView(entry: entry)' : '';
|
|
55
|
+
return `// AUTO-GENERATED by expo-invoke — do not edit manually.
|
|
56
|
+
import WidgetKit
|
|
57
|
+
import SwiftUI
|
|
58
|
+
|
|
59
|
+
// MARK: - Data
|
|
60
|
+
|
|
61
|
+
private struct InvokeWidgetData {
|
|
62
|
+
var count: Int
|
|
63
|
+
var badgeLabel: String
|
|
64
|
+
var title: String?
|
|
65
|
+
var subtitle: String?
|
|
66
|
+
var detail: String?
|
|
67
|
+
var deepLink: String?
|
|
68
|
+
|
|
69
|
+
static let empty = InvokeWidgetData(count: 0, badgeLabel: "")
|
|
70
|
+
static let placeholder = InvokeWidgetData(
|
|
71
|
+
count: 2,
|
|
72
|
+
badgeLabel: "${escapeSwift(widgetTitle)}",
|
|
73
|
+
title: "Example Item",
|
|
74
|
+
subtitle: "In Progress",
|
|
75
|
+
detail: "John D.",
|
|
76
|
+
deepLink: nil
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// MARK: - Timeline Entry
|
|
81
|
+
|
|
82
|
+
struct InvokeWidgetEntry: TimelineEntry {
|
|
83
|
+
let date: Date
|
|
84
|
+
let data: InvokeWidgetData
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// MARK: - Provider
|
|
88
|
+
|
|
89
|
+
struct InvokeWidgetProvider: TimelineProvider {
|
|
90
|
+
private let appGroup = "${escapeSwift(appGroupId)}"
|
|
91
|
+
private let dataKey = "${escapeSwift(widgetDataKey)}"
|
|
92
|
+
|
|
93
|
+
func placeholder(in context: Context) -> InvokeWidgetEntry {
|
|
94
|
+
InvokeWidgetEntry(date: Date(), data: .placeholder)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
func getSnapshot(in context: Context, completion: @escaping (InvokeWidgetEntry) -> Void) {
|
|
98
|
+
completion(InvokeWidgetEntry(date: Date(), data: load()))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
func getTimeline(in context: Context, completion: @escaping (Timeline<InvokeWidgetEntry>) -> Void) {
|
|
102
|
+
let entry = InvokeWidgetEntry(date: Date(), data: load())
|
|
103
|
+
let refresh = Calendar.current.date(byAdding: .minute, value: 15, to: Date()) ?? Date()
|
|
104
|
+
completion(Timeline(entries: [entry], policy: .after(refresh)))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private func load() -> InvokeWidgetData {
|
|
108
|
+
guard
|
|
109
|
+
let defaults = UserDefaults(suiteName: appGroup),
|
|
110
|
+
let raw = defaults.string(forKey: dataKey),
|
|
111
|
+
let blob = raw.data(using: .utf8),
|
|
112
|
+
let json = try? JSONSerialization.jsonObject(with: blob) as? [String: Any]
|
|
113
|
+
else { return .empty }
|
|
114
|
+
|
|
115
|
+
return InvokeWidgetData(
|
|
116
|
+
count: json["count"] as? Int ?? 0,
|
|
117
|
+
badgeLabel: json["badgeLabel"] as? String ?? "",
|
|
118
|
+
title: json["title"] as? String,
|
|
119
|
+
subtitle: json["subtitle"] as? String,
|
|
120
|
+
detail: json["detail"] as? String,
|
|
121
|
+
deepLink: json["deepLink"] as? String
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// MARK: - Shared Helpers
|
|
127
|
+
|
|
128
|
+
private let accentColor = ${accentColor}
|
|
129
|
+
private let bgColor = ${bgColor}
|
|
130
|
+
|
|
131
|
+
private func resolvedURL(entry: InvokeWidgetEntry) -> URL {
|
|
132
|
+
let raw = entry.data.deepLink ?? "${escapeSwift(widgetDeepLink)}"
|
|
133
|
+
return URL(string: raw) ?? URL(string: "${escapeSwift(widgetDeepLink)}")!
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// MARK: - Small View
|
|
137
|
+
|
|
138
|
+
${hasSmall ? `struct SmallInvokeView: View {
|
|
139
|
+
let entry: InvokeWidgetEntry
|
|
140
|
+
var body: some View {
|
|
141
|
+
ZStack {
|
|
142
|
+
bgColor.ignoresSafeArea()
|
|
143
|
+
VStack(alignment: .leading, spacing: 6) {
|
|
144
|
+
HStack {
|
|
145
|
+
Image(systemName: "square.grid.2x2.fill")
|
|
146
|
+
.font(.system(size: 16, weight: .semibold))
|
|
147
|
+
.foregroundColor(accentColor)
|
|
148
|
+
Spacer()
|
|
149
|
+
Text("\\(entry.data.count)")
|
|
150
|
+
.font(.system(size: 30, weight: .bold))
|
|
151
|
+
.foregroundColor(accentColor)
|
|
152
|
+
}
|
|
153
|
+
if !entry.data.badgeLabel.isEmpty {
|
|
154
|
+
Text(entry.data.badgeLabel)
|
|
155
|
+
.font(.system(size: 11, weight: .medium))
|
|
156
|
+
.foregroundColor(.secondary)
|
|
157
|
+
}
|
|
158
|
+
Spacer()
|
|
159
|
+
if let title = entry.data.title {
|
|
160
|
+
Text(title)
|
|
161
|
+
.font(.system(size: 12, weight: .semibold))
|
|
162
|
+
.lineLimit(2)
|
|
163
|
+
.foregroundColor(.primary)
|
|
164
|
+
}
|
|
165
|
+
if let sub = entry.data.subtitle {
|
|
166
|
+
Text(sub)
|
|
167
|
+
.font(.system(size: 10))
|
|
168
|
+
.foregroundColor(.secondary)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
.padding(14)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}` : '// Small size not enabled'}
|
|
175
|
+
|
|
176
|
+
// MARK: - Medium View
|
|
177
|
+
|
|
178
|
+
${hasMedium ? `struct MediumInvokeView: View {
|
|
179
|
+
let entry: InvokeWidgetEntry
|
|
180
|
+
var body: some View {
|
|
181
|
+
ZStack {
|
|
182
|
+
bgColor.ignoresSafeArea()
|
|
183
|
+
HStack(spacing: 0) {
|
|
184
|
+
VStack(alignment: .leading, spacing: 8) {
|
|
185
|
+
Image(systemName: "square.grid.2x2.fill")
|
|
186
|
+
.font(.system(size: 20, weight: .semibold))
|
|
187
|
+
.foregroundColor(accentColor)
|
|
188
|
+
Text("\\(entry.data.count)")
|
|
189
|
+
.font(.system(size: 36, weight: .bold))
|
|
190
|
+
.foregroundColor(accentColor)
|
|
191
|
+
if !entry.data.badgeLabel.isEmpty {
|
|
192
|
+
Text(entry.data.badgeLabel)
|
|
193
|
+
.font(.system(size: 11, weight: .medium))
|
|
194
|
+
.foregroundColor(.secondary)
|
|
195
|
+
.lineLimit(2)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
.frame(maxHeight: .infinity, alignment: .topLeading)
|
|
199
|
+
.padding(16)
|
|
200
|
+
.frame(minWidth: 100)
|
|
201
|
+
|
|
202
|
+
Rectangle()
|
|
203
|
+
.fill(Color.secondary.opacity(0.18))
|
|
204
|
+
.frame(width: 1)
|
|
205
|
+
.padding(.vertical, 12)
|
|
206
|
+
|
|
207
|
+
VStack(alignment: .leading, spacing: 6) {
|
|
208
|
+
Text("${escapeSwift(widgetTitle)}")
|
|
209
|
+
.font(.system(size: 10, weight: .semibold))
|
|
210
|
+
.foregroundColor(.secondary)
|
|
211
|
+
if let title = entry.data.title {
|
|
212
|
+
Text(title)
|
|
213
|
+
.font(.system(size: 13, weight: .semibold))
|
|
214
|
+
.lineLimit(2)
|
|
215
|
+
.foregroundColor(.primary)
|
|
216
|
+
}
|
|
217
|
+
if let sub = entry.data.subtitle {
|
|
218
|
+
Text(sub)
|
|
219
|
+
.font(.system(size: 11))
|
|
220
|
+
.foregroundColor(.secondary)
|
|
221
|
+
}
|
|
222
|
+
if let detail = entry.data.detail {
|
|
223
|
+
HStack(spacing: 4) {
|
|
224
|
+
Image(systemName: "person.fill")
|
|
225
|
+
.font(.system(size: 9))
|
|
226
|
+
.foregroundColor(.secondary)
|
|
227
|
+
Text(detail)
|
|
228
|
+
.font(.system(size: 11))
|
|
229
|
+
.foregroundColor(.secondary)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
|
234
|
+
.padding(16)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}` : '// Medium size not enabled'}
|
|
239
|
+
|
|
240
|
+
// MARK: - Large View
|
|
241
|
+
|
|
242
|
+
${hasLarge ? `struct LargeInvokeView: View {
|
|
243
|
+
let entry: InvokeWidgetEntry
|
|
244
|
+
var body: some View {
|
|
245
|
+
ZStack {
|
|
246
|
+
bgColor.ignoresSafeArea()
|
|
247
|
+
VStack(alignment: .leading, spacing: 14) {
|
|
248
|
+
HStack {
|
|
249
|
+
Image(systemName: "square.grid.2x2.fill")
|
|
250
|
+
.font(.system(size: 18, weight: .semibold))
|
|
251
|
+
.foregroundColor(accentColor)
|
|
252
|
+
Text("${escapeSwift(widgetTitle)}")
|
|
253
|
+
.font(.system(size: 17, weight: .bold))
|
|
254
|
+
.foregroundColor(.primary)
|
|
255
|
+
Spacer()
|
|
256
|
+
if entry.data.count > 0 {
|
|
257
|
+
Text("\\(entry.data.count) \\(entry.data.badgeLabel)")
|
|
258
|
+
.font(.system(size: 12, weight: .semibold))
|
|
259
|
+
.foregroundColor(accentColor)
|
|
260
|
+
.padding(.horizontal, 10)
|
|
261
|
+
.padding(.vertical, 4)
|
|
262
|
+
.background(accentColor.opacity(0.12))
|
|
263
|
+
.clipShape(Capsule())
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
Divider()
|
|
267
|
+
if let title = entry.data.title {
|
|
268
|
+
VStack(alignment: .leading, spacing: 8) {
|
|
269
|
+
Text(title)
|
|
270
|
+
.font(.system(size: 15, weight: .semibold))
|
|
271
|
+
.foregroundColor(.primary)
|
|
272
|
+
if let sub = entry.data.subtitle {
|
|
273
|
+
Text(sub)
|
|
274
|
+
.font(.system(size: 12))
|
|
275
|
+
.foregroundColor(.secondary)
|
|
276
|
+
}
|
|
277
|
+
if let detail = entry.data.detail {
|
|
278
|
+
HStack(spacing: 6) {
|
|
279
|
+
Image(systemName: "person.circle.fill")
|
|
280
|
+
.font(.system(size: 13))
|
|
281
|
+
.foregroundColor(accentColor)
|
|
282
|
+
Text(detail)
|
|
283
|
+
.font(.system(size: 12))
|
|
284
|
+
.foregroundColor(.secondary)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
.padding(14)
|
|
289
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
290
|
+
.background(Color.white.opacity(0.6))
|
|
291
|
+
.clipShape(RoundedRectangle(cornerRadius: 12))
|
|
292
|
+
} else {
|
|
293
|
+
VStack(spacing: 10) {
|
|
294
|
+
Image(systemName: "square.grid.2x2")
|
|
295
|
+
.font(.system(size: 34))
|
|
296
|
+
.foregroundColor(accentColor.opacity(0.4))
|
|
297
|
+
Text("Nothing here yet")
|
|
298
|
+
.font(.system(size: 13))
|
|
299
|
+
.foregroundColor(.secondary)
|
|
300
|
+
}
|
|
301
|
+
.frame(maxWidth: .infinity)
|
|
302
|
+
.padding(24)
|
|
303
|
+
}
|
|
304
|
+
Spacer()
|
|
305
|
+
}
|
|
306
|
+
.padding(16)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}` : '// Large size not enabled'}
|
|
310
|
+
|
|
311
|
+
// MARK: - Entry View Router
|
|
312
|
+
|
|
313
|
+
struct InvokeWidgetEntryView: View {
|
|
314
|
+
var entry: InvokeWidgetEntry
|
|
315
|
+
@Environment(\\.widgetFamily) var family
|
|
316
|
+
|
|
317
|
+
var body: some View {
|
|
318
|
+
Group {
|
|
319
|
+
switch family {
|
|
320
|
+
${[smallCase, mediumCase, largeCase].filter(Boolean).join('\n ')}
|
|
321
|
+
default:
|
|
322
|
+
${hasSmall ? 'SmallInvokeView(entry: entry)' : hasMedium ? 'MediumInvokeView(entry: entry)' : 'LargeInvokeView(entry: entry)'}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// MARK: - Widget Configuration
|
|
329
|
+
|
|
330
|
+
struct InvokeWidget: Widget {
|
|
331
|
+
let kind: String = "InvokeWidget"
|
|
332
|
+
|
|
333
|
+
var body: some WidgetConfiguration {
|
|
334
|
+
StaticConfiguration(kind: kind, provider: InvokeWidgetProvider()) { entry in
|
|
335
|
+
InvokeWidgetEntryView(entry: entry)
|
|
336
|
+
.widgetURL(resolvedURL(entry: entry))
|
|
337
|
+
}
|
|
338
|
+
.configurationDisplayName("${escapeSwift(widgetTitle)}")
|
|
339
|
+
.description("${escapeSwift(widgetDescription)}")
|
|
340
|
+
.supportedFamilies([${families}])
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// MARK: - Widget Bundle
|
|
345
|
+
|
|
346
|
+
@main
|
|
347
|
+
struct InvokeWidgetBundle: WidgetBundle {
|
|
348
|
+
var body: some Widget {
|
|
349
|
+
InvokeWidget()
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
`;
|
|
353
|
+
}
|
|
354
|
+
function generateWidgetInfoPlist() {
|
|
355
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
356
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
357
|
+
<plist version="1.0">
|
|
358
|
+
<dict>
|
|
359
|
+
<key>NSExtension</key>
|
|
360
|
+
<dict>
|
|
361
|
+
<key>NSExtensionPointIdentifier</key>
|
|
362
|
+
<string>com.apple.widgetkit-extension</string>
|
|
363
|
+
</dict>
|
|
364
|
+
</dict>
|
|
365
|
+
</plist>`;
|
|
366
|
+
}
|
|
367
|
+
function generateWidgetEntitlements(appGroupId) {
|
|
368
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
369
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
370
|
+
<plist version="1.0">
|
|
371
|
+
<dict>
|
|
372
|
+
<key>com.apple.security.application-groups</key>
|
|
373
|
+
<array>
|
|
374
|
+
<string>${appGroupId}</string>
|
|
375
|
+
</array>
|
|
376
|
+
</dict>
|
|
377
|
+
</plist>`;
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=generateSwiftWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSwiftWidget.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftWidget.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
import { type ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
-
import type { IntentDefinition } from '../../src/types';
|
|
2
|
+
import type { IntentDefinition, AppEntityDefinition, FocusFilterDefinition, AppClipDefinition } from '../../src/types';
|
|
3
3
|
interface IOSInvokeOptions {
|
|
4
4
|
intents: IntentDefinition[];
|
|
5
5
|
voiceUsageDescription?: string;
|
|
6
6
|
appGroupId?: string;
|
|
7
|
+
entities?: AppEntityDefinition[];
|
|
8
|
+
focusFilters?: FocusFilterDefinition[];
|
|
9
|
+
appClips?: AppClipDefinition[];
|
|
10
|
+
enablePushToTalk?: boolean;
|
|
11
|
+
pttUsageDescription?: string;
|
|
12
|
+
enableLiveActivities?: boolean;
|
|
13
|
+
liveActivityTypes?: string[];
|
|
14
|
+
/** Enable the built-in WidgetKit extension. Requires appGroupId. */
|
|
15
|
+
enableWidget?: boolean;
|
|
16
|
+
/** Display name shown in the widget picker (defaults to app name) */
|
|
17
|
+
widgetTitle?: string;
|
|
18
|
+
/** Description shown in the widget picker */
|
|
19
|
+
widgetDescription?: string;
|
|
20
|
+
/**
|
|
21
|
+
* UserDefaults key the app writes widget data to via setWidgetData().
|
|
22
|
+
* Defaults to "invokeWidgetData".
|
|
23
|
+
*/
|
|
24
|
+
widgetDataKey?: string;
|
|
25
|
+
/** Hex accent colour for the widget UI (defaults to "#267AD9") */
|
|
26
|
+
widgetAccentColor?: string;
|
|
27
|
+
/** URL scheme deep-link opened when widget is tapped */
|
|
28
|
+
widgetDeepLink?: string;
|
|
29
|
+
/** Widget sizes to support (defaults to ["small","medium"]) */
|
|
30
|
+
widgetSizes?: ('small' | 'medium' | 'large')[];
|
|
7
31
|
}
|
|
8
32
|
export declare const withIOSInvoke: ConfigPlugin<IOSInvokeOptions>;
|
|
9
33
|
export {};
|