expo-invoke 2.0.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/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 +17 -0
- package/build/plugin/ios/withIOSInvoke.js +23 -1
- 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 +25 -0
- package/build/plugin/src/withInvoke.js +8 -1
- package/build/plugin/src/withInvoke.js.map +1 -1
- package/package.json +1 -1
|
@@ -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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"}
|
|
@@ -11,6 +11,23 @@ interface IOSInvokeOptions {
|
|
|
11
11
|
pttUsageDescription?: string;
|
|
12
12
|
enableLiveActivities?: boolean;
|
|
13
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')[];
|
|
14
31
|
}
|
|
15
32
|
export declare const withIOSInvoke: ConfigPlugin<IOSInvokeOptions>;
|
|
16
33
|
export {};
|
|
@@ -41,8 +41,10 @@ const generateSwiftIntents_1 = require("../codegen/generateSwiftIntents");
|
|
|
41
41
|
const generateSwiftEntities_1 = require("../codegen/generateSwiftEntities");
|
|
42
42
|
const generateSwiftFocusFilters_1 = require("../codegen/generateSwiftFocusFilters");
|
|
43
43
|
const generateSwiftAppClip_1 = require("../codegen/generateSwiftAppClip");
|
|
44
|
+
const withWidgetExtension_1 = require("./withWidgetExtension");
|
|
44
45
|
const withIOSInvoke = (config, options) => {
|
|
45
|
-
|
|
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;
|
|
46
48
|
// 1. Info.plist usage descriptions + feature flags
|
|
47
49
|
config = (0, config_plugins_1.withInfoPlist)(config, (cfg) => {
|
|
48
50
|
var _a;
|
|
@@ -128,6 +130,26 @@ const withIOSInvoke = (config, options) => {
|
|
|
128
130
|
return cfg;
|
|
129
131
|
},
|
|
130
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
|
+
}
|
|
131
153
|
return config;
|
|
132
154
|
};
|
|
133
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;AACvE,4EAAyE;AACzE,oFAAiF;AACjF,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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"}
|
|
@@ -28,6 +28,31 @@ export interface InvokePluginOptions {
|
|
|
28
28
|
enableLiveActivities?: boolean;
|
|
29
29
|
/** ActivityAttributes class names your app defines (for documentation / validation) */
|
|
30
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')[];
|
|
31
56
|
}
|
|
32
57
|
declare const _default: any;
|
|
33
58
|
export default _default;
|
|
@@ -5,7 +5,7 @@ const withIOSInvoke_1 = require("../ios/withIOSInvoke");
|
|
|
5
5
|
const withAndroidInvoke_1 = require("../android/withAndroidInvoke");
|
|
6
6
|
const validation_1 = require("../../src/utils/validation");
|
|
7
7
|
const withInvoke = (config, options) => {
|
|
8
|
-
const { intents = [], widgets: _widgets, notificationActions, voiceUsageDescription, appGroupId, entities = [], focusFilters = [], appClips = [], slices = [], enableInteractiveWidgets = false, enablePushToTalk = false, pttUsageDescription, enableLiveActivities = false, liveActivityTypes = [], } = options;
|
|
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
9
|
// Validate options early — throws with a helpful message if misconfigured
|
|
10
10
|
(0, validation_1.validatePluginOptions)({ enablePushToTalk, pttUsageDescription, enableLiveActivities, liveActivityTypes });
|
|
11
11
|
config = (0, withIOSInvoke_1.withIOSInvoke)(config, {
|
|
@@ -19,6 +19,13 @@ const withInvoke = (config, options) => {
|
|
|
19
19
|
pttUsageDescription,
|
|
20
20
|
enableLiveActivities,
|
|
21
21
|
liveActivityTypes,
|
|
22
|
+
enableWidget,
|
|
23
|
+
widgetTitle,
|
|
24
|
+
widgetDescription,
|
|
25
|
+
widgetDataKey,
|
|
26
|
+
widgetAccentColor,
|
|
27
|
+
widgetDeepLink,
|
|
28
|
+
widgetSizes,
|
|
22
29
|
});
|
|
23
30
|
config = (0, withAndroidInvoke_1.withAndroidInvoke)(config, {
|
|
24
31
|
intents,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withInvoke.js","sourceRoot":"","sources":["../../../plugin/src/withInvoke.ts"],"names":[],"mappings":";;AAAA,yDAA8E;AAC9E,wDAAqD;AACrD,oEAAiE;AACjE,2DAAmE;
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-invoke",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "The complete native-surface-to-JS bridge for Expo. One intent config → Siri, Google Assistant, home screen widgets, Dynamic Island, app icon menus, notification actions, NFC, QR, deep links and more — all through a single useInvoke() hook.",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"module": "build/src/index.js",
|