expo-invoke 1.2.0 → 2.0.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/ios/withIOSInvoke.d.ts +8 -1
- package/build/plugin/ios/withIOSInvoke.js +61 -10
- package/build/plugin/ios/withIOSInvoke.js.map +1 -1
- package/build/plugin/src/withInvoke.d.ts +20 -3
- package/build/plugin/src/withInvoke.js +23 -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 +5 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
package expo.modules.invoke
|
|
2
|
+
|
|
3
|
+
import android.app.PendingIntent
|
|
4
|
+
import android.content.BroadcastReceiver
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.Intent
|
|
7
|
+
import android.content.SharedPreferences
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* BroadcastReceiver for interactive widget button taps (Android 12+).
|
|
11
|
+
* Widget buttons use PendingIntent pointing to this receiver.
|
|
12
|
+
* On receive, writes a pending intent so the app (or background handler) can process it.
|
|
13
|
+
*/
|
|
14
|
+
class InteractiveWidgetReceiver : BroadcastReceiver() {
|
|
15
|
+
|
|
16
|
+
companion object {
|
|
17
|
+
const val ACTION = "expo.modules.invoke.WIDGET_ACTION"
|
|
18
|
+
const val EXTRA_INTENT_ID = "intentId"
|
|
19
|
+
const val EXTRA_PARAMETERS = "parameters"
|
|
20
|
+
|
|
21
|
+
fun buildPendingIntent(
|
|
22
|
+
context: Context,
|
|
23
|
+
intentId: String,
|
|
24
|
+
parametersJson: String = "{}",
|
|
25
|
+
requestCode: Int = intentId.hashCode()
|
|
26
|
+
): PendingIntent {
|
|
27
|
+
val intent = Intent(ACTION).apply {
|
|
28
|
+
setPackage(context.packageName)
|
|
29
|
+
putExtra(EXTRA_INTENT_ID, intentId)
|
|
30
|
+
putExtra(EXTRA_PARAMETERS, parametersJson)
|
|
31
|
+
}
|
|
32
|
+
return PendingIntent.getBroadcast(
|
|
33
|
+
context,
|
|
34
|
+
requestCode,
|
|
35
|
+
intent,
|
|
36
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override fun onReceive(context: Context, intent: Intent?) {
|
|
42
|
+
if (intent?.action != ACTION) return
|
|
43
|
+
val intentId = intent.getStringExtra(EXTRA_INTENT_ID) ?: return
|
|
44
|
+
val prefs: SharedPreferences = context.getSharedPreferences("expo.invoke", Context.MODE_PRIVATE)
|
|
45
|
+
ExpoInvokeModule.writePendingIntent(prefs, intentId, "widget")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
package expo.modules.invoke
|
|
2
|
+
|
|
3
|
+
import android.app.PendingIntent
|
|
4
|
+
import android.content.ContentResolver
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.Intent
|
|
7
|
+
import android.net.Uri
|
|
8
|
+
import androidx.slice.Slice
|
|
9
|
+
import androidx.slice.SliceProvider
|
|
10
|
+
import androidx.slice.builders.ListBuilder
|
|
11
|
+
import androidx.slice.builders.SliceAction
|
|
12
|
+
import org.json.JSONArray
|
|
13
|
+
import org.json.JSONException
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Android Slices provider for expo-invoke.
|
|
17
|
+
* Surfaces live app content inside Google Search and Google Assistant responses.
|
|
18
|
+
*
|
|
19
|
+
* Register in AndroidManifest via withAndroidInvoke plugin when slices[] is defined.
|
|
20
|
+
* Authority: {packageName}.invoke.slices
|
|
21
|
+
*
|
|
22
|
+
* Each SliceDefinition maps a URI path to an intent + widget data.
|
|
23
|
+
*/
|
|
24
|
+
class InvokeSliceProvider : SliceProvider() {
|
|
25
|
+
|
|
26
|
+
override fun onCreateSliceProvider(): Boolean = true
|
|
27
|
+
|
|
28
|
+
override fun onBindSlice(sliceUri: Uri): Slice? {
|
|
29
|
+
val context = context ?: return null
|
|
30
|
+
val prefs = context.getSharedPreferences("expo.invoke", Context.MODE_PRIVATE)
|
|
31
|
+
|
|
32
|
+
val sliceConfigJson = prefs.getString("slices", null) ?: return null
|
|
33
|
+
val sliceConfig = findSliceForUri(sliceConfigJson, sliceUri.path ?: "") ?: return null
|
|
34
|
+
|
|
35
|
+
val title = sliceConfig.optString("title", "")
|
|
36
|
+
val intentId = sliceConfig.optString("intentId", "")
|
|
37
|
+
val subtitleKey = sliceConfig.optString("subtitleKey", null)
|
|
38
|
+
val subtitle = subtitleKey?.let { prefs.getString("widget.$it", null) }
|
|
39
|
+
|
|
40
|
+
val tapIntent = buildTapIntent(context, intentId)
|
|
41
|
+
val action = SliceAction.create(tapIntent, null, ListBuilder.ICON_IMAGE, title)
|
|
42
|
+
|
|
43
|
+
return ListBuilder(context, sliceUri, ListBuilder.INFINITY)
|
|
44
|
+
.addRow { row ->
|
|
45
|
+
row.setTitle(title)
|
|
46
|
+
if (subtitle != null) row.setSubtitle(subtitle.trim('"'))
|
|
47
|
+
row.setPrimaryAction(action)
|
|
48
|
+
}
|
|
49
|
+
.build()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override fun onMapIntentToUri(intent: Intent?): Uri {
|
|
53
|
+
val prefs = context?.getSharedPreferences("expo.invoke", Context.MODE_PRIVATE)
|
|
54
|
+
val pkg = context?.packageName ?: "unknown"
|
|
55
|
+
return Uri.parse("content://$pkg.invoke.slices/default")
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private fun findSliceForUri(json: String, path: String): org.json.JSONObject? {
|
|
59
|
+
return try {
|
|
60
|
+
val arr = JSONArray(json)
|
|
61
|
+
for (i in 0 until arr.length()) {
|
|
62
|
+
val obj = arr.getJSONObject(i)
|
|
63
|
+
if (obj.optString("uriPath") == path) return obj
|
|
64
|
+
}
|
|
65
|
+
null
|
|
66
|
+
} catch (_: JSONException) { null }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private fun buildTapIntent(context: Context, intentId: String): PendingIntent {
|
|
70
|
+
val pkg = context.packageName
|
|
71
|
+
val deepLink = "$pkg://invoke/$intentId"
|
|
72
|
+
val launchIntent = Intent(Intent.ACTION_VIEW, Uri.parse(deepLink)).apply {
|
|
73
|
+
setPackage(pkg)
|
|
74
|
+
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
|
75
|
+
}
|
|
76
|
+
return PendingIntent.getActivity(
|
|
77
|
+
context,
|
|
78
|
+
intentId.hashCode(),
|
|
79
|
+
launchIntent,
|
|
80
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -6,6 +6,7 @@ import android.content.pm.ShortcutInfo
|
|
|
6
6
|
import android.content.pm.ShortcutManager
|
|
7
7
|
import android.graphics.drawable.Icon
|
|
8
8
|
import android.os.Build
|
|
9
|
+
import android.util.Log
|
|
9
10
|
import androidx.core.content.getSystemService
|
|
10
11
|
import org.json.JSONArray
|
|
11
12
|
import org.json.JSONObject
|
|
@@ -29,44 +30,49 @@ object ShortcutsHelper {
|
|
|
29
30
|
|
|
30
31
|
@TargetApi(Build.VERSION_CODES.N_MR1)
|
|
31
32
|
private fun parseShortcuts(context: Context, json: String): List<ShortcutInfo> {
|
|
32
|
-
val arr =
|
|
33
|
-
|
|
33
|
+
val arr = try {
|
|
34
|
+
JSONArray(json)
|
|
35
|
+
} catch (e: Exception) {
|
|
36
|
+
Log.w("ExpoInvoke", "parseShortcuts: could not parse JSON array: ${e.message}")
|
|
37
|
+
return emptyList()
|
|
38
|
+
}
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
return (0 until arr.length()).mapNotNull { i ->
|
|
41
|
+
runCatching {
|
|
42
|
+
val obj = arr.getJSONObject(i)
|
|
43
|
+
val id = obj.getString("id")
|
|
44
|
+
val title = obj.getString("title")
|
|
45
|
+
val subtitle = obj.optString("subtitle", "")
|
|
46
|
+
val intentId = obj.optString("intentId", id)
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
val launchIntent = context.packageManager
|
|
49
|
+
.getLaunchIntentForPackage(context.packageName)
|
|
50
|
+
?.apply {
|
|
51
|
+
action = "expo.invoke.SHORTCUT"
|
|
52
|
+
putExtra("intentId", intentId)
|
|
53
|
+
if (obj.has("parameters")) {
|
|
54
|
+
putExtra("parameters", obj.getJSONObject("parameters").toString())
|
|
55
|
+
}
|
|
50
56
|
}
|
|
51
|
-
|
|
52
|
-
?: continue
|
|
57
|
+
?: return@runCatching null
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
val builder = ShortcutInfo.Builder(context, id)
|
|
60
|
+
.setShortLabel(title.take(10))
|
|
61
|
+
.setLongLabel(if (subtitle.isNotEmpty()) subtitle.take(25) else title.take(25))
|
|
62
|
+
.setIntent(launchIntent)
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
} catch (_: Exception) { /* icon is optional */ }
|
|
64
|
+
try {
|
|
65
|
+
val iconRes = context.resources.getIdentifier("ic_launcher", "mipmap", context.packageName)
|
|
66
|
+
if (iconRes != 0) {
|
|
67
|
+
builder.setIcon(Icon.createWithResource(context, iconRes))
|
|
68
|
+
}
|
|
69
|
+
} catch (_: Exception) { /* icon is optional */ }
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
builder.build()
|
|
72
|
+
}.getOrElse { e ->
|
|
73
|
+
Log.w("ExpoInvoke", "parseShortcuts: skipping shortcut at index $i: ${e.message}")
|
|
74
|
+
null
|
|
75
|
+
}
|
|
68
76
|
}
|
|
69
|
-
|
|
70
|
-
return result
|
|
71
77
|
}
|
|
72
78
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
-
import type { IntentDefinition, NotificationCategoryDefinition } from '../../src/types';
|
|
2
|
+
import type { IntentDefinition, NotificationCategoryDefinition, SliceDefinition } from '../../src/types';
|
|
3
3
|
interface AndroidInvokeOptions {
|
|
4
4
|
intents: IntentDefinition[];
|
|
5
5
|
notificationActions?: NotificationCategoryDefinition[];
|
|
6
|
+
slices?: SliceDefinition[];
|
|
7
|
+
enableInteractiveWidgets?: boolean;
|
|
6
8
|
}
|
|
7
9
|
export declare const withAndroidInvoke: ConfigPlugin<AndroidInvokeOptions>;
|
|
8
10
|
export {};
|
|
@@ -40,17 +40,18 @@ const path = __importStar(require("path"));
|
|
|
40
40
|
const generateActionsXml_1 = require("../codegen/generateActionsXml");
|
|
41
41
|
const generateShortcutsXml_1 = require("../codegen/generateShortcutsXml");
|
|
42
42
|
const withAndroidInvoke = (config, options) => {
|
|
43
|
-
const { intents } = options;
|
|
44
|
-
// 1. AndroidManifest.xml
|
|
43
|
+
const { intents, slices = [], enableInteractiveWidgets = false } = options;
|
|
44
|
+
// 1. AndroidManifest.xml
|
|
45
45
|
config = (0, config_plugins_1.withAndroidManifest)(config, (cfg) => {
|
|
46
|
-
var _a, _b, _c, _d, _e;
|
|
46
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
47
47
|
const app = (_a = cfg.modResults.manifest.application) === null || _a === void 0 ? void 0 : _a[0];
|
|
48
48
|
if (!app)
|
|
49
49
|
return cfg;
|
|
50
50
|
app.service = (_b = app.service) !== null && _b !== void 0 ? _b : [];
|
|
51
51
|
app.receiver = (_c = app.receiver) !== null && _c !== void 0 ? _c : [];
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
app.provider = (_d = app.provider) !== null && _d !== void 0 ? _d : [];
|
|
53
|
+
const packageName = (_f = (_e = cfg.android) === null || _e === void 0 ? void 0 : _e.package) !== null && _f !== void 0 ? _f : 'com.example.app';
|
|
54
|
+
// QuickTileService
|
|
54
55
|
const hasQts = app.service.some((s) => { var _a; return ((_a = s.$) === null || _a === void 0 ? void 0 : _a['android:name']) === 'expo.modules.invoke.QuickTileService'; });
|
|
55
56
|
if (!hasQts) {
|
|
56
57
|
app.service.push({
|
|
@@ -62,16 +63,45 @@ const withAndroidInvoke = (config, options) => {
|
|
|
62
63
|
'android:exported': 'true',
|
|
63
64
|
},
|
|
64
65
|
'intent-filter': [
|
|
65
|
-
{
|
|
66
|
-
action: [{ $: { 'android:name': 'android.service.quicksettings.action.QS_TILE' } }],
|
|
67
|
-
},
|
|
66
|
+
{ action: [{ $: { 'android:name': 'android.service.quicksettings.action.QS_TILE' } }] },
|
|
68
67
|
],
|
|
69
68
|
});
|
|
70
69
|
}
|
|
71
|
-
//
|
|
72
|
-
|
|
70
|
+
// InteractiveWidgetReceiver
|
|
71
|
+
if (enableInteractiveWidgets) {
|
|
72
|
+
const hasReceiver = app.receiver.some((r) => { var _a; return ((_a = r.$) === null || _a === void 0 ? void 0 : _a['android:name']) === 'expo.modules.invoke.InteractiveWidgetReceiver'; });
|
|
73
|
+
if (!hasReceiver) {
|
|
74
|
+
app.receiver.push({
|
|
75
|
+
$: {
|
|
76
|
+
'android:name': 'expo.modules.invoke.InteractiveWidgetReceiver',
|
|
77
|
+
'android:exported': 'false',
|
|
78
|
+
},
|
|
79
|
+
'intent-filter': [
|
|
80
|
+
{ action: [{ $: { 'android:name': 'expo.modules.invoke.WIDGET_ACTION' } }] },
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// InvokeSliceProvider
|
|
86
|
+
if (slices.length > 0) {
|
|
87
|
+
const hasSlice = app.provider.some((p) => { var _a; return ((_a = p.$) === null || _a === void 0 ? void 0 : _a['android:name']) === 'expo.modules.invoke.InvokeSliceProvider'; });
|
|
88
|
+
if (!hasSlice) {
|
|
89
|
+
app.provider.push({
|
|
90
|
+
$: {
|
|
91
|
+
'android:name': 'expo.modules.invoke.InvokeSliceProvider',
|
|
92
|
+
'android:authorities': `${packageName}.invoke.slices`,
|
|
93
|
+
'android:exported': 'true',
|
|
94
|
+
},
|
|
95
|
+
'intent-filter': [
|
|
96
|
+
{ action: [{ $: { 'android:name': 'android.intent.action.VIEW' } }] },
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// App Actions + Shortcuts meta-data on MainActivity
|
|
102
|
+
const mainActivity = ((_g = app.activity) !== null && _g !== void 0 ? _g : []).find((a) => { var _a, _b; return (_b = (_a = a.$) === null || _a === void 0 ? void 0 : _a['android:name']) === null || _b === void 0 ? void 0 : _b.endsWith('.MainActivity'); });
|
|
73
103
|
if (mainActivity) {
|
|
74
|
-
mainActivity['meta-data'] = (
|
|
104
|
+
mainActivity['meta-data'] = (_h = mainActivity['meta-data']) !== null && _h !== void 0 ? _h : [];
|
|
75
105
|
const hasMeta = mainActivity['meta-data'].some((m) => { var _a; return ((_a = m.$) === null || _a === void 0 ? void 0 : _a['android:name']) === 'android.app.shortcuts'; });
|
|
76
106
|
if (!hasMeta) {
|
|
77
107
|
mainActivity['meta-data'].push({
|
|
@@ -87,16 +117,42 @@ const withAndroidInvoke = (config, options) => {
|
|
|
87
117
|
}
|
|
88
118
|
return cfg;
|
|
89
119
|
});
|
|
90
|
-
// 2. Generate res/xml
|
|
120
|
+
// 2. Generate res/xml files + slice strings
|
|
91
121
|
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
92
122
|
'android',
|
|
93
123
|
async (cfg) => {
|
|
94
124
|
var _a, _b;
|
|
95
125
|
const packageName = (_b = (_a = cfg.android) === null || _a === void 0 ? void 0 : _a.package) !== null && _b !== void 0 ? _b : 'com.example.app';
|
|
96
126
|
const resXmlDir = path.join(cfg.modRequest.platformProjectRoot, 'app', 'src', 'main', 'res', 'xml');
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
127
|
+
const resValuesDir = path.join(cfg.modRequest.platformProjectRoot, 'app', 'src', 'main', 'res', 'values');
|
|
128
|
+
for (const dir of [resXmlDir, resValuesDir]) {
|
|
129
|
+
try {
|
|
130
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
throw new Error(`[expo-invoke] Could not create Android resource directory at "${dir}".\n` +
|
|
134
|
+
`Cause: ${e instanceof Error ? e.message : e}\n` +
|
|
135
|
+
`Fix: Ensure the path is writable. Try running \`npx expo prebuild --clean\`.`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const writeXml = (filePath, content) => {
|
|
139
|
+
try {
|
|
140
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
throw new Error(`[expo-invoke] Failed to write "${path.basename(filePath)}".\n` +
|
|
144
|
+
`Cause: ${e instanceof Error ? e.message : e}\n` +
|
|
145
|
+
`Fix: Ensure the Android resource directory is writable. Run \`npx expo prebuild --clean\`.`);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
writeXml(path.join(resXmlDir, 'actions.xml'), (0, generateActionsXml_1.generateActionsXml)(intents, packageName));
|
|
149
|
+
writeXml(path.join(resXmlDir, 'shortcuts.xml'), (0, generateShortcutsXml_1.generateShortcutsXml)(intents, packageName));
|
|
150
|
+
// Slice string resources
|
|
151
|
+
if (slices.length > 0) {
|
|
152
|
+
const sliceStrings = slices.map((s) => ` <string name="slice_${s.id}_title">${s.title}</string>`).join('\n');
|
|
153
|
+
const xml = `<?xml version="1.0" encoding="utf-8"?>\n<resources>\n${sliceStrings}\n</resources>`;
|
|
154
|
+
writeXml(path.join(resValuesDir, 'slice_strings.xml'), xml);
|
|
155
|
+
}
|
|
100
156
|
return cfg;
|
|
101
157
|
},
|
|
102
158
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withAndroidInvoke.js","sourceRoot":"","sources":["../../../plugin/android/withAndroidInvoke.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAI8B;AAC9B,uCAAyB;AACzB,2CAA6B;AAC7B,sEAAmE;AACnE,0EAAuE;
|
|
1
|
+
{"version":3,"file":"withAndroidInvoke.js","sourceRoot":"","sources":["../../../plugin/android/withAndroidInvoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSwiftAppClip = generateSwiftAppClip;
|
|
4
|
+
function generateSwiftAppClip(clips) {
|
|
5
|
+
if (clips.length === 0)
|
|
6
|
+
return '';
|
|
7
|
+
const registrations = clips.map((c) => ` AppClipHandler.register(intentId: "${c.intentId}", urlPrefix: "${c.urlPrefix}")`).join('\n');
|
|
8
|
+
return `// AUTO-GENERATED by expo-invoke config plugin. Do not edit manually.
|
|
9
|
+
import Foundation
|
|
10
|
+
|
|
11
|
+
// Called once during app startup to register App Clip URL → intent mappings.
|
|
12
|
+
// ExpoInvokeModule.configure() calls this automatically.
|
|
13
|
+
@objc public class InvokeAppClipRegistrations: NSObject {
|
|
14
|
+
@objc public static func registerAll() {
|
|
15
|
+
${registrations}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=generateSwiftAppClip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSwiftAppClip.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftAppClip.ts"],"names":[],"mappings":";;AAEA,oDAkBC;AAlBD,SAAgB,oBAAoB,CAAC,KAA0B;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACpC,wCAAwC,CAAC,CAAC,QAAQ,kBAAkB,CAAC,CAAC,SAAS,IAAI,CACpF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;;;;;;;EAOP,aAAa;;;CAGd,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSwiftEntities = generateSwiftEntities;
|
|
4
|
+
function toPascalCase(id) {
|
|
5
|
+
return id.split(/[_\s-]+/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join('');
|
|
6
|
+
}
|
|
7
|
+
function swiftPropertyType(type) {
|
|
8
|
+
switch (type) {
|
|
9
|
+
case 'text': return 'String';
|
|
10
|
+
case 'number': return 'Double';
|
|
11
|
+
case 'date': return 'Date';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function generateEntityStruct(entity) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const name = `${toPascalCase(entity.id)}Entity`;
|
|
17
|
+
const queryName = `${toPascalCase(entity.id)}EntityQuery`;
|
|
18
|
+
const propDecls = entity.properties.map((p) => ` var ${p.name}: ${swiftPropertyType(p.type)}`).join('\n');
|
|
19
|
+
const toJSONLines = entity.properties.map((p) => {
|
|
20
|
+
if (p.type === 'date') {
|
|
21
|
+
return ` dict["${p.name}"] = ${p.name}.timeIntervalSince1970 * 1000`;
|
|
22
|
+
}
|
|
23
|
+
return ` dict["${p.name}"] = ${p.name}`;
|
|
24
|
+
}).join('\n');
|
|
25
|
+
const fromJSONLines = entity.properties.map((p) => {
|
|
26
|
+
if (p.type === 'number') {
|
|
27
|
+
return ` self.${p.name} = dict["${p.name}"] as? Double ?? 0`;
|
|
28
|
+
}
|
|
29
|
+
else if (p.type === 'date') {
|
|
30
|
+
return ` self.${p.name} = (dict["${p.name}"] as? Double).map { Date(timeIntervalSince1970: $0 / 1000) } ?? Date()`;
|
|
31
|
+
}
|
|
32
|
+
return ` self.${p.name} = dict["${p.name}"] as? String ?? ""`;
|
|
33
|
+
}).join('\n');
|
|
34
|
+
const displayRep = (_b = (_a = entity.properties[0]) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'id';
|
|
35
|
+
return `@available(iOS 16.4, *)
|
|
36
|
+
struct ${name}: AppEntity {
|
|
37
|
+
static var typeDisplayRepresentation: TypeDisplayRepresentation = "${entity.title}"
|
|
38
|
+
static var defaultQuery = ${queryName}()
|
|
39
|
+
|
|
40
|
+
var id: String
|
|
41
|
+
${propDecls}
|
|
42
|
+
|
|
43
|
+
var displayRepresentation: DisplayRepresentation {
|
|
44
|
+
DisplayRepresentation(title: LocalizedStringResource(stringLiteral: ${displayRep}))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func toJSON() -> [String: Any] {
|
|
48
|
+
var dict: [String: Any] = ["id": id]
|
|
49
|
+
${toJSONLines}
|
|
50
|
+
return dict
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
init(id: String, dict: [String: Any]) {
|
|
54
|
+
self.id = id
|
|
55
|
+
${fromJSONLines}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@available(iOS 16.4, *)
|
|
60
|
+
struct ${queryName}: EntityQuery {
|
|
61
|
+
func entities(for ids: [${name}.ID]) async throws -> [${name}] { [] }
|
|
62
|
+
|
|
63
|
+
func suggestedEntities() async throws -> [${name}] {
|
|
64
|
+
let results = await EntityQueryBridge.shared.queryEntities(entityId: "${entity.id}", query: "")
|
|
65
|
+
return results.compactMap { dict in
|
|
66
|
+
guard let id = dict["id"] as? String else { return nil }
|
|
67
|
+
return ${name}(id: id, dict: dict)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func entities(matching query: String) async throws -> [${name}] {
|
|
72
|
+
let results = await EntityQueryBridge.shared.queryEntities(entityId: "${entity.id}", query: query)
|
|
73
|
+
return results.compactMap { dict in
|
|
74
|
+
guard let id = dict["id"] as? String else { return nil }
|
|
75
|
+
return ${name}(id: id, dict: dict)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}`;
|
|
79
|
+
}
|
|
80
|
+
function generateSwiftEntities(entities) {
|
|
81
|
+
if (entities.length === 0)
|
|
82
|
+
return '';
|
|
83
|
+
const structs = entities.map(generateEntityStruct).join('\n\n');
|
|
84
|
+
return `// AUTO-GENERATED by expo-invoke config plugin. Do not edit manually.
|
|
85
|
+
import AppIntents
|
|
86
|
+
import Foundation
|
|
87
|
+
|
|
88
|
+
${structs}
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=generateSwiftEntities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSwiftEntities.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftEntities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSwiftFocusFilters = generateSwiftFocusFilters;
|
|
4
|
+
function toPascalCase(id) {
|
|
5
|
+
return id.split(/[_\s-]+/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join('');
|
|
6
|
+
}
|
|
7
|
+
function swiftParamType(type) {
|
|
8
|
+
return type === 'boolean' ? 'Bool' : 'String';
|
|
9
|
+
}
|
|
10
|
+
function generateFilterStruct(filter) {
|
|
11
|
+
var _a;
|
|
12
|
+
const name = `${toPascalCase(filter.id)}FocusFilter`;
|
|
13
|
+
const params = (_a = filter.parameters) !== null && _a !== void 0 ? _a : [];
|
|
14
|
+
const paramDecls = params.map((p) => ` @Parameter(title: "${p.title}")\n var ${p.name}: ${swiftParamType(p.type)}${p.type === 'boolean' ? '' : '?'}`).join('\n\n');
|
|
15
|
+
const paramsDict = params.map((p) => ` params["${p.name}"] = ${p.name}${p.type !== 'boolean' ? ' ?? ""' : ''}`).join('\n');
|
|
16
|
+
return `@available(iOS 16.0, *)
|
|
17
|
+
struct ${name}: SetFocusFilterIntent {
|
|
18
|
+
static var title: LocalizedStringResource = "${filter.title}"
|
|
19
|
+
static var authorizationPolicy: IntentAuthorizationPolicy = .alwaysAllowed
|
|
20
|
+
|
|
21
|
+
${paramDecls || ' // No parameters'}
|
|
22
|
+
|
|
23
|
+
func perform() async throws -> some IntentResult {
|
|
24
|
+
var params: [String: Any] = [:]
|
|
25
|
+
${paramsDict}
|
|
26
|
+
FocusFilterRegistrar.shared.apply(filterId: "${filter.id}", parameters: params)
|
|
27
|
+
return .result()
|
|
28
|
+
}
|
|
29
|
+
}`;
|
|
30
|
+
}
|
|
31
|
+
function generateSwiftFocusFilters(filters) {
|
|
32
|
+
if (filters.length === 0)
|
|
33
|
+
return '';
|
|
34
|
+
const structs = filters.map(generateFilterStruct).join('\n\n');
|
|
35
|
+
return `// AUTO-GENERATED by expo-invoke config plugin. Do not edit manually.
|
|
36
|
+
import AppIntents
|
|
37
|
+
import Foundation
|
|
38
|
+
|
|
39
|
+
${structs}
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=generateSwiftFocusFilters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSwiftFocusFilters.js","sourceRoot":"","sources":["../../../plugin/codegen/generateSwiftFocusFilters.ts"],"names":[],"mappings":";;AAsCA,8DASC;AA7CD,SAAS,YAAY,CAAC,EAAU;IAC9B,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzF,CAAC;AAED,SAAS,cAAc,CAAC,IAAwB;IAC9C,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChD,CAAC;AAED,SAAS,oBAAoB,CAAC,MAA6B;;IACzD,MAAM,IAAI,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC;IACrD,MAAM,MAAM,GAAG,MAAA,MAAM,CAAC,UAAU,mCAAI,EAAE,CAAC;IAEvC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,wBAAwB,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAClH,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEf,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,eAAe,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;SACA,IAAI;iDACoC,MAAM,CAAC,KAAK;;;EAG3D,UAAU,IAAI,oBAAoB;;;;EAIlC,UAAU;mDACuC,MAAM,CAAC,EAAE;;;EAG1D,CAAC;AACH,CAAC;AAED,SAAgB,yBAAyB,CAAC,OAAgC;IACxE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO;;;;EAIP,OAAO;CACR,CAAC;AACF,CAAC"}
|