diff --git a/README.md b/README.md index 5983e68..cd00b37 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@
StartTemplateWidgetOptions |
+
+**Returns:** Promise<StartTemplateActivityResult>
+
+--------------------
+
+
### updateTemplateActivity(...)
```typescript
@@ -513,6 +566,21 @@ Complete or fail an async widget bridge message.
--------------------
+### reloadWidgets(...)
+
+```typescript
+reloadWidgets(options?: ReloadWidgetsOptions | undefined) => PromiseReloadWidgetsOptions |
+
+--------------------
+
+
### getPluginVersion()
```typescript
@@ -582,13 +650,14 @@ Generic SVG template definition stored by the plugin.
Bundle of optional WidgetKit surface layouts.
-| Prop | Type | Description |
-| ---------------------------------- | --------------------------------------------------------------- | ------------------------------------------------ |
-| **`lockScreen`** | SvgTemplateLayout | Primary lock-screen / banner layout. |
-| **`dynamicIslandExpanded`** | SvgTemplateLayout | Optional expanded Dynamic Island layout. |
-| **`dynamicIslandCompactLeading`** | SvgTemplateLayout | Optional compact leading Dynamic Island layout. |
-| **`dynamicIslandCompactTrailing`** | SvgTemplateLayout | Optional compact trailing Dynamic Island layout. |
-| **`dynamicIslandMinimal`** | SvgTemplateLayout | Optional minimal Dynamic Island layout. |
+| Prop | Type | Description |
+| ---------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
+| **`homeScreen`** | SvgTemplateLayout | Optional Home Screen / SpringBoard widget layout. When omitted, native Home Screen widgets may fall back to `lockScreen`. |
+| **`lockScreen`** | SvgTemplateLayout | Optional lock-screen / Live Activity banner layout. |
+| **`dynamicIslandExpanded`** | SvgTemplateLayout | Optional expanded Dynamic Island layout. |
+| **`dynamicIslandCompactLeading`** | SvgTemplateLayout | Optional compact leading Dynamic Island layout. |
+| **`dynamicIslandCompactTrailing`** | SvgTemplateLayout | Optional compact trailing Dynamic Island layout. |
+| **`dynamicIslandMinimal`** | SvgTemplateLayout | Optional minimal Dynamic Island layout. |
#### SvgTemplateLayoutWithSvg
@@ -740,6 +809,22 @@ Persisted timer runtime state.
Options for starting a generic SVG template activity.
+| Prop | Type | Description |
+| ----------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`activityId`** | string | Optional explicit activity identifier. When omitted, the native runtime creates one. |
+| **`definition`** | SvgTemplateDefinition | Generic SVG template definition. |
+| **`state`** | SvgTemplateState | Initial JSON state exposed under `state.*`. |
+| **`openUrl`** | string | Optional deep link used when the widget body is tapped. |
+| **`startLiveActivity`** | boolean | Whether iOS should also start a native Live Activity. Defaults to `true`. Set to `false` when the same SVG template should only back a home-screen or lock-screen widget surface. |
+
+
+#### StartTemplateWidgetOptions
+
+Options for starting or replacing a Home Screen / SpringBoard widget template.
+
+This persists the same SVG template record as `startTemplateActivity`, but native iOS
+implementations do not start an ActivityKit Live Activity.
+
| Prop | Type | Description |
| ---------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **`activityId`** | string | Optional explicit activity identifier. When omitted, the native runtime creates one. |
@@ -1046,6 +1131,15 @@ Options for completing an async widget bridge message.
| **`error`** | string | Optional error string. When set, the message status becomes `failed`. |
+#### ReloadWidgetsOptions
+
+Options for forcing installed native widgets to reload their timeline.
+
+| Prop | Type | Description |
+| ---------- | ------------------- | ---------------------------------------------------------------------------------------------- |
+| **`kind`** | string | Optional native widget kind to reload on iOS. When omitted, every widget timeline is reloaded. |
+
+
#### PluginVersionResult
Result payload for plugin version queries.
@@ -1090,7 +1184,7 @@ JSON-safe array used as activity state.
Named WidgetKit surface for one SVG layout variant.
-'lockScreen' | 'dynamicIslandExpanded' | 'dynamicIslandCompactLeading' | 'dynamicIslandCompactTrailing' | 'dynamicIslandMinimal'
+'homeScreen' | 'lockScreen' | 'dynamicIslandExpanded' | 'dynamicIslandCompactLeading' | 'dynamicIslandCompactTrailing' | 'dynamicIslandMinimal'
#### SvgTemplateState
diff --git a/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKit.java b/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKit.java
index b429611..de45e1d 100644
--- a/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKit.java
+++ b/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKit.java
@@ -185,6 +185,11 @@ public JSONObject completeWidgetMessage(final String messageId, final JSONObject
return message;
}
+ public void reloadWidgets(final String kind) {
+ notifyStoreChanged(null, kind);
+ notifyWidgetBridgeChanged(null, null, kind);
+ }
+
public JSONObject getPluginVersion() throws JSONException {
String versionName = "android";
try {
@@ -199,13 +204,25 @@ public JSONObject getPluginVersion() throws JSONException {
}
private void notifyStoreChanged(final String activityId) {
- final Intent intent = new Intent(CapgoWidgetKitConstants.ACTION_TEMPLATE_STORE_CHANGED)
- .setPackage(context.getPackageName())
- .putExtra(CapgoWidgetKitConstants.EXTRA_ACTIVITY_ID, activityId);
+ notifyStoreChanged(activityId, null);
+ }
+
+ private void notifyStoreChanged(final String activityId, final String kind) {
+ final Intent intent = new Intent(CapgoWidgetKitConstants.ACTION_TEMPLATE_STORE_CHANGED).setPackage(context.getPackageName());
+ if (activityId != null) {
+ intent.putExtra(CapgoWidgetKitConstants.EXTRA_ACTIVITY_ID, activityId);
+ }
+ if (kind != null) {
+ intent.putExtra(CapgoWidgetKitConstants.EXTRA_WIDGET_KIND, kind);
+ }
context.sendBroadcast(intent);
}
private void notifyWidgetBridgeChanged(final String widgetId, final String messageId) {
+ notifyWidgetBridgeChanged(widgetId, messageId, null);
+ }
+
+ private void notifyWidgetBridgeChanged(final String widgetId, final String messageId, final String kind) {
final Intent intent = new Intent(CapgoWidgetKitConstants.ACTION_NATIVE_WIDGET_BRIDGE_CHANGED).setPackage(context.getPackageName());
if (widgetId != null) {
intent.putExtra(CapgoWidgetKitConstants.EXTRA_WIDGET_ID, widgetId);
@@ -213,6 +230,9 @@ private void notifyWidgetBridgeChanged(final String widgetId, final String messa
if (messageId != null) {
intent.putExtra(CapgoWidgetKitConstants.EXTRA_MESSAGE_ID, messageId);
}
+ if (kind != null) {
+ intent.putExtra(CapgoWidgetKitConstants.EXTRA_WIDGET_KIND, kind);
+ }
context.sendBroadcast(intent);
}
}
diff --git a/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitConstants.java b/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitConstants.java
index 648f439..6340119 100644
--- a/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitConstants.java
+++ b/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitConstants.java
@@ -10,6 +10,7 @@ public final class CapgoWidgetKitConstants {
public static final String EXTRA_ACTION_ID = "actionId";
public static final String EXTRA_SOURCE_ID = "sourceId";
public static final String EXTRA_PAYLOAD_JSON = "payloadJson";
+ public static final String EXTRA_WIDGET_KIND = "widgetKind";
public static final String EXTRA_WIDGET_ID = "widgetId";
public static final String EXTRA_MESSAGE_ID = "messageId";
public static final String ACTIVITY_IDS_KEY = "activityIds";
diff --git a/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitPlugin.java b/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitPlugin.java
index 1ee427e..c6a7421 100644
--- a/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitPlugin.java
+++ b/android/src/main/java/app/capgo/widgetkit/CapgoWidgetKitPlugin.java
@@ -32,6 +32,15 @@ public void areActivitiesSupported(final PluginCall call) {
@PluginMethod
public void startTemplateActivity(final PluginCall call) {
+ startTemplateRecord(call);
+ }
+
+ @PluginMethod
+ public void startTemplateWidget(final PluginCall call) {
+ startTemplateRecord(call);
+ }
+
+ private void startTemplateRecord(final PluginCall call) {
final JSObject definition = call.getObject("definition");
final JSObject state = call.getObject("state");
@@ -347,6 +356,12 @@ public void completeWidgetMessage(final PluginCall call) {
}
}
+ @PluginMethod
+ public void reloadWidgets(final PluginCall call) {
+ implementation.reloadWidgets(call.getString("kind"));
+ call.resolve();
+ }
+
@PluginMethod
public void getPluginVersion(final PluginCall call) {
try {
diff --git a/android/src/main/java/app/capgo/widgetkit/TemplateRuntime.java b/android/src/main/java/app/capgo/widgetkit/TemplateRuntime.java
index 723c39d..f477f40 100644
--- a/android/src/main/java/app/capgo/widgetkit/TemplateRuntime.java
+++ b/android/src/main/java/app/capgo/widgetkit/TemplateRuntime.java
@@ -167,7 +167,7 @@ static JSONArray acknowledgeEvents(final JSONArray events, final String activity
static JSONObject resolveSurface(final JSONObject record, final String surface, final long nowMs) throws JSONException {
final JSONObject layouts = record.getJSONObject("definition").getJSONObject("layouts");
- final JSONObject layout = layouts.optJSONObject(surface);
+ final JSONObject layout = layoutForSurface(layouts, surface);
if (layout == null) {
return null;
}
@@ -431,7 +431,7 @@ private static JSONArray frameIdsForMutation(final JSONObject activity, final JS
return new JSONArray();
}
- final JSONObject layout = activity.getJSONObject("definition").getJSONObject("layouts").optJSONObject(surface);
+ final JSONObject layout = layoutForSurface(activity.getJSONObject("definition").getJSONObject("layouts"), surface);
final JSONArray frames = layout != null ? TemplateJsonUtils.arrayOrEmpty(layout, "frames") : new JSONArray();
final JSONArray frameIds = new JSONArray();
for (int index = 0; index < frames.length(); index += 1) {
@@ -443,6 +443,14 @@ private static JSONArray frameIdsForMutation(final JSONObject activity, final JS
return frameIds;
}
+ private static JSONObject layoutForSurface(final JSONObject layouts, final String surface) {
+ final JSONObject layout = layouts.optJSONObject(surface);
+ if (layout != null) {
+ return layout;
+ }
+ return "homeScreen".equals(surface) ? layouts.optJSONObject("lockScreen") : null;
+ }
+
private static int indexOfString(final JSONArray values, final String target) {
for (int index = 0; index < values.length(); index += 1) {
if (target.equals(values.optString(index))) {
diff --git a/example-app/android/app/src/main/java/app/capgo/widgetkit/exampleapp/TemplateSampleWidgetProvider.java b/example-app/android/app/src/main/java/app/capgo/widgetkit/exampleapp/TemplateSampleWidgetProvider.java
index 8417a13..63d9bcb 100644
--- a/example-app/android/app/src/main/java/app/capgo/widgetkit/exampleapp/TemplateSampleWidgetProvider.java
+++ b/example-app/android/app/src/main/java/app/capgo/widgetkit/exampleapp/TemplateSampleWidgetProvider.java
@@ -18,7 +18,7 @@
public class TemplateSampleWidgetProvider extends AppWidgetProvider {
- private static final String SURFACE_LOCK_SCREEN = "lockScreen";
+ private static final String SURFACE_HOME_SCREEN = "homeScreen";
private static final int PREVIEW_WIDTH_PX = 720;
private static final int PREVIEW_HEIGHT_PX = 360;
@@ -65,7 +65,7 @@ private RemoteViews buildViews(final Context context) {
return views;
}
- final JSONObject layout = bridge.resolveLayout(activity.optString("activityId"), SURFACE_LOCK_SCREEN);
+ final JSONObject layout = bridge.resolveLayout(activity.optString("activityId"), SURFACE_HOME_SCREEN);
if (layout == null) {
renderEmptyState(views);
return views;
diff --git a/example-app/ios/App/ExampleWidgetExtension/ExampleWidgetBundle.swift b/example-app/ios/App/ExampleWidgetExtension/ExampleWidgetBundle.swift
index 142a2a0..17f32b1 100644
--- a/example-app/ios/App/ExampleWidgetExtension/ExampleWidgetBundle.swift
+++ b/example-app/ios/App/ExampleWidgetExtension/ExampleWidgetBundle.swift
@@ -6,12 +6,31 @@ import CapgoWidgetKitPlugin
@main
struct ExampleWidgetBundle: WidgetBundle {
var body: some Widget {
+ ExampleTemplateHomeWidget()
+
if #available(iOS 16.2, *) {
ExampleTemplateLiveActivityWidget()
}
}
}
+struct ExampleTemplateHomeWidget: Widget {
+ private let kind = "ExampleTemplateHomeWidget"
+
+ var body: some WidgetConfiguration {
+ StaticConfiguration(kind: kind, provider: CapgoTemplateWidgetTimelineProvider()) { entry in
+ CapgoTemplateHomeWidgetView(entry: entry) { layout in
+ ExampleTemplateSurfaceCard(layout: layout)
+ } placeholder: {
+ ExampleTemplateSurfaceCard(layout: nil)
+ }
+ }
+ .configurationDisplayName("Capgo Template")
+ .description("Home Screen widget rendered from the shared Capgo SVG template store.")
+ .supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
+ }
+}
+
@available(iOS 16.2, *)
struct ExampleTemplateLiveActivityWidget: Widget {
private let bridge = CapgoTemplateWidgetBridge()
diff --git a/example-app/src/main.js b/example-app/src/main.js
index 0069ae1..4d60093 100644
--- a/example-app/src/main.js
+++ b/example-app/src/main.js
@@ -281,11 +281,11 @@ const renderPreview = () => {
return;
}
- const resolvedLayout = resolveTemplateSurface(currentActivity, 'lockScreen');
+ const resolvedLayout = resolveTemplateSurface(currentActivity, 'homeScreen');
if (!resolvedLayout) {
preview.innerHTML = `
The lock screen surface is missing from this activity.
+The home screen surface is missing from this activity.