expo-live-activity 0.4.2 → 0.4.3-alpha1

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/Package.swift ADDED
@@ -0,0 +1,16 @@
1
+ // swift-tools-version: 5.7
2
+
3
+ import PackageDescription
4
+
5
+ let package = Package(
6
+ name: "ExpoLiveActivity",
7
+ platforms: [.iOS(.v16)],
8
+ products: [.library(name: "ExpoLiveActivity", targets: ["ExpoLiveActivity"])],
9
+ targets: [
10
+ .target(
11
+ name: "ExpoLiveActivity",
12
+ path: "ios-files",
13
+ exclude: ["LiveActivityWidgetBundle.swift"]
14
+ ),
15
+ ]
16
+ )
package/README.md CHANGED
@@ -44,7 +44,7 @@ The module comes with a built-in config plugin that creates a target in iOS with
44
44
  }
45
45
  }
46
46
  ```
47
- If you want to update Live Acitivity with push notifications you can add option `"enablePushNotifications": true`:
47
+ If you want to update Live Activity with push notifications you can add option `"enablePushNotifications": true`:
48
48
  ```json
49
49
  {
50
50
  "expo": {
package/build/index.d.ts CHANGED
@@ -59,7 +59,7 @@ export type ActivityTokenReceivedEvent = {
59
59
  activityPushToken: string;
60
60
  };
61
61
  export type ActivityPushToStartTokenReceivedEvent = {
62
- activityPushToStartToken: string;
62
+ activityPushToStartToken: string | null;
63
63
  };
64
64
  type ActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended';
65
65
  export type ActivityUpdateEvent = {
@@ -88,8 +88,19 @@ export declare function stopActivity(id: string, state: LiveActivityState): any;
88
88
  * @param {LiveActivityState} state The updated state for the live activity.
89
89
  */
90
90
  export declare function updateActivity(id: string, state: LiveActivityState): any;
91
- export declare function addActivityTokenListener(listener: (event: ActivityTokenReceivedEvent) => void): Voidable<EventSubscription>;
91
+ /**
92
+ * @param {function} updateTokenListener The listener function that will be called when an update token is received.
93
+ */
94
+ export declare function addActivityTokenListener(updateTokenListener: (event: ActivityTokenReceivedEvent) => void): Voidable<EventSubscription>;
95
+ /**
96
+ * Adds a listener that is called when a push-to-start token is received. Supported only on iOS > 17.2.
97
+ * On earlier iOS versions, the listener will return null as a token.
98
+ * @param {function} listener The listener function that will be called when the observer starts and then when a push-to-start token is received.
99
+ */
92
100
  export declare function addActivityPushToStartTokenListener(listener: (event: ActivityPushToStartTokenReceivedEvent) => void): Voidable<EventSubscription>;
93
- export declare function addActivityUpdatesListener(listener: (event: ActivityUpdateEvent) => void): Voidable<EventSubscription>;
101
+ /**
102
+ * @param {function} statusListener The listener function that will be called when an activity status changes.
103
+ */
104
+ export declare function addActivityUpdatesListener(statusListener: (event: ActivityUpdateEvent) => void): Voidable<EventSubscription>;
94
105
  export {};
95
106
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAKrD,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAE3B,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,CAAA;AAE3D,KAAK,eAAe,GAChB;IACE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,GACD;IACE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAEL,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,eAAe,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,OAAO,GACf;IACE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GACD,MAAM,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,CAAA;AAE7E,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEpD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAA;AAClD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,cAAc,CAAA;IACrB,MAAM,EAAE,cAAc,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAA;AAElF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,sBAAsB,CAAA;IAClC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,qCAAqC,GAAG;IAClD,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAA;CACxC,CAAA;AAED,KAAK,aAAa,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAE3E,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,aAAa,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAA;IAC7D,0BAA0B,EAAE,CAAC,MAAM,EAAE,qCAAqC,KAAK,IAAI,CAAA;IACnF,aAAa,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAA;CACrD,CAAA;AA8DD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAErG;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,OAEhE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,OAElE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,mBAAmB,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,GAC/D,QAAQ,CAAC,iBAAiB,CAAC,CAG7B;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,CAAC,KAAK,EAAE,qCAAqC,KAAK,IAAI,GAC/D,QAAQ,CAAC,iBAAiB,CAAC,CAG7B;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GACnD,QAAQ,CAAC,iBAAiB,CAAC,CAG7B"}
package/build/index.js CHANGED
@@ -74,16 +74,27 @@ export function updateActivity(id, state) {
74
74
  if (assertIOS('updateActivity'))
75
75
  return ExpoLiveActivityModule.updateActivity(id, state);
76
76
  }
77
- export function addActivityTokenListener(listener) {
77
+ /**
78
+ * @param {function} updateTokenListener The listener function that will be called when an update token is received.
79
+ */
80
+ export function addActivityTokenListener(updateTokenListener) {
78
81
  if (assertIOS('addActivityTokenListener'))
79
- return ExpoLiveActivityModule.addListener('onTokenReceived', listener);
82
+ return ExpoLiveActivityModule.addListener('onTokenReceived', updateTokenListener);
80
83
  }
84
+ /**
85
+ * Adds a listener that is called when a push-to-start token is received. Supported only on iOS > 17.2.
86
+ * On earlier iOS versions, the listener will return null as a token.
87
+ * @param {function} listener The listener function that will be called when the observer starts and then when a push-to-start token is received.
88
+ */
81
89
  export function addActivityPushToStartTokenListener(listener) {
82
90
  if (assertIOS('addActivityPushToStartTokenListener'))
83
91
  return ExpoLiveActivityModule.addListener('onPushToStartTokenReceived', listener);
84
92
  }
85
- export function addActivityUpdatesListener(listener) {
93
+ /**
94
+ * @param {function} statusListener The listener function that will be called when an activity status changes.
95
+ */
96
+ export function addActivityUpdatesListener(statusListener) {
86
97
  if (assertIOS('addActivityUpdatesListener'))
87
- return ExpoLiveActivityModule.addListener('onStateChange', listener);
98
+ return ExpoLiveActivityModule.addListener('onStateChange', statusListener);
88
99
  }
89
100
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventSubscription } from 'expo-modules-core'\nimport { Platform } from 'react-native'\n\nimport ExpoLiveActivityModule from './ExpoLiveActivityModule'\n\ntype Voidable<T> = T | void\n\nexport type DynamicIslandTimerType = 'circular' | 'digital'\n\ntype ProgressBarType =\n | {\n date?: number\n progress?: undefined\n }\n | {\n date?: undefined\n progress?: number\n }\n\nexport type LiveActivityState = {\n title: string\n subtitle?: string\n progressBar?: ProgressBarType\n imageName?: string\n dynamicIslandImageName?: string\n}\n\nexport type NativeLiveActivityState = {\n title: string\n subtitle?: string\n date?: number\n progress?: number\n imageName?: string\n dynamicIslandImageName?: string\n}\n\nexport type Padding =\n | {\n top?: number\n bottom?: number\n left?: number\n right?: number\n vertical?: number\n horizontal?: number\n }\n | number\n\nexport type ImagePosition = 'left' | 'right' | 'leftStretch' | 'rightStretch'\n\nexport type ImageAlign = 'top' | 'center' | 'bottom'\n\nexport type ImageDimension = number | `${number}%`\nexport type ImageSize = {\n width: ImageDimension\n height: ImageDimension\n}\n\nexport type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n\nexport type LiveActivityConfig = {\n backgroundColor?: string\n titleColor?: string\n subtitleColor?: string\n progressViewTint?: string\n progressViewLabelColor?: string\n deepLinkUrl?: string\n timerType?: DynamicIslandTimerType\n padding?: Padding\n imagePosition?: ImagePosition\n imageAlign?: ImageAlign\n imageSize?: ImageSize\n contentFit?: ImageContentFit\n}\n\nexport type ActivityTokenReceivedEvent = {\n activityID: string\n activityName: string\n activityPushToken: string\n}\n\nexport type ActivityPushToStartTokenReceivedEvent = {\n activityPushToStartToken: string\n}\n\ntype ActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended'\n\nexport type ActivityUpdateEvent = {\n activityID: string\n activityName: string\n activityState: ActivityState\n}\n\nexport type LiveActivityModuleEvents = {\n onTokenReceived: (params: ActivityTokenReceivedEvent) => void\n onPushToStartTokenReceived: (params: ActivityPushToStartTokenReceivedEvent) => void\n onStateChange: (params: ActivityUpdateEvent) => void\n}\n\nfunction assertIOS(name: string) {\n const isIOS = Platform.OS === 'ios'\n\n if (!isIOS) console.error(`${name} is only available on iOS`)\n\n return isIOS\n}\n\nfunction normalizeConfig(config?: LiveActivityConfig) {\n if (config === undefined) return config\n\n const { padding, imageSize, ...base } = config\n type NormalizedConfig = LiveActivityConfig & {\n paddingDetails?: Padding\n imageWidth?: number\n imageHeight?: number\n imageWidthPercent?: number\n imageHeightPercent?: number\n }\n const normalized: NormalizedConfig = { ...base }\n\n // Normalize padding: keep number in padding, object in paddingDetails\n if (typeof padding === 'number') {\n normalized.padding = padding\n } else if (typeof padding === 'object') {\n normalized.paddingDetails = padding\n }\n\n // Normalize imageSize: object with width/height each a number (points) or percent string like '50%'\n if (imageSize) {\n const regExp = /^(100(?:\\.0+)?|\\d{1,2}(?:\\.\\d+)?)%$/ // Matches 0.0% to 100.0%\n\n const { width, height } = imageSize\n\n if (typeof width === 'number') {\n normalized.imageWidth = width\n } else if (typeof width === 'string') {\n const match = width.trim().match(regExp)\n if (match) {\n normalized.imageWidthPercent = Number(match[1])\n } else {\n throw new Error('imageSize.width percent string must be in format \"0%\" to \"100%\"')\n }\n }\n\n if (typeof height === 'number') {\n normalized.imageHeight = height\n } else if (typeof height === 'string') {\n const match = height.trim().match(regExp)\n if (match) {\n normalized.imageHeightPercent = Number(match[1])\n } else {\n throw new Error('imageSize.height percent string must be in format \"0%\" to \"100%\"')\n }\n }\n }\n\n return normalized\n}\n\n/**\n * @param {LiveActivityState} state The state for the live activity.\n * @param {LiveActivityConfig} config Live activity config object.\n * @returns {string} The identifier of the started activity or undefined if creating live activity failed.\n */\nexport function startActivity(state: LiveActivityState, config?: LiveActivityConfig): Voidable<string> {\n if (assertIOS('startActivity')) return ExpoLiveActivityModule.startActivity(state, normalizeConfig(config))\n}\n\n/**\n * @param {string} id The identifier of the activity to stop.\n * @param {LiveActivityState} state The updated state for the live activity.\n */\nexport function stopActivity(id: string, state: LiveActivityState) {\n if (assertIOS('stopActivity')) return ExpoLiveActivityModule.stopActivity(id, state)\n}\n\n/**\n * @param {string} id The identifier of the activity to update.\n * @param {LiveActivityState} state The updated state for the live activity.\n */\nexport function updateActivity(id: string, state: LiveActivityState) {\n if (assertIOS('updateActivity')) return ExpoLiveActivityModule.updateActivity(id, state)\n}\n\nexport function addActivityTokenListener(\n listener: (event: ActivityTokenReceivedEvent) => void\n): Voidable<EventSubscription> {\n if (assertIOS('addActivityTokenListener')) return ExpoLiveActivityModule.addListener('onTokenReceived', listener)\n}\n\nexport function addActivityPushToStartTokenListener(\n listener: (event: ActivityPushToStartTokenReceivedEvent) => void\n): Voidable<EventSubscription> {\n if (assertIOS('addActivityPushToStartTokenListener'))\n return ExpoLiveActivityModule.addListener('onPushToStartTokenReceived', listener)\n}\n\nexport function addActivityUpdatesListener(\n listener: (event: ActivityUpdateEvent) => void\n): Voidable<EventSubscription> {\n if (assertIOS('addActivityUpdatesListener')) return ExpoLiveActivityModule.addListener('onStateChange', listener)\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventSubscription } from 'expo-modules-core'\nimport { Platform } from 'react-native'\n\nimport ExpoLiveActivityModule from './ExpoLiveActivityModule'\n\ntype Voidable<T> = T | void\n\nexport type DynamicIslandTimerType = 'circular' | 'digital'\n\ntype ProgressBarType =\n | {\n date?: number\n progress?: undefined\n }\n | {\n date?: undefined\n progress?: number\n }\n\nexport type LiveActivityState = {\n title: string\n subtitle?: string\n progressBar?: ProgressBarType\n imageName?: string\n dynamicIslandImageName?: string\n}\n\nexport type NativeLiveActivityState = {\n title: string\n subtitle?: string\n date?: number\n progress?: number\n imageName?: string\n dynamicIslandImageName?: string\n}\n\nexport type Padding =\n | {\n top?: number\n bottom?: number\n left?: number\n right?: number\n vertical?: number\n horizontal?: number\n }\n | number\n\nexport type ImagePosition = 'left' | 'right' | 'leftStretch' | 'rightStretch'\n\nexport type ImageAlign = 'top' | 'center' | 'bottom'\n\nexport type ImageDimension = number | `${number}%`\nexport type ImageSize = {\n width: ImageDimension\n height: ImageDimension\n}\n\nexport type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n\nexport type LiveActivityConfig = {\n backgroundColor?: string\n titleColor?: string\n subtitleColor?: string\n progressViewTint?: string\n progressViewLabelColor?: string\n deepLinkUrl?: string\n timerType?: DynamicIslandTimerType\n padding?: Padding\n imagePosition?: ImagePosition\n imageAlign?: ImageAlign\n imageSize?: ImageSize\n contentFit?: ImageContentFit\n}\n\nexport type ActivityTokenReceivedEvent = {\n activityID: string\n activityName: string\n activityPushToken: string\n}\n\nexport type ActivityPushToStartTokenReceivedEvent = {\n activityPushToStartToken: string | null\n}\n\ntype ActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended'\n\nexport type ActivityUpdateEvent = {\n activityID: string\n activityName: string\n activityState: ActivityState\n}\n\nexport type LiveActivityModuleEvents = {\n onTokenReceived: (params: ActivityTokenReceivedEvent) => void\n onPushToStartTokenReceived: (params: ActivityPushToStartTokenReceivedEvent) => void\n onStateChange: (params: ActivityUpdateEvent) => void\n}\n\nfunction assertIOS(name: string) {\n const isIOS = Platform.OS === 'ios'\n\n if (!isIOS) console.error(`${name} is only available on iOS`)\n\n return isIOS\n}\n\nfunction normalizeConfig(config?: LiveActivityConfig) {\n if (config === undefined) return config\n\n const { padding, imageSize, ...base } = config\n type NormalizedConfig = LiveActivityConfig & {\n paddingDetails?: Padding\n imageWidth?: number\n imageHeight?: number\n imageWidthPercent?: number\n imageHeightPercent?: number\n }\n const normalized: NormalizedConfig = { ...base }\n\n // Normalize padding: keep number in padding, object in paddingDetails\n if (typeof padding === 'number') {\n normalized.padding = padding\n } else if (typeof padding === 'object') {\n normalized.paddingDetails = padding\n }\n\n // Normalize imageSize: object with width/height each a number (points) or percent string like '50%'\n if (imageSize) {\n const regExp = /^(100(?:\\.0+)?|\\d{1,2}(?:\\.\\d+)?)%$/ // Matches 0.0% to 100.0%\n\n const { width, height } = imageSize\n\n if (typeof width === 'number') {\n normalized.imageWidth = width\n } else if (typeof width === 'string') {\n const match = width.trim().match(regExp)\n if (match) {\n normalized.imageWidthPercent = Number(match[1])\n } else {\n throw new Error('imageSize.width percent string must be in format \"0%\" to \"100%\"')\n }\n }\n\n if (typeof height === 'number') {\n normalized.imageHeight = height\n } else if (typeof height === 'string') {\n const match = height.trim().match(regExp)\n if (match) {\n normalized.imageHeightPercent = Number(match[1])\n } else {\n throw new Error('imageSize.height percent string must be in format \"0%\" to \"100%\"')\n }\n }\n }\n\n return normalized\n}\n\n/**\n * @param {LiveActivityState} state The state for the live activity.\n * @param {LiveActivityConfig} config Live activity config object.\n * @returns {string} The identifier of the started activity or undefined if creating live activity failed.\n */\nexport function startActivity(state: LiveActivityState, config?: LiveActivityConfig): Voidable<string> {\n if (assertIOS('startActivity')) return ExpoLiveActivityModule.startActivity(state, normalizeConfig(config))\n}\n\n/**\n * @param {string} id The identifier of the activity to stop.\n * @param {LiveActivityState} state The updated state for the live activity.\n */\nexport function stopActivity(id: string, state: LiveActivityState) {\n if (assertIOS('stopActivity')) return ExpoLiveActivityModule.stopActivity(id, state)\n}\n\n/**\n * @param {string} id The identifier of the activity to update.\n * @param {LiveActivityState} state The updated state for the live activity.\n */\nexport function updateActivity(id: string, state: LiveActivityState) {\n if (assertIOS('updateActivity')) return ExpoLiveActivityModule.updateActivity(id, state)\n}\n\n/**\n * @param {function} updateTokenListener The listener function that will be called when an update token is received.\n */\nexport function addActivityTokenListener(\n updateTokenListener: (event: ActivityTokenReceivedEvent) => void\n): Voidable<EventSubscription> {\n if (assertIOS('addActivityTokenListener'))\n return ExpoLiveActivityModule.addListener('onTokenReceived', updateTokenListener)\n}\n\n/**\n * Adds a listener that is called when a push-to-start token is received. Supported only on iOS > 17.2.\n * On earlier iOS versions, the listener will return null as a token.\n * @param {function} listener The listener function that will be called when the observer starts and then when a push-to-start token is received.\n */\nexport function addActivityPushToStartTokenListener(\n listener: (event: ActivityPushToStartTokenReceivedEvent) => void\n): Voidable<EventSubscription> {\n if (assertIOS('addActivityPushToStartTokenListener'))\n return ExpoLiveActivityModule.addListener('onPushToStartTokenReceived', listener)\n}\n\n/**\n * @param {function} statusListener The listener function that will be called when an activity status changes.\n */\nexport function addActivityUpdatesListener(\n statusListener: (event: ActivityUpdateEvent) => void\n): Voidable<EventSubscription> {\n if (assertIOS('addActivityUpdatesListener'))\n return ExpoLiveActivityModule.addListener('onStateChange', statusListener)\n}\n"]}
@@ -141,6 +141,10 @@ public class ExpoLiveActivityModule: Module {
141
141
  private func observePushToStartToken() {
142
142
  guard #available(iOS 17.2, *), ActivityAuthorizationInfo().areActivitiesEnabled else { return }
143
143
 
144
+ if let initialToken = (Activity<LiveActivityAttributes>.pushToStartToken?.reduce("") { $0 + String(format: "%02x", $1) }) {
145
+ sendPushToStartToken(activityPushToStartToken: initialToken)
146
+ }
147
+
144
148
  print("Observing push to start token updates...")
145
149
  Task {
146
150
  for await data in Activity<LiveActivityAttributes>.pushToStartTokenUpdates {
@@ -196,11 +200,14 @@ public class ExpoLiveActivityModule: Module {
196
200
  public func definition() -> ModuleDefinition {
197
201
  Name("ExpoLiveActivity")
198
202
 
199
- OnCreate {
203
+ OnStartObserving("onTokenReceived") {
204
+ observeLiveActivityUpdates()
205
+ }
206
+
207
+ OnStartObserving("onPushToStartTokenReceived") {
200
208
  if pushNotificationsEnabled {
201
209
  observePushToStartToken()
202
210
  }
203
- observeLiveActivityUpdates()
204
211
  }
205
212
 
206
213
  Events("onTokenReceived", "onPushToStartTokenReceived", "onStateChange")
@@ -43,7 +43,7 @@ import WidgetKit
43
43
  attributes.progressViewTint.map { Color(hex: $0) }
44
44
  }
45
45
 
46
- private var imageAlignment: Alignment {
46
+ private var imageVerticalAlignment: VerticalAlignment {
47
47
  switch attributes.imageAlign {
48
48
  case "center":
49
49
  return .center
@@ -54,7 +54,7 @@ import WidgetKit
54
54
  }
55
55
  }
56
56
 
57
- private func alignedImage(imageName: String) -> some View {
57
+ private func alignedImage(imageName: String, horizontalAlignment: HorizontalAlignment) -> some View {
58
58
  let defaultHeight: CGFloat = 64
59
59
  let defaultWidth: CGFloat = 64
60
60
  let containerHeight = imageContainerSize?.height
@@ -94,7 +94,7 @@ import WidgetKit
94
94
 
95
95
  return ZStack(alignment: .center) {
96
96
  Group {
97
- let fit = attributes.contentFit ?? "cover"
97
+ let fit = attributes.contentFit ?? "contain"
98
98
  switch fit {
99
99
  case "contain":
100
100
  Image.dynamic(assetNameOrPath: imageName).resizable().scaledToFit().frame(width: computedWidth, height: computedHeight)
@@ -135,7 +135,11 @@ import WidgetKit
135
135
  }
136
136
  }
137
137
  }
138
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: imageAlignment)
138
+ .frame(
139
+ maxWidth: .infinity,
140
+ maxHeight: .infinity,
141
+ alignment: Alignment(horizontal: horizontalAlignment, vertical: imageVerticalAlignment)
142
+ )
139
143
  .background(
140
144
  GeometryReader { proxy in
141
145
  Color.clear
@@ -191,7 +195,7 @@ import WidgetKit
191
195
  HStack(alignment: .center) {
192
196
  if hasImage, isLeftImage {
193
197
  if let imageName = contentState.imageName {
194
- alignedImage(imageName: imageName)
198
+ alignedImage(imageName: imageName, horizontalAlignment: .leading)
195
199
  }
196
200
  }
197
201
 
@@ -221,9 +225,8 @@ import WidgetKit
221
225
  }.layoutPriority(1)
222
226
 
223
227
  if hasImage, !isLeftImage { // right side (default)
224
- Spacer()
225
228
  if let imageName = contentState.imageName {
226
- alignedImage(imageName: imageName)
229
+ alignedImage(imageName: imageName, horizontalAlignment: .trailing)
227
230
  }
228
231
  }
229
232
  }
@@ -2,14 +2,30 @@ import ActivityKit
2
2
  import SwiftUI
3
3
  import WidgetKit
4
4
 
5
- struct LiveActivityAttributes: ActivityAttributes {
6
- struct ContentState: Codable, Hashable {
5
+ public struct LiveActivityAttributes: ActivityAttributes {
6
+ public struct ContentState: Codable, Hashable {
7
7
  var title: String
8
8
  var subtitle: String?
9
9
  var timerEndDateInMilliseconds: Double?
10
10
  var progress: Double?
11
11
  var imageName: String?
12
12
  var dynamicIslandImageName: String?
13
+
14
+ public init(
15
+ title: String,
16
+ subtitle: String? = nil,
17
+ timerEndDateInMilliseconds: Double? = nil,
18
+ progress: Double? = nil,
19
+ imageName: String? = nil,
20
+ dynamicIslandImageName: String? = nil
21
+ ) {
22
+ self.title = title
23
+ self.subtitle = subtitle
24
+ self.timerEndDateInMilliseconds = timerEndDateInMilliseconds
25
+ self.progress = progress
26
+ self.imageName = imageName
27
+ self.dynamicIslandImageName = dynamicIslandImageName
28
+ }
13
29
  }
14
30
 
15
31
  var name: String
@@ -30,23 +46,78 @@ struct LiveActivityAttributes: ActivityAttributes {
30
46
  var imageAlign: String?
31
47
  var contentFit: String?
32
48
 
33
- enum DynamicIslandTimerType: String, Codable {
49
+ public init(
50
+ name: String,
51
+ backgroundColor: String? = nil,
52
+ titleColor: String? = nil,
53
+ subtitleColor: String? = nil,
54
+ progressViewTint: String? = nil,
55
+ progressViewLabelColor: String? = nil,
56
+ deepLinkUrl: String? = nil,
57
+ timerType: DynamicIslandTimerType? = nil,
58
+ padding: Int? = nil,
59
+ paddingDetails: PaddingDetails? = nil,
60
+ imagePosition: String? = nil,
61
+ imageWidth: Int? = nil,
62
+ imageHeight: Int? = nil,
63
+ imageWidthPercent: Double? = nil,
64
+ imageHeightPercent: Double? = nil,
65
+ imageAlign: String? = nil,
66
+ contentFit: String? = nil
67
+ ) {
68
+ self.name = name
69
+ self.backgroundColor = backgroundColor
70
+ self.titleColor = titleColor
71
+ self.subtitleColor = subtitleColor
72
+ self.progressViewTint = progressViewTint
73
+ self.progressViewLabelColor = progressViewLabelColor
74
+ self.deepLinkUrl = deepLinkUrl
75
+ self.timerType = timerType
76
+ self.padding = padding
77
+ self.paddingDetails = paddingDetails
78
+ self.imagePosition = imagePosition
79
+ self.imageWidth = imageWidth
80
+ self.imageHeight = imageHeight
81
+ self.imageWidthPercent = imageWidthPercent
82
+ self.imageHeightPercent = imageHeightPercent
83
+ self.imageAlign = imageAlign
84
+ self.contentFit = contentFit
85
+ }
86
+
87
+ public enum DynamicIslandTimerType: String, Codable {
34
88
  case circular
35
89
  case digital
36
90
  }
37
91
 
38
- struct PaddingDetails: Codable, Hashable {
92
+ public struct PaddingDetails: Codable, Hashable {
39
93
  var top: Int?
40
94
  var bottom: Int?
41
95
  var left: Int?
42
96
  var right: Int?
43
97
  var vertical: Int?
44
98
  var horizontal: Int?
99
+
100
+ public init(
101
+ top: Int? = nil,
102
+ bottom: Int? = nil,
103
+ left: Int? = nil,
104
+ right: Int? = nil,
105
+ vertical: Int? = nil,
106
+ horizontal: Int? = nil
107
+ ) {
108
+ self.top = top
109
+ self.bottom = bottom
110
+ self.left = left
111
+ self.right = right
112
+ self.vertical = vertical
113
+ self.horizontal = horizontal
114
+ }
45
115
  }
46
116
  }
47
117
 
48
- struct LiveActivityWidget: Widget {
49
- var body: some WidgetConfiguration {
118
+ @available(iOS 16.1, *)
119
+ public struct LiveActivityWidget: Widget {
120
+ public var body: some WidgetConfiguration {
50
121
  ActivityConfiguration(for: LiveActivityAttributes.self) { context in
51
122
  LiveActivityView(contentState: context.state, attributes: context.attributes)
52
123
  .activityBackgroundTint(
@@ -76,6 +147,12 @@ struct LiveActivityWidget: Widget {
76
147
  )
77
148
  .padding(.horizontal, 5)
78
149
  .applyWidgetURL(from: context.attributes.deepLinkUrl)
150
+ } else if let progress = context.state.progress {
151
+ dynamicIslandExpandedBottomProgress(
152
+ progress: progress, progressViewTint: context.attributes.progressViewTint
153
+ )
154
+ .padding(.horizontal, 5)
155
+ .applyWidgetURL(from: context.attributes.deepLinkUrl)
79
156
  }
80
157
  }
81
158
  } compactLeading: {
@@ -91,6 +168,11 @@ struct LiveActivityWidget: Widget {
91
168
  timerType: context.attributes.timerType ?? .circular,
92
169
  progressViewTint: context.attributes.progressViewTint
93
170
  ).applyWidgetURL(from: context.attributes.deepLinkUrl)
171
+ } else if let progress = context.state.progress {
172
+ compactProgress(
173
+ progress: progress,
174
+ progressViewTint: context.attributes.progressViewTint
175
+ ).applyWidgetURL(from: context.attributes.deepLinkUrl)
94
176
  }
95
177
  } minimal: {
96
178
  if let date = context.state.timerEndDateInMilliseconds {
@@ -99,11 +181,18 @@ struct LiveActivityWidget: Widget {
99
181
  timerType: context.attributes.timerType ?? .circular,
100
182
  progressViewTint: context.attributes.progressViewTint
101
183
  ).applyWidgetURL(from: context.attributes.deepLinkUrl)
184
+ } else if let progress = context.state.progress {
185
+ compactProgress(
186
+ progress: progress,
187
+ progressViewTint: context.attributes.progressViewTint
188
+ ).applyWidgetURL(from: context.attributes.deepLinkUrl)
102
189
  }
103
190
  }
104
191
  }
105
192
  }
106
193
 
194
+ public init() {}
195
+
107
196
  @ViewBuilder
108
197
  private func compactTimer(
109
198
  endDate: Double,
@@ -166,4 +255,20 @@ struct LiveActivityWidget: Widget {
166
255
  )
167
256
  .progressViewStyle(.circular)
168
257
  }
258
+
259
+ private func compactProgress(
260
+ progress: Double,
261
+ progressViewTint: String?
262
+ ) -> some View {
263
+ ProgressView(value: progress)
264
+ .progressViewStyle(.circular)
265
+ .tint(progressViewTint.map { Color(hex: $0) })
266
+ }
267
+
268
+ private func dynamicIslandExpandedBottomProgress(progress: Double, progressViewTint: String?) -> some View {
269
+ ProgressView(value: progress)
270
+ .foregroundStyle(.white)
271
+ .tint(progressViewTint.map { Color(hex: $0) })
272
+ .padding(.top, 5)
273
+ }
169
274
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-live-activity",
3
- "version": "0.4.2",
3
+ "version": "0.4.3-alpha1",
4
4
  "description": "A module for adding Live Activity to a React Native app for iOS.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -9,6 +9,7 @@
9
9
  "clean": "expo-module clean",
10
10
  "clean:plugin": "rm -rf plugin/build plugin/tsconfig.tsbuildinfo",
11
11
  "format:check": "prettier --check .",
12
+ "format:fix": "prettier --write . && swiftformat --exclude \"**/node_modules/\" .",
12
13
  "lint": "expo-module eslint",
13
14
  "lint:libOnly": "expo-module eslint --ignore-pattern 'example/*'",
14
15
  "test": "expo-module test",
@@ -16,7 +17,10 @@
16
17
  "prepublishOnly": "expo-module prepublishOnly",
17
18
  "expo-module": "expo-module",
18
19
  "open:ios": "xed example/ios",
19
- "typecheck": "tsc"
20
+ "typecheck": "tsc",
21
+ "generateTests": "node ./example/tests/scripts/generateFlows.js",
22
+ "runAllTests": "./example/tests/scripts/runAllTests.sh",
23
+ "generateTestReport": "node ./example/tests/scripts/generateReport.js"
20
24
  },
21
25
  "keywords": [
22
26
  "react-native",
@@ -47,7 +51,8 @@
47
51
  "expo": "~54.0.0",
48
52
  "expo-module-scripts": "^5.0.3",
49
53
  "prettier": "^3.6.2",
50
- "react-native": "0.81.4"
54
+ "react-native": "0.81.4",
55
+ "pdf-lib": "^1.17.1"
51
56
  },
52
57
  "peerDependencies": {
53
58
  "expo": "*",
@@ -102,7 +102,7 @@ function getWidgetFiles(targetPath) {
102
102
  const imagesXcassetsTarget = path.join(targetPath, 'Assets.xcassets');
103
103
  const files = fs.readdirSync(imageAssetsPath);
104
104
  files.forEach((file) => {
105
- if (path.extname(file).match(/\.(png|jpg|jpeg)$/)) {
105
+ if (path.extname(file).match(/\.(png|jpg|jpeg|svg)$/)) {
106
106
  const source = path.join(imageAssetsPath, file);
107
107
  const imageSetDir = path.join(imagesXcassetsTarget, `${path.basename(file, path.extname(file))}.imageset`);
108
108
  // Create the .imageset directory if it doesn't exist
@@ -78,7 +78,7 @@ export function getWidgetFiles(targetPath: string) {
78
78
  const files = fs.readdirSync(imageAssetsPath)
79
79
 
80
80
  files.forEach((file) => {
81
- if (path.extname(file).match(/\.(png|jpg|jpeg)$/)) {
81
+ if (path.extname(file).match(/\.(png|jpg|jpeg|svg)$/)) {
82
82
  const source = path.join(imageAssetsPath, file)
83
83
  const imageSetDir = path.join(imagesXcassetsTarget, `${path.basename(file, path.extname(file))}.imageset`)
84
84
 
package/src/index.ts CHANGED
@@ -79,7 +79,7 @@ export type ActivityTokenReceivedEvent = {
79
79
  }
80
80
 
81
81
  export type ActivityPushToStartTokenReceivedEvent = {
82
- activityPushToStartToken: string
82
+ activityPushToStartToken: string | null
83
83
  }
84
84
 
85
85
  type ActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended'
@@ -181,12 +181,21 @@ export function updateActivity(id: string, state: LiveActivityState) {
181
181
  if (assertIOS('updateActivity')) return ExpoLiveActivityModule.updateActivity(id, state)
182
182
  }
183
183
 
184
+ /**
185
+ * @param {function} updateTokenListener The listener function that will be called when an update token is received.
186
+ */
184
187
  export function addActivityTokenListener(
185
- listener: (event: ActivityTokenReceivedEvent) => void
188
+ updateTokenListener: (event: ActivityTokenReceivedEvent) => void
186
189
  ): Voidable<EventSubscription> {
187
- if (assertIOS('addActivityTokenListener')) return ExpoLiveActivityModule.addListener('onTokenReceived', listener)
190
+ if (assertIOS('addActivityTokenListener'))
191
+ return ExpoLiveActivityModule.addListener('onTokenReceived', updateTokenListener)
188
192
  }
189
193
 
194
+ /**
195
+ * Adds a listener that is called when a push-to-start token is received. Supported only on iOS > 17.2.
196
+ * On earlier iOS versions, the listener will return null as a token.
197
+ * @param {function} listener The listener function that will be called when the observer starts and then when a push-to-start token is received.
198
+ */
190
199
  export function addActivityPushToStartTokenListener(
191
200
  listener: (event: ActivityPushToStartTokenReceivedEvent) => void
192
201
  ): Voidable<EventSubscription> {
@@ -194,8 +203,12 @@ export function addActivityPushToStartTokenListener(
194
203
  return ExpoLiveActivityModule.addListener('onPushToStartTokenReceived', listener)
195
204
  }
196
205
 
206
+ /**
207
+ * @param {function} statusListener The listener function that will be called when an activity status changes.
208
+ */
197
209
  export function addActivityUpdatesListener(
198
- listener: (event: ActivityUpdateEvent) => void
210
+ statusListener: (event: ActivityUpdateEvent) => void
199
211
  ): Voidable<EventSubscription> {
200
- if (assertIOS('addActivityUpdatesListener')) return ExpoLiveActivityModule.addListener('onStateChange', listener)
212
+ if (assertIOS('addActivityUpdatesListener'))
213
+ return ExpoLiveActivityModule.addListener('onStateChange', statusListener)
201
214
  }