expo-live-activity 0.2.1-alpha1 → 0.2.2-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.
Files changed (72) hide show
  1. package/.prettierignore +5 -0
  2. package/.prettierrc +6 -0
  3. package/README.md +152 -56
  4. package/app.plugin.js +1 -1
  5. package/build/ExpoLiveActivityModule.d.ts.map +1 -1
  6. package/build/ExpoLiveActivityModule.js.map +1 -1
  7. package/build/index.d.ts +18 -2
  8. package/build/index.d.ts.map +1 -1
  9. package/build/index.js +21 -33
  10. package/build/index.js.map +1 -1
  11. package/eslint.config.js +42 -0
  12. package/ios/ExpoLiveActivityModule.swift +154 -91
  13. package/ios/Helpers.swift +1 -2
  14. package/ios-files/Assets.xcassets/AccentColor.colorset/Contents.json +5 -5
  15. package/ios-files/Assets.xcassets/AppIcon.appiconset/Contents.json +19 -19
  16. package/ios-files/Assets.xcassets/Contents.json +3 -3
  17. package/ios-files/Assets.xcassets/WidgetBackground.colorset/Contents.json +5 -5
  18. package/ios-files/View+applyWidgetURL.swift +15 -1
  19. package/package.json +18 -6
  20. package/plugin/build/index.d.ts +1 -1
  21. package/plugin/build/index.js +8 -3
  22. package/plugin/build/lib/getWidgetExtensionEntitlements.d.ts +6 -2
  23. package/plugin/build/lib/getWidgetExtensionEntitlements.js +1 -1
  24. package/plugin/build/lib/getWidgetFiles.js +18 -17
  25. package/plugin/build/types.d.ts +1 -1
  26. package/plugin/build/withConfig.d.ts +1 -1
  27. package/plugin/build/withPlist.d.ts +5 -0
  28. package/plugin/build/withPlist.js +25 -0
  29. package/plugin/build/withPodfile.d.ts +1 -1
  30. package/plugin/build/withPodfile.js +5 -5
  31. package/plugin/build/withPushNotifications.d.ts +1 -1
  32. package/plugin/build/withPushNotifications.js +2 -2
  33. package/plugin/build/withWidgetExtensionEntitlements.d.ts +1 -1
  34. package/plugin/build/withWidgetExtensionEntitlements.js +1 -1
  35. package/plugin/build/withXcode.d.ts +1 -1
  36. package/plugin/build/withXcode.js +8 -8
  37. package/plugin/build/xcode/addBuildPhases.d.ts +2 -2
  38. package/plugin/build/xcode/addBuildPhases.js +8 -10
  39. package/plugin/build/xcode/addPbxGroup.d.ts +2 -2
  40. package/plugin/build/xcode/addPbxGroup.js +2 -2
  41. package/plugin/build/xcode/addProductFile.d.ts +1 -1
  42. package/plugin/build/xcode/addProductFile.js +3 -3
  43. package/plugin/build/xcode/addTargetDependency.d.ts +1 -1
  44. package/plugin/build/xcode/addTargetDependency.js +5 -7
  45. package/plugin/build/xcode/addToPbxNativeTargetSection.d.ts +1 -1
  46. package/plugin/build/xcode/addToPbxNativeTargetSection.js +5 -5
  47. package/plugin/build/xcode/addToPbxProjectSection.d.ts +1 -1
  48. package/plugin/build/xcode/addToPbxProjectSection.js +1 -2
  49. package/plugin/build/xcode/addXCConfigurationList.d.ts +1 -1
  50. package/plugin/build/xcode/addXCConfigurationList.js +6 -6
  51. package/plugin/src/index.ts +19 -18
  52. package/plugin/src/lib/getWidgetExtensionEntitlements.ts +10 -13
  53. package/plugin/src/lib/getWidgetFiles.ts +70 -74
  54. package/plugin/src/types.ts +3 -5
  55. package/plugin/src/withConfig.ts +15 -15
  56. package/plugin/src/withPlist.ts +27 -0
  57. package/plugin/src/withPodfile.ts +17 -24
  58. package/plugin/src/withPushNotifications.ts +7 -11
  59. package/plugin/src/withWidgetExtensionEntitlements.ts +14 -14
  60. package/plugin/src/withXcode.ts +32 -41
  61. package/plugin/src/xcode/addBuildPhases.ts +26 -41
  62. package/plugin/src/xcode/addPbxGroup.ts +9 -16
  63. package/plugin/src/xcode/addProductFile.ts +7 -7
  64. package/plugin/src/xcode/addTargetDependency.ts +7 -12
  65. package/plugin/src/xcode/addToPbxNativeTargetSection.ts +13 -15
  66. package/plugin/src/xcode/addToPbxProjectSection.ts +7 -17
  67. package/plugin/src/xcode/addXCConfigurationList.ts +16 -16
  68. package/plugin/tsconfig.tsbuildinfo +1 -1
  69. package/scripts/update-version.sh +15 -0
  70. package/src/ExpoLiveActivityModule.ts +2 -2
  71. package/src/index.ts +69 -55
  72. package/.eslintrc.js +0 -5
@@ -0,0 +1,5 @@
1
+ /build
2
+ /example/.expo
3
+ /example/ios
4
+ /plugin/build
5
+ /.eslintrc.js
package/.prettierrc ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "printWidth": 120,
5
+ "trailingComma": "es5"
6
+ }
package/README.md CHANGED
@@ -6,68 +6,80 @@
6
6
  `expo-live-activity` is a React Native module designed for use with Expo to manage and display live activities on iOS devices exclusively. This module leverages the Live Activities feature introduced in iOS 16, allowing developers to deliver timely updates right on the lock screen.
7
7
 
8
8
  ## Features
9
+
9
10
  - Start, update, and stop live activities directly from your React Native application.
10
11
  - Easy integration with a comprehensive API.
11
12
  - Custom image support within live activities with a pre-configured path.
12
13
  - Listen and handle changes in push notification tokens associated with a live activity.
13
14
 
14
15
  ## Platform compatibility
16
+
15
17
  **Note:** This module is intended for use on **iOS devices only**. The minimal iOS version that supports Live Activities is 16.2. When methods are invoked on platforms other than iOS or on older iOS versions, they will log an error, ensuring that they are used in the correct context.
16
18
 
17
19
  ## Installation
20
+
18
21
  > [!NOTE]
19
22
  > The library isn't supported in Expo Go, to set it up correctly you need to use [Expo DevClient](https://docs.expo.dev/versions/latest/sdk/dev-client/) .
20
- To begin using `expo-live-activity`, follow the installation and configuration steps outlined below:
23
+ > To begin using `expo-live-activity`, follow the installation and configuration steps outlined below:
21
24
 
22
25
  ### Step 1: Installation
26
+
23
27
  Run the following command to add the expo-live-activity module to your project:
28
+
24
29
  ```sh
25
30
  npm install expo-live-activity
26
31
  ```
27
32
 
28
33
  ### Step 2: Config Plugin Setup
34
+
29
35
  The module comes with a built-in config plugin that creates a target in iOS with all the necessary files. The images used in live activities should be added to a pre-defined folder in your assets directory:
36
+
30
37
  1. **Add the config plugin to your app.json or app.config.js:**
31
38
  ```json
32
39
  {
33
- "expo": {
34
- "plugins": ["expo-live-activity"]
35
- }
40
+ "expo": {
41
+ "plugins": ["expo-live-activity"]
42
+ }
36
43
  }
37
44
  ```
38
45
  If you want to update Live Acitivity with push notifications you can add option `"enablePushNotifications": true`:
39
46
  ```json
40
47
  {
41
- "expo": {
42
- "plugins": [
43
- [
44
- "expo-live-activity",
45
- {
46
- "enablePushNotifications": true
47
- }
48
- ]
49
- ]
50
- }
48
+ "expo": {
49
+ "plugins": [
50
+ [
51
+ "expo-live-activity",
52
+ {
53
+ "enablePushNotifications": true
54
+ }
55
+ ]
56
+ ]
57
+ }
51
58
  }
52
59
  ```
53
60
  2. **Assets configuration:**
54
61
  Place images intended for live activities in the `assets/liveActivity` folder. The plugin manages these assets automatically.
55
62
 
56
63
  Then prebuild your app with:
64
+
57
65
  ```sh
58
- npx expo prebuild --clean
66
+ npx expo prebuild --clean
59
67
  ```
60
68
 
61
69
  ### Step 3: Usage in Your React Native App
70
+
62
71
  Import the functionalities provided by the `expo-live-activity` module in your JavaScript or TypeScript files:
72
+
63
73
  ```javascript
64
- import * as LiveActivity from "expo-live-activity";
74
+ import * as LiveActivity from 'expo-live-activity'
65
75
  ```
66
76
 
67
77
  ## API
78
+
68
79
  `expo-live-activity` module exports three primary functions to manage live activities:
69
80
 
70
81
  ### Managing Live Activities
82
+
71
83
  - **`startActivity(state: LiveActivityState, config?: LiveActivityConfig): string | undefined`**:
72
84
  Start a new live activity. Takes a `state` configuration object for initial activity state and an optional `config` object to customize appearance or behavior. It returns the `ID` of the created live activity, which should be stored for future reference. If the live activity can't be created (eg. on android or iOS lower than 16.2), it will return `undefined`.
73
85
 
@@ -78,16 +90,40 @@ import * as LiveActivity from "expo-live-activity";
78
90
  Terminate an ongoing live activity. The `state` object should contain the final state of the activity. The `activityId` indicates which activity should be stopped.
79
91
 
80
92
  ### Handling Push Notification Tokens
93
+
94
+ - **`addActivityPushToStartTokenListener(listener: (event: ActivityPushToStartTokenReceivedEvent) => void): EventSubscription | undefined`**:
95
+ Subscribe to changes in the push to start token for starting live acitivities with push notifications.
81
96
  - **`addActivityTokenListener(listener: (event: ActivityTokenReceivedEvent) => void): EventSubscription | undefined`**:
82
97
  Subscribe to changes in the push notification token associated with live activities.
83
98
 
84
-
85
99
  ### Deep linking
86
- When starting a new live activity, it's possible to pass `deepLinkUrl` field in `config` object. This can be any string that you can handle in your main app target.
100
+
101
+ When starting a new live activity, it's possible to pass `deepLinkUrl` field in `config` object. This usually should be a path to one of your screens. If you are using @react-navigation in your project, it's easiest to enable auto linking:
102
+
103
+ ```typescript
104
+ const prefix = Linking.createURL('')
105
+
106
+ export default function App() {
107
+ const url = Linking.useLinkingURL()
108
+ const linking = {
109
+ enabled: 'auto' as const,
110
+ prefixes: [prefix],
111
+ }
112
+ }
113
+
114
+ // Then start the activity with:
115
+ LiveActivity.startActivity(state, {
116
+ deepLinkUrl: '/order',
117
+ })
118
+ ```
119
+
120
+ URL scheme will be taken automatically from `scheme` field in `app.json` or fall back to `ios.bundleIdentifier`.
87
121
 
88
122
  ### State Object Structure
123
+
89
124
  The `state` object should include:
90
- ```javascript
125
+
126
+ ```typescript
91
127
  {
92
128
  title: string;
93
129
  subtitle?: string;
@@ -98,7 +134,9 @@ The `state` object should include:
98
134
  ```
99
135
 
100
136
  ### Config Object Structure
137
+
101
138
  The `config` object should include:
139
+
102
140
  ```typescript
103
141
  {
104
142
  backgroundColor?: string;
@@ -111,75 +149,133 @@ The `config` object should include:
111
149
  };
112
150
  ```
113
151
 
152
+ ### Activity updates
153
+
154
+ `LiveActivity.addActivityUpdatesListener` API allows to subscribe to changes in live activity state. This is useful for example when you want to update the live activity with new information. Handler will receive an `ActivityUpdateEvent` object which contains information about new state under `activityState` property which is of `ActivityState` type, so the possible values are: `'active'`, `'dismissed'`, `'pending'`, `'stale'` or `'ended'`. Apart from this property, the event also contains `activityId` and `activityName` which can be used to identify the live activity.
155
+
114
156
  ## Example Usage
157
+
115
158
  Managing a live activity:
116
- ```javascript
159
+
160
+ ```typescript
117
161
  const state: LiveActivity.LiveActivityState = {
118
- title: "Title",
119
- subtitle: "This is a subtitle",
162
+ title: 'Title',
163
+ subtitle: 'This is a subtitle',
120
164
  date: new Date(Date.now() + 60 * 1000 * 5).getTime(),
121
- imageName: "live_activity_image",
122
- dynamicIslandImageName: "dynamic_island_image"
123
- };
165
+ imageName: 'live_activity_image',
166
+ dynamicIslandImageName: 'dynamic_island_image',
167
+ }
124
168
 
125
169
  const config: LiveActivity.LiveActivityConfig = {
126
- backgroundColor: "#FFFFFF",
127
- titleColor: "#000000",
128
- subtitleColor: "#333333",
129
- progressViewTint: "#4CAF50",
130
- progressViewLabelColor: "#FFFFFF",
131
- deepLinkUrl: "/dashboard",
132
- timerType: "circular"
133
- };
170
+ backgroundColor: '#FFFFFF',
171
+ titleColor: '#000000',
172
+ subtitleColor: '#333333',
173
+ progressViewTint: '#4CAF50',
174
+ progressViewLabelColor: '#FFFFFF',
175
+ deepLinkUrl: '/dashboard',
176
+ timerType: 'circular',
177
+ }
134
178
 
135
- const activityId = LiveActivity.startActivity(state, config);
179
+ const activityId = LiveActivity.startActivity(state, config)
136
180
  // Store activityId for future reference
137
181
  ```
182
+
138
183
  This will initiate a live activity with the specified title, subtitle, image from your configured assets folder and a time to which there will be a countdown in a progress view.
139
184
 
140
185
  Subscribing to push token changes:
141
- ```javascript
186
+
187
+ ```typescript
142
188
  useEffect(() => {
143
- const subscription = LiveActivity.addActivityTokenListener(({
144
- activityID: newActivityID,
145
- activityPushToken: newToken
146
- }) => {
147
- // Send token to a remote server to update live activity with push notifications
148
- });
149
-
150
- return () => subscription?.remove();
151
- }, []);
189
+ const updateTokenSubscription = LiveActivity.addActivityTokenListener(
190
+ ({ activityID: newActivityID, activityName: newName, activityPushToken: newToken }) => {
191
+ // Send token to a remote server to update live activity with push notifications
192
+ }
193
+ )
194
+ const startTokenSubscription = LiveActivity.addActivityPushToStartTokenListener(
195
+ ({ activityPushToStartToken: newActivityPushToStartToken }) => {
196
+ // Send token to a remote server to start live activity with push notifications
197
+ }
198
+ )
199
+
200
+ return () => {
201
+ updateTokenSubscription?.remove()
202
+ startTokenSubscription?.remove()
203
+ }
204
+ }, [])
152
205
  ```
153
206
 
154
207
  > [!NOTE]
155
208
  > Receiving push token may not work on simulators. Make sure to use physical device when testing this functionality.
156
209
 
157
210
  ## Push notifications
158
- By default, updating live activity is possible only via API. If you want to have possibility to update live activity using push notifications, you can enable that feature by adding `"enablePushNotifications": true` in the plugin config in your `app.json` or `app.config.ts` file. Then, the notification payload should look like this:
211
+
212
+ By default, starting and updating live activity is possible only via API. If you want to have possibility to start or update live activity using push notifications, you can enable that feature by adding `"enablePushNotifications": true` in the plugin config in your `app.json` or `app.config.ts` file.
213
+
214
+ > [!NOTE]
215
+ > PushToStart works only for iOS 17.2 and higher.
216
+
217
+ Example payload for starting live activity:
159
218
 
160
219
  ```json
161
220
  {
162
- "aps":{
163
- "event":"update",
164
- "content-state":{
165
- "title":"Hello",
166
- "subtitle":"World",
167
- "timerEndDateInMilliseconds":1754064245000,
168
- "imageName": "live_activity_image",
169
- "dynamicIslandImageName": "dynamic_island_image"
170
- },
171
- "timestamp":1754063621319 // timestamp of when the push notification was sent
221
+ "aps": {
222
+ "event": "start",
223
+ "content-state": {
224
+ "title": "Live activity title!",
225
+ "subtitle": "Live activity subtitle.",
226
+ "timerEndDateInMilliseconds": 1754410997000,
227
+ "imageName": "live_activity_image",
228
+ "dynamicIslandImageName": "dynamic_island_image"
229
+ },
230
+ "timestamp": 1754491435000, // timestamp of when the push notification was sent
231
+ "attributes-type": "LiveActivityAttributes",
232
+ "attributes": {
233
+ "name": "Test",
234
+ "backgroundColor": "001A72",
235
+ "titleColor": "EBEBF0",
236
+ "subtitleColor": "FFFFFF75",
237
+ "progressViewTint": "38ACDD",
238
+ "progressViewLabelColor": "FFFFFF",
239
+ "deepLinkUrl": "/dashboard",
240
+ "timerType": "digital"
241
+ },
242
+ "alert": {
243
+ "title": "",
244
+ "body": "",
245
+ "sound": "default"
172
246
  }
247
+ }
248
+ }
249
+ ```
250
+
251
+ Example payload for updating live activity:
252
+
253
+ ```json
254
+ {
255
+ "aps": {
256
+ "event": "update",
257
+ "content-state": {
258
+ "title": "Hello",
259
+ "subtitle": "World",
260
+ "timerEndDateInMilliseconds": 1754064245000,
261
+ "imageName": "live_activity_image",
262
+ "dynamicIslandImageName": "dynamic_island_image"
263
+ },
264
+ "timestamp": 1754063621319 // timestamp of when the push notification was sent
265
+ }
173
266
  }
174
267
  ```
175
268
 
176
269
  Where `timerEndDateInMilliseconds` value is a timestamp in milliseconds corresponding to the target point of the counter displayed in live activity view.
177
270
 
178
271
  ## Image support
272
+
179
273
  Live activity view also supports image display. There are two dedicated fields in the `state` object for that:
274
+
180
275
  - `imageName`
181
276
  - `dynamicIslandImageName`
182
277
 
183
278
  The value of each field can be:
279
+
184
280
  - a string which maps to an asset name
185
- - a URL to remote image - currently, it's possible to use this option only via API, but we plan on to add that feature to push notifications as well. It also requires adding "App Groups" capability to both "main app" and "live activity" targets.
281
+ - a URL to remote image - currently, it's possible to use this option only via API, but we plan on to add that feature to push notifications as well. It also requires adding "App Groups" capability to both "main app" and "live activity" targets.
package/app.plugin.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // This file configures the entry file for your plugin.
2
- module.exports = require('./plugin/build');
2
+ module.exports = require('./plugin/build')
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLiveActivityModule.d.ts","sourceRoot":"","sources":["../src/ExpoLiveActivityModule.ts"],"names":[],"mappings":";AAEA,wBAA+D"}
1
+ {"version":3,"file":"ExpoLiveActivityModule.d.ts","sourceRoot":"","sources":["../src/ExpoLiveActivityModule.ts"],"names":[],"mappings":";AAEA,wBAA8D"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLiveActivityModule.js","sourceRoot":"","sources":["../src/ExpoLiveActivityModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,MAAM,CAAC;AAEnD,eAAe,2BAA2B,CAAC,kBAAkB,CAAC,CAAC","sourcesContent":["import { requireOptionalNativeModule } from 'expo';\n\nexport default requireOptionalNativeModule('ExpoLiveActivity');\n"]}
1
+ {"version":3,"file":"ExpoLiveActivityModule.js","sourceRoot":"","sources":["../src/ExpoLiveActivityModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,MAAM,CAAA;AAElD,eAAe,2BAA2B,CAAC,kBAAkB,CAAC,CAAA","sourcesContent":["import { requireOptionalNativeModule } from 'expo'\n\nexport default requireOptionalNativeModule('ExpoLiveActivity')\n"]}
package/build/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { EventSubscription } from 'expo-modules-core';
2
+ type Voidable<T> = T | void;
2
3
  export type DynamicIslandTimerType = 'circular' | 'digital';
3
4
  export type LiveActivityState = {
4
5
  title: string;
@@ -18,17 +19,29 @@ export type LiveActivityConfig = {
18
19
  };
19
20
  export type ActivityTokenReceivedEvent = {
20
21
  activityID: string;
22
+ activityName: string;
21
23
  activityPushToken: string;
22
24
  };
25
+ export type ActivityPushToStartTokenReceivedEvent = {
26
+ activityPushToStartToken: string;
27
+ };
28
+ type ActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended';
29
+ export type ActivityUpdateEvent = {
30
+ activityID: string;
31
+ activityName: string;
32
+ activityState: ActivityState;
33
+ };
23
34
  export type LiveActivityModuleEvents = {
24
35
  onTokenReceived: (params: ActivityTokenReceivedEvent) => void;
36
+ onPushToStartTokenReceived: (params: ActivityPushToStartTokenReceivedEvent) => void;
37
+ onStateChange: (params: ActivityUpdateEvent) => void;
25
38
  };
26
39
  /**
27
40
  * @param {LiveActivityState} state The state for the live activity.
28
41
  * @param {LiveActivityConfig} config Live activity config object.
29
42
  * @returns {string} The identifier of the started activity or undefined if creating live activity failed.
30
43
  */
31
- export declare function startActivity(state: LiveActivityState, config?: LiveActivityConfig): string | undefined;
44
+ export declare function startActivity(state: LiveActivityState, config?: LiveActivityConfig): Voidable<string>;
32
45
  /**
33
46
  * @param {string} id The identifier of the activity to stop.
34
47
  * @param {LiveActivityState} state The updated state for the live activity.
@@ -39,5 +52,8 @@ export declare function stopActivity(id: string, state: LiveActivityState): any;
39
52
  * @param {LiveActivityState} state The updated state for the live activity.
40
53
  */
41
54
  export declare function updateActivity(id: string, state: LiveActivityState): any;
42
- export declare function addActivityTokenListener(listener: (event: ActivityTokenReceivedEvent) => void): EventSubscription | undefined;
55
+ export declare function addActivityTokenListener(listener: (event: ActivityTokenReceivedEvent) => void): Voidable<EventSubscription>;
56
+ export declare function addActivityPushToStartTokenListener(listener: (event: ActivityPushToStartTokenReceivedEvent) => void): Voidable<EventSubscription>;
57
+ export declare function addActivityUpdatesListener(listener: (event: ActivityUpdateEvent) => void): Voidable<EventSubscription>;
58
+ export {};
43
59
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,CAAA;AAE3D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAC/D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAWvG;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,OAShE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,OASlE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,GAAG,iBAAiB,GAAG,SAAS,CAM7H"}
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,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,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;CACnC,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,CAAA;CACjC,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;AAUD;;;;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,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,GACpD,QAAQ,CAAC,iBAAiB,CAAC,CAE7B;AAED,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,CAAC,KAAK,EAAE,qCAAqC,KAAK,IAAI,GAC/D,QAAQ,CAAC,iBAAiB,CAAC,CAG7B;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAC7C,QAAQ,CAAC,iBAAiB,CAAC,CAE7B"}
package/build/index.js CHANGED
@@ -1,58 +1,46 @@
1
- import ExpoLiveActivityModule from "./ExpoLiveActivityModule";
2
- import { Platform } from "react-native";
1
+ import { Platform } from 'react-native';
2
+ import ExpoLiveActivityModule from './ExpoLiveActivityModule';
3
+ function assertIOS(name) {
4
+ const isIOS = Platform.OS === 'ios';
5
+ if (!isIOS)
6
+ console.error(`${name} is only available on iOS`);
7
+ return isIOS;
8
+ }
3
9
  /**
4
10
  * @param {LiveActivityState} state The state for the live activity.
5
11
  * @param {LiveActivityConfig} config Live activity config object.
6
12
  * @returns {string} The identifier of the started activity or undefined if creating live activity failed.
7
13
  */
8
14
  export function startActivity(state, config) {
9
- if (Platform.OS !== "ios") {
10
- console.error("startActivity is only available on iOS");
11
- return undefined;
12
- }
13
- try {
15
+ if (assertIOS('startActivity'))
14
16
  return ExpoLiveActivityModule.startActivity(state, config);
15
- }
16
- catch (error) {
17
- console.error(`startActivity failed with an error: ${error}`);
18
- return undefined;
19
- }
20
17
  }
21
18
  /**
22
19
  * @param {string} id The identifier of the activity to stop.
23
20
  * @param {LiveActivityState} state The updated state for the live activity.
24
21
  */
25
22
  export function stopActivity(id, state) {
26
- if (Platform.OS !== "ios") {
27
- console.error("stopActivity is only available on iOS");
28
- }
29
- try {
23
+ if (assertIOS('stopActivity'))
30
24
  return ExpoLiveActivityModule.stopActivity(id, state);
31
- }
32
- catch (error) {
33
- console.error(`stopActivity failed with an error: ${error}`);
34
- }
35
25
  }
36
26
  /**
37
27
  * @param {string} id The identifier of the activity to update.
38
28
  * @param {LiveActivityState} state The updated state for the live activity.
39
29
  */
40
30
  export function updateActivity(id, state) {
41
- if (Platform.OS !== "ios") {
42
- console.error("updateActivity is only available on iOS");
43
- }
44
- try {
31
+ if (assertIOS('updateActivity'))
45
32
  return ExpoLiveActivityModule.updateActivity(id, state);
46
- }
47
- catch (error) {
48
- console.error(`updateActivity failed with an error: ${error}`);
49
- }
50
33
  }
51
34
  export function addActivityTokenListener(listener) {
52
- if (Platform.OS !== "ios") {
53
- console.error("addActivityTokenListener is only available on iOS");
54
- return undefined;
55
- }
56
- return ExpoLiveActivityModule.addListener('onTokenReceived', listener);
35
+ if (assertIOS('addActivityTokenListener'))
36
+ return ExpoLiveActivityModule.addListener('onTokenReceived', listener);
37
+ }
38
+ export function addActivityPushToStartTokenListener(listener) {
39
+ if (assertIOS('addActivityPushToStartTokenListener'))
40
+ return ExpoLiveActivityModule.addListener('onPushToStartTokenReceived', listener);
41
+ }
42
+ export function addActivityUpdatesListener(listener) {
43
+ if (assertIOS('addActivityUpdatesListener'))
44
+ return ExpoLiveActivityModule.addListener('onStateChange', listener);
57
45
  }
58
46
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAgCxC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAwB,EAAE,MAA2B;IACjF,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACxD,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uCAAuC,KAAK,EAAE,CAAC,CAAC;QAC9D,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,KAAwB;IAC/D,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU,EAAE,KAAwB;IACjE,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,KAAK,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAqD;IAC5F,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,sBAAsB,CAAC,WAAW,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AACzE,CAAC","sourcesContent":["import ExpoLiveActivityModule from \"./ExpoLiveActivityModule\";\nimport { Platform } from \"react-native\";\nimport { EventSubscription } from 'expo-modules-core';\n\nexport type DynamicIslandTimerType = 'circular' | 'digital'\n\nexport type LiveActivityState = {\n title: string;\n subtitle?: string;\n date?: number;\n imageName?: string;\n dynamicIslandImageName?: string;\n};\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};\n\nexport type ActivityTokenReceivedEvent = {\n activityID: string;\n activityPushToken: string;\n};\n\nexport type LiveActivityModuleEvents = {\n onTokenReceived: (params: ActivityTokenReceivedEvent) => void;\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): string | undefined {\n if (Platform.OS !== \"ios\") {\n console.error(\"startActivity is only available on iOS\");\n return undefined\n }\n try {\n return ExpoLiveActivityModule.startActivity(state, config);\n } catch (error) {\n console.error(`startActivity failed with an error: ${error}`);\n return undefined\n }\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 (Platform.OS !== \"ios\") {\n console.error(\"stopActivity is only available on iOS\");\n }\n try {\n return ExpoLiveActivityModule.stopActivity(id, state);\n } catch (error) {\n console.error(`stopActivity failed with an error: ${error}`);\n }\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 (Platform.OS !== \"ios\") {\n console.error(\"updateActivity is only available on iOS\");\n }\n try {\n return ExpoLiveActivityModule.updateActivity(id, state);\n } catch (error) {\n console.error(`updateActivity failed with an error: ${error}`);\n }\n}\n\nexport function addActivityTokenListener(listener: (event: ActivityTokenReceivedEvent) => void): EventSubscription | undefined {\n if (Platform.OS !== \"ios\") {\n console.error(\"addActivityTokenListener is only available on iOS\");\n return undefined\n }\n return ExpoLiveActivityModule.addListener('onTokenReceived', listener);\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAgD7D,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAA;IAEnC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAA;IAE7D,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAwB,EAAE,MAA2B;IACjF,IAAI,SAAS,CAAC,eAAe,CAAC;QAAE,OAAO,sBAAsB,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;AAC5F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,KAAwB;IAC/D,IAAI,SAAS,CAAC,cAAc,CAAC;QAAE,OAAO,sBAAsB,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;AACtF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU,EAAE,KAAwB;IACjE,IAAI,SAAS,CAAC,gBAAgB,CAAC;QAAE,OAAO,sBAAsB,CAAC,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;AAC1F,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,QAAqD;IAErD,IAAI,SAAS,CAAC,0BAA0B,CAAC;QAAE,OAAO,sBAAsB,CAAC,WAAW,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAA;AACnH,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,QAAgE;IAEhE,IAAI,SAAS,CAAC,qCAAqC,CAAC;QAClD,OAAO,sBAAsB,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAA;AACrF,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,QAA8C;IAE9C,IAAI,SAAS,CAAC,4BAA4B,CAAC;QAAE,OAAO,sBAAsB,CAAC,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAA;AACnH,CAAC","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\nexport type LiveActivityState = {\n title: string\n subtitle?: string\n date?: number\n imageName?: string\n dynamicIslandImageName?: string\n}\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}\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\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, 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"]}
@@ -0,0 +1,42 @@
1
+ const { defineConfig } = require('eslint/config')
2
+ const expoConfig = require('eslint-config-expo/flat')
3
+ const eslintPluginPrettierRecommended = require('eslint-plugin-prettier/recommended')
4
+ const simpleImportSort = require('eslint-plugin-simple-import-sort')
5
+
6
+ module.exports = defineConfig([
7
+ expoConfig,
8
+ eslintPluginPrettierRecommended,
9
+ {
10
+ ignores: ['build/*', 'plugin/build/*'],
11
+ },
12
+ defineConfig([
13
+ {
14
+ files: ['example/webpack.config.js'],
15
+ languageOptions: {
16
+ globals: {
17
+ __dirname: 'readonly',
18
+ },
19
+ },
20
+ },
21
+ {
22
+ basePath: 'example',
23
+ settings: {
24
+ 'import/resolver': {
25
+ alias: {
26
+ map: [['expo-live-activity', './src']],
27
+ extensions: ['.ts'],
28
+ },
29
+ },
30
+ },
31
+ },
32
+ {
33
+ plugins: {
34
+ 'simple-import-sort': simpleImportSort,
35
+ },
36
+ rules: {
37
+ 'simple-import-sort/imports': 'error',
38
+ 'simple-import-sort/exports': 'error',
39
+ },
40
+ },
41
+ ]),
42
+ ])