1import { requireOptionalNativeModule } from "expo";
2import * as Linking from "expo-linking";
3import type { SubscriptionUsageSnapshot } from "./subscriptionUsageSnapshot";
4
5let tapUrl: string | undefined;
6let listening = false;
7
8export async function publishSubscriptionUsage(snapshot: SubscriptionUsageSnapshot) {
9 if (!requireOptionalNativeModule("ExpoWidgets")) return;
10 const [{ default: widget }, { addUserInteractionListener }] = await Promise.all([
11 import("./SubscriptionUsage"),
12 import("expo-widgets"),
13 ]);
14 tapUrl = snapshot.url;
15 if (!listening) {
16 // expo-widgets has no Android counterpart to widgetURL: the card is a
17 // button whose tap is delivered to this process, so opening the app needs
18 // a live JS runtime.
19 listening = true;
20 addUserInteractionListener((event) => {
21 if (event.source === "SubscriptionUsage" && tapUrl) void Linking.openURL(tapUrl);
22 });
23 }
24 widget.updateSnapshot(snapshot);
25 // Android has no timeline; an alarm re-renders the stored snapshot at each deadline.
26 requireOptionalNativeModule<{ schedule: (name: string, deadlines: number[]) => void }>(
27 "T3WidgetExpiry",
28 )?.schedule(
29 "SubscriptionUsage",
30 snapshot.providers.map((provider) => provider.expiresAt).filter((at) => at > 0),
31 );
32}