voltra 1.0.0-rc.1 → 1.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/CODE_OF_CONDUCT.md +132 -0
- package/CONTRIBUTING.md +235 -0
- package/README.md +5 -3
- package/build/VoltraModule.d.ts +120 -2
- package/build/VoltraModule.d.ts.map +1 -1
- package/build/VoltraModule.js +2 -1
- package/build/VoltraModule.js.map +1 -1
- package/build/events.d.ts +1 -3
- package/build/events.d.ts.map +1 -1
- package/build/events.js.map +1 -1
- package/build/live-activity/api.d.ts +1 -1
- package/build/live-activity/api.d.ts.map +1 -1
- package/build/live-activity/api.js +17 -2
- package/build/live-activity/api.js.map +1 -1
- package/build/preload.d.ts +2 -37
- package/build/preload.d.ts.map +1 -1
- package/build/preload.js.map +1 -1
- package/build/types.d.ts +58 -0
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/build/widgets/widget-api.d.ts +2 -11
- package/build/widgets/widget-api.d.ts.map +1 -1
- package/build/widgets/widget-api.js.map +1 -1
- package/ios/Voltra.podspec +6 -21
- package/ios/VoltraWidget.podspec +30 -0
- package/ios/shared/Data+hexString.swift +0 -2
- package/ios/ui/Style/StyleConverter.swift +6 -7
- package/package.json +1 -9
- package/plugin/build/features/ios/files/swift/widgetBundle.js +2 -2
- package/plugin/build/features/ios/podfile/index.js +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
- Demonstrating empathy and kindness toward other people
|
|
21
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
- Giving and gracefully accepting constructive feedback
|
|
23
|
+
- Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
- Focusing on what is best not just for us as individuals, but for the overall
|
|
26
|
+
community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
- The use of sexualized language or imagery, and sexual attention or advances of
|
|
31
|
+
any kind
|
|
32
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
- Public or private harassment
|
|
34
|
+
- Publishing others' private information, such as a physical or email address,
|
|
35
|
+
without their explicit permission
|
|
36
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official e-mail address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the community leaders responsible for enforcement at
|
|
63
|
+
[INSERT CONTACT METHOD].
|
|
64
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
65
|
+
|
|
66
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
67
|
+
reporter of any incident.
|
|
68
|
+
|
|
69
|
+
## Enforcement Guidelines
|
|
70
|
+
|
|
71
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
72
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
73
|
+
|
|
74
|
+
### 1. Correction
|
|
75
|
+
|
|
76
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
77
|
+
unprofessional or unwelcome in the community.
|
|
78
|
+
|
|
79
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
80
|
+
clarity around the nature of the violation and an explanation of why the
|
|
81
|
+
behavior was inappropriate. A public apology may be requested.
|
|
82
|
+
|
|
83
|
+
### 2. Warning
|
|
84
|
+
|
|
85
|
+
**Community Impact**: A violation through a single incident or series of
|
|
86
|
+
actions.
|
|
87
|
+
|
|
88
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
89
|
+
interaction with the people involved, including unsolicited interaction with
|
|
90
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
91
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
92
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
|
93
|
+
ban.
|
|
94
|
+
|
|
95
|
+
### 3. Temporary Ban
|
|
96
|
+
|
|
97
|
+
**Community Impact**: A serious violation of community standards, including
|
|
98
|
+
sustained inappropriate behavior.
|
|
99
|
+
|
|
100
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
101
|
+
communication with the community for a specified period of time. No public or
|
|
102
|
+
private interaction with the people involved, including unsolicited interaction
|
|
103
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
104
|
+
Violating these terms may lead to a permanent ban.
|
|
105
|
+
|
|
106
|
+
### 4. Permanent Ban
|
|
107
|
+
|
|
108
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
109
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
110
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
111
|
+
|
|
112
|
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
|
113
|
+
community.
|
|
114
|
+
|
|
115
|
+
## Attribution
|
|
116
|
+
|
|
117
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
118
|
+
version 2.1, available at
|
|
119
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
120
|
+
|
|
121
|
+
Community Impact Guidelines were inspired by
|
|
122
|
+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
123
|
+
|
|
124
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
125
|
+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
|
126
|
+
[https://www.contributor-covenant.org/translations][translations].
|
|
127
|
+
|
|
128
|
+
[homepage]: https://www.contributor-covenant.org
|
|
129
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
130
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
131
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
132
|
+
[translations]: https://www.contributor-covenant.org/translations
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Contributing to Voltra
|
|
2
|
+
|
|
3
|
+
## Before you start any work
|
|
4
|
+
|
|
5
|
+
Please open an issue before starting to work on a new feature or a fix to a bug you encountered. This will prevent you from wasting your time on a feature that's not going to be merged, because for instance it's out of scope. If there is an existing issue present for the matter you want to work on, make sure to post a comment saying you are going to work on it. This will make sure there will be only one person working on a given issue.
|
|
6
|
+
|
|
7
|
+
## Development process
|
|
8
|
+
|
|
9
|
+
All work on Voltra happens directly on GitHub. Contributors send pull requests which go through the review process.
|
|
10
|
+
|
|
11
|
+
> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
|
|
12
|
+
|
|
13
|
+
1. Fork the repo and create your branch from `main` (a guide on [how to fork a repository](https://help.github.com/articles/fork-a-repo/)).
|
|
14
|
+
2. Run `npm install` to install all required dependencies.
|
|
15
|
+
3. Build the plugin: `npx tsc -p plugin/tsconfig.json`.
|
|
16
|
+
4. Now you are ready to make changes.
|
|
17
|
+
|
|
18
|
+
## Architecture overview
|
|
19
|
+
|
|
20
|
+
### JS/TS code structure
|
|
21
|
+
|
|
22
|
+
The JavaScript/TypeScript code has **two separate entry points** that must be maintained as independent boundaries:
|
|
23
|
+
|
|
24
|
+
- **Client entry (`src/index.ts`)**: React Native code that runs in the app. Exports JSX components, hooks, and the imperative API for managing Live Activities.
|
|
25
|
+
- **Server entry (`src/server.ts`)**: Node.js code for rendering Voltra components to string payloads. Used for server-side rendering and push notification payloads.
|
|
26
|
+
|
|
27
|
+
⚠️ **Important**: These two entry points must remain separate. Client code should not import server-only dependencies, and server code should not import React Native-specific modules.
|
|
28
|
+
|
|
29
|
+
### Expo config plugin (`plugin/`)
|
|
30
|
+
|
|
31
|
+
The Expo plugin in `plugin/src/` handles all Xcode project setup during `expo prebuild`:
|
|
32
|
+
|
|
33
|
+
1. **Creates the widget extension target** with proper build settings
|
|
34
|
+
2. **Copies template files** from `ios-files/` (widget bundle, assets, Info.plist) into the extension target
|
|
35
|
+
3. **Configures CocoaPods** to include the `VoltraWidget` subspec in the extension target
|
|
36
|
+
4. **Sets up entitlements** for App Groups (optional, for event forwarding)
|
|
37
|
+
5. **Configures push notifications** (optional)
|
|
38
|
+
|
|
39
|
+
### Swift code distribution (`ios/`)
|
|
40
|
+
|
|
41
|
+
Voltra's Swift code lives in `ios/` and is distributed as a **CocoaPods package** with multiple subspecs:
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
# From ios/Voltra.podspec
|
|
45
|
+
s.subspec 'Core' do |ss|
|
|
46
|
+
# React Native bridge module (auto-linked by Expo)
|
|
47
|
+
ss.source_files = ["app/**/*.swift", "shared/**/*.swift", "ui/**/*.swift"]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
s.subspec 'Widget' do |ss|
|
|
51
|
+
# Widget extension code (used by Live Activity target)
|
|
52
|
+
ss.source_files = ["shared/**/*.swift", "ui/**/*.swift", "target/**/*.swift"]
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **`Core` subspec**: Contains the React Native module (`app/`), shared code (`shared/`), and UI components (`ui/`). Auto-linked by Expo in the main app.
|
|
57
|
+
- **`Widget` subspec**: Contains shared code, UI components, and widget-specific files (`target/`). Used by the Live Activity extension target.
|
|
58
|
+
|
|
59
|
+
This separation ensures the widget extension doesn't include unnecessary React Native dependencies.
|
|
60
|
+
|
|
61
|
+
### Template files (`ios-files/`)
|
|
62
|
+
|
|
63
|
+
Files in `ios-files/` are copied by the config plugin into the generated widget extension:
|
|
64
|
+
|
|
65
|
+
- `VoltraWidgetBundle.swift` — Widget bundle entry point
|
|
66
|
+
- `Assets.xcassets/` — Asset catalog for the extension
|
|
67
|
+
- `Info.plist` — Extension configuration
|
|
68
|
+
|
|
69
|
+
## Props synchronization
|
|
70
|
+
|
|
71
|
+
Component props are kept in sync between TypeScript and Swift via a **custom code generator**. The single source of truth is:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
data/components.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This file defines all components, their parameters, types, and short names used for payload compression.
|
|
78
|
+
|
|
79
|
+
### Running the generator
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
npm run generate
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This generates:
|
|
86
|
+
|
|
87
|
+
- **TypeScript prop types**: `src/jsx/props/*.ts`
|
|
88
|
+
- **Swift parameter structs**: `ios/ui/Generated/Parameters/*.swift`
|
|
89
|
+
- **Component ID mappings**: `src/payload/component-ids.ts` and `ios/shared/ComponentTypeID.swift`
|
|
90
|
+
- **Short name mappings**: `src/payload/short-names.ts` and `ios/shared/ShortNames.swift`
|
|
91
|
+
|
|
92
|
+
⚠️ **Important**: When adding new components or modifying props, always update `data/components.json` first, then run the generator. Do not manually edit generated files (marked with `.generated`).
|
|
93
|
+
|
|
94
|
+
## Payload size budget
|
|
95
|
+
|
|
96
|
+
Live Activity payloads have strict size limits imposed by iOS. Voltra includes tests that track payload sizes for real-world examples.
|
|
97
|
+
|
|
98
|
+
### How it works
|
|
99
|
+
|
|
100
|
+
The test in `src/__tests__/payload-size.node.test.tsx` renders example components and snapshots their compressed payload size:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
it('BasicLiveActivityUI', async () => {
|
|
104
|
+
const size = await getPayloadSize({
|
|
105
|
+
lockScreen: <BasicLiveActivityUI />,
|
|
106
|
+
})
|
|
107
|
+
expect(size).toMatchSnapshot()
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### When payload size changes
|
|
112
|
+
|
|
113
|
+
If your changes affect payload size, the tests will fail. This is intentional:
|
|
114
|
+
|
|
115
|
+
- **Size decreased?** Great! Run `npm test -- -u` to update snapshots and lock in the improvement.
|
|
116
|
+
- **Size increased?** Investigate carefully. Is the increase justified? Can it be optimized? Only update snapshots after confirming the increase is necessary.
|
|
117
|
+
|
|
118
|
+
⚠️ **CI will block merging** if payload size snapshots are out of date. This ensures we don't accidentally regress payload efficiency.
|
|
119
|
+
|
|
120
|
+
## Payload schema versioning
|
|
121
|
+
|
|
122
|
+
The payload schema has a version number to support forward compatibility. When the Swift code receives a payload with a newer version than it understands, it renders empty instead of crashing.
|
|
123
|
+
|
|
124
|
+
### Version constants
|
|
125
|
+
|
|
126
|
+
The version is defined in two places that must stay in sync:
|
|
127
|
+
|
|
128
|
+
- **TypeScript**: `src/renderer/renderer.ts` → `VOLTRA_PAYLOAD_VERSION`
|
|
129
|
+
- **Swift**: `ios/shared/VoltraPayloadMigrator.swift` → `currentVersion`
|
|
130
|
+
|
|
131
|
+
### When to increment the version
|
|
132
|
+
|
|
133
|
+
Increment the version when making **breaking changes** to the payload schema:
|
|
134
|
+
|
|
135
|
+
- Adding required fields that old Swift code wouldn't understand
|
|
136
|
+
- Changing the structure of existing fields
|
|
137
|
+
- Renaming keys in a way that breaks parsing
|
|
138
|
+
|
|
139
|
+
You do **not** need to increment for:
|
|
140
|
+
|
|
141
|
+
- Adding optional fields (old Swift code will ignore them)
|
|
142
|
+
- Bug fixes that don't change the schema
|
|
143
|
+
- Adding new component types (they render as `EmptyView` if unknown)
|
|
144
|
+
|
|
145
|
+
### Adding migrations
|
|
146
|
+
|
|
147
|
+
When you increment the version, add a migration in Swift to upgrade old payloads:
|
|
148
|
+
|
|
149
|
+
1. Increment `currentVersion` in both TypeScript and Swift
|
|
150
|
+
2. Create a migration struct implementing `VoltraPayloadMigration`
|
|
151
|
+
3. Register it in the `migrations` dictionary
|
|
152
|
+
|
|
153
|
+
```swift
|
|
154
|
+
// Example: V1ToV2Migration.swift
|
|
155
|
+
struct V1ToV2Migration: VoltraPayloadMigration {
|
|
156
|
+
static let fromVersion = 1
|
|
157
|
+
static let toVersion = 2
|
|
158
|
+
|
|
159
|
+
static func migrate(_ json: JSONValue) throws -> JSONValue {
|
|
160
|
+
// Transform v1 payload to v2 format
|
|
161
|
+
// Update the version field
|
|
162
|
+
var result = json
|
|
163
|
+
result["v"] = .int(2)
|
|
164
|
+
return result
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// In VoltraPayloadMigrator.swift:
|
|
169
|
+
private static let migrations: [Int: any VoltraPayloadMigration.Type] = [
|
|
170
|
+
1: V1ToV2Migration.self,
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
This ensures users with older apps can still receive updates from newer servers.
|
|
175
|
+
|
|
176
|
+
## Testing your changes
|
|
177
|
+
|
|
178
|
+
The `example/` directory contains an Expo app for testing changes.
|
|
179
|
+
|
|
180
|
+
### Running the example app
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
# 1) Build the plugin
|
|
184
|
+
npx tsc -p plugin/tsconfig.json
|
|
185
|
+
|
|
186
|
+
# 2) Install example dependencies
|
|
187
|
+
(cd example && npm install)
|
|
188
|
+
|
|
189
|
+
# 3) Prebuild for iOS
|
|
190
|
+
(cd example && npx expo prebuild -p ios)
|
|
191
|
+
|
|
192
|
+
# 4) Run on iOS
|
|
193
|
+
(cd example && npx expo run:ios)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If iterating on the plugin, rebuild after each change in `plugin/src/`.
|
|
197
|
+
|
|
198
|
+
### Running tests
|
|
199
|
+
|
|
200
|
+
Run the following checks before opening a pull request:
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
# Linting
|
|
204
|
+
npm run lint:libOnly
|
|
205
|
+
|
|
206
|
+
# Type checking
|
|
207
|
+
npm run build
|
|
208
|
+
|
|
209
|
+
# Unit tests
|
|
210
|
+
npm test
|
|
211
|
+
|
|
212
|
+
# Format check
|
|
213
|
+
npm run format:check
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
If formatting fails, run `npx prettier --write .` to fix it.
|
|
217
|
+
|
|
218
|
+
## Creating a pull request
|
|
219
|
+
|
|
220
|
+
When you are ready to have your changes incorporated into the main codebase, open a pull request.
|
|
221
|
+
|
|
222
|
+
This repository follows [the Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/#summary). Please follow this pattern in your pull request titles. Keep in mind your commits will be squashed before merging and the title will be used as a commit title.
|
|
223
|
+
|
|
224
|
+
### Pull request checklist
|
|
225
|
+
|
|
226
|
+
- [ ] Tests pass (`npm test`)
|
|
227
|
+
- [ ] Linting passes (`npm run lint:libOnly`)
|
|
228
|
+
- [ ] Formatting is correct (`npm run format:check`)
|
|
229
|
+
- [ ] If props changed, generator was run (`npm run generate`)
|
|
230
|
+
- [ ] If payload size changed, snapshots were intentionally updated
|
|
231
|
+
- [ ] Documentation updated if needed
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
By contributing to Voltra, you agree that your contributions will be licensed under its MIT license.
|
package/README.md
CHANGED
|
@@ -84,13 +84,15 @@ export function OrderTracker({ orderId }: { orderId: string }) {
|
|
|
84
84
|
|
|
85
85
|
**Note:** This module is intended for use on **iOS devices only**.
|
|
86
86
|
|
|
87
|
-
##
|
|
87
|
+
## Authors
|
|
88
88
|
|
|
89
|
-
`voltra` is an open source
|
|
89
|
+
`voltra` is an open source collaboration between [Saúl Sharma](https://github.com/saul-sharma) and [Szymon Chmal](https://github.com/szymonchmal) at [Callstack][callstack-readme-with-love].
|
|
90
|
+
|
|
91
|
+
If you think it's cool, please star it 🌟. This project will always remain free to use.
|
|
90
92
|
|
|
91
93
|
[Callstack][callstack-readme-with-love] is a group of React and React Native geeks, contact us at [hello@callstack.com](mailto:hello@callstack.com) if you need any help with these or just want to say hi!
|
|
92
94
|
|
|
93
|
-
Like the project? ⚛️ [Join the team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
|
|
95
|
+
Like the project? ⚛️ [Join the Callstack team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
|
|
94
96
|
|
|
95
97
|
[callstack-readme-with-love]: https://callstack.com/?utm_source=github.com&utm_medium=referral&utm_campaign=voltra&utm_term=readme-with-love
|
|
96
98
|
[license-badge]: https://img.shields.io/npm/l/voltra?style=for-the-badge
|
package/build/VoltraModule.d.ts
CHANGED
|
@@ -1,3 +1,121 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { EventSubscription, PreloadImageOptions, PreloadImagesResult, UpdateWidgetOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Options for starting a Live Activity
|
|
4
|
+
*/
|
|
5
|
+
export type StartVoltraOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Target type for the activity (used internally)
|
|
8
|
+
*/
|
|
9
|
+
target?: string;
|
|
10
|
+
/**
|
|
11
|
+
* URL to open when the Live Activity is tapped.
|
|
12
|
+
*/
|
|
13
|
+
deepLinkUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The ID/name of the Live Activity.
|
|
16
|
+
* Allows you to rebind to the same activity on app restart.
|
|
17
|
+
*/
|
|
18
|
+
activityId?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Unix timestamp in milliseconds
|
|
21
|
+
*/
|
|
22
|
+
staleDate?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Double value between 0.0 and 1.0, defaults to 0.0
|
|
25
|
+
*/
|
|
26
|
+
relevanceScore?: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Options for updating a Live Activity
|
|
30
|
+
*/
|
|
31
|
+
export type UpdateVoltraOptions = {
|
|
32
|
+
/**
|
|
33
|
+
* Unix timestamp in milliseconds
|
|
34
|
+
*/
|
|
35
|
+
staleDate?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Double value between 0.0 and 1.0, defaults to 0.0
|
|
38
|
+
*/
|
|
39
|
+
relevanceScore?: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Options for ending a Live Activity
|
|
43
|
+
*/
|
|
44
|
+
export type EndVoltraOptions = {
|
|
45
|
+
dismissalPolicy?: {
|
|
46
|
+
type: 'immediate' | 'after';
|
|
47
|
+
date?: number;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* VoltraModule native module interface
|
|
52
|
+
*/
|
|
53
|
+
export interface VoltraModuleSpec {
|
|
54
|
+
/**
|
|
55
|
+
* Start a new Live Activity
|
|
56
|
+
*/
|
|
57
|
+
startLiveActivity(jsonString: string, options?: StartVoltraOptions): Promise<string>;
|
|
58
|
+
/**
|
|
59
|
+
* Update an existing Live Activity
|
|
60
|
+
*/
|
|
61
|
+
updateLiveActivity(activityId: string, jsonString: string, options?: UpdateVoltraOptions): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* End a Live Activity
|
|
64
|
+
*/
|
|
65
|
+
endLiveActivity(activityId: string, options?: EndVoltraOptions): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* End all active Live Activities
|
|
68
|
+
*/
|
|
69
|
+
endAllLiveActivities(): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Get the latest (most recently created) Voltra Live Activity ID, if any
|
|
72
|
+
*/
|
|
73
|
+
getLatestVoltraActivityId(): Promise<string | null>;
|
|
74
|
+
/**
|
|
75
|
+
* List all running Voltra Live Activity IDs
|
|
76
|
+
*/
|
|
77
|
+
listVoltraActivityIds(): Promise<string[]>;
|
|
78
|
+
/**
|
|
79
|
+
* Check if a Live Activity with the given name is currently active
|
|
80
|
+
*/
|
|
81
|
+
isLiveActivityActive(activityName: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Check if the app was launched in the background (headless)
|
|
84
|
+
*/
|
|
85
|
+
isHeadless(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Preload images to App Group storage for use in Live Activities
|
|
88
|
+
*/
|
|
89
|
+
preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Reload Live Activities to pick up preloaded images
|
|
92
|
+
*/
|
|
93
|
+
reloadLiveActivities(activityNames?: string[] | null): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Clear preloaded images from App Group storage
|
|
96
|
+
*/
|
|
97
|
+
clearPreloadedImages(keys?: string[] | null): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Update a home screen widget with new content
|
|
100
|
+
*/
|
|
101
|
+
updateWidget(widgetId: string, jsonString: string, options?: UpdateWidgetOptions): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Reload widget timelines to refresh their content
|
|
104
|
+
*/
|
|
105
|
+
reloadWidgets(widgetIds?: string[] | null): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Clear a widget's stored data
|
|
108
|
+
*/
|
|
109
|
+
clearWidget(widgetId: string): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Clear all widgets' stored data
|
|
112
|
+
*/
|
|
113
|
+
clearAllWidgets(): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Add an event listener
|
|
116
|
+
*/
|
|
117
|
+
addListener(event: string, listener: (event: any) => void): EventSubscription;
|
|
118
|
+
}
|
|
119
|
+
declare const VoltraModule: VoltraModuleSpec;
|
|
120
|
+
export default VoltraModule;
|
|
3
121
|
//# sourceMappingURL=VoltraModule.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoltraModule.d.ts","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VoltraModule.d.ts","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"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"}
|
package/build/VoltraModule.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoltraModule.js","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"VoltraModule.js","sourceRoot":"","sources":["../src/VoltraModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAA;AA4I1C,MAAM,YAAY,GAAG,mBAAmB,CAAmB,cAAc,CAAC,CAAA;AAE1E,eAAe,YAAY,CAAA","sourcesContent":["import { requireNativeModule } from 'expo'\n\nimport type { EventSubscription, PreloadImageOptions, PreloadImagesResult, UpdateWidgetOptions } from './types.js'\n\n/**\n * Options for starting a Live Activity\n */\nexport type StartVoltraOptions = {\n /**\n * Target type for the activity (used internally)\n */\n target?: string\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n /**\n * The ID/name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityId?: string\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0, defaults to 0.0\n */\n relevanceScore?: number\n}\n\n/**\n * Options for updating a Live Activity\n */\nexport type UpdateVoltraOptions = {\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0, defaults to 0.0\n */\n relevanceScore?: number\n}\n\n/**\n * Options for ending a Live Activity\n */\nexport type EndVoltraOptions = {\n dismissalPolicy?: {\n type: 'immediate' | 'after'\n date?: number\n }\n}\n\n/**\n * VoltraModule native module interface\n */\nexport interface VoltraModuleSpec {\n /**\n * Start a new Live Activity\n */\n startLiveActivity(jsonString: string, options?: StartVoltraOptions): Promise<string>\n\n /**\n * Update an existing Live Activity\n */\n updateLiveActivity(activityId: string, jsonString: string, options?: UpdateVoltraOptions): Promise<void>\n\n /**\n * End a Live Activity\n */\n endLiveActivity(activityId: string, options?: EndVoltraOptions): Promise<void>\n\n /**\n * End all active Live Activities\n */\n endAllLiveActivities(): Promise<void>\n\n /**\n * Get the latest (most recently created) Voltra Live Activity ID, if any\n */\n getLatestVoltraActivityId(): Promise<string | null>\n\n /**\n * List all running Voltra Live Activity IDs\n */\n listVoltraActivityIds(): Promise<string[]>\n\n /**\n * Check if a Live Activity with the given name is currently active\n */\n isLiveActivityActive(activityName: string): boolean\n\n /**\n * Check if the app was launched in the background (headless)\n */\n isHeadless(): boolean\n\n /**\n * Preload images to App Group storage for use in Live Activities\n */\n preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult>\n\n /**\n * Reload Live Activities to pick up preloaded images\n */\n reloadLiveActivities(activityNames?: string[] | null): Promise<void>\n\n /**\n * Clear preloaded images from App Group storage\n */\n clearPreloadedImages(keys?: string[] | null): Promise<void>\n\n /**\n * Update a home screen widget with new content\n */\n updateWidget(widgetId: string, jsonString: string, options?: UpdateWidgetOptions): Promise<void>\n\n /**\n * Reload widget timelines to refresh their content\n */\n reloadWidgets(widgetIds?: string[] | null): Promise<void>\n\n /**\n * Clear a widget's stored data\n */\n clearWidget(widgetId: string): Promise<void>\n\n /**\n * Clear all widgets' stored data\n */\n clearAllWidgets(): Promise<void>\n\n /**\n * Add an event listener\n */\n addListener(event: string, listener: (event: any) => void): EventSubscription\n}\n\nconst VoltraModule = requireNativeModule<VoltraModuleSpec>('VoltraModule')\n\nexport default VoltraModule\n"]}
|
package/build/events.d.ts
CHANGED
package/build/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAInD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AACjG,MAAM,MAAM,gCAAgC,GAAG,gBAAgB,GAAG;IAChE,IAAI,EAAE,uBAAuB,CAAA;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AACD,MAAM,MAAM,2CAA2C,GAAG,gBAAgB,GAAG;IAC3E,IAAI,EAAE,kCAAkC,CAAA;IACxC,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AACD,MAAM,MAAM,yBAAyB,GAAG,gBAAgB,GAAG;IACzD,IAAI,EAAE,aAAa,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,mBAAmB,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG;IACtD,IAAI,EAAE,aAAa,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAMD,MAAM,MAAM,cAAc,GAAG;IAC3B,qBAAqB,EAAE,gCAAgC,CAAA;IACvD,gCAAgC,EAAE,2CAA2C,CAAA;IAC7E,WAAW,EAAE,yBAAyB,CAAA;IACtC,WAAW,EAAE,sBAAsB,CAAA;CACpC,CAAA;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,cAAc,EAC9D,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3C,iBAAiB,CAMnB"}
|
package/build/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,YAAY,MAAM,mBAAmB,CAAA;AA6B5C,MAAM,gBAAgB,GAAsB;IAC1C,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;CACjB,CAAA;AASD,MAAM,UAAU,iBAAiB,CAC/B,KAAQ,EACR,QAA4C;IAE5C,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;QAC5B,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,OAAO,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAClD,CAAC","sourcesContent":["import type { EventSubscription } from './types.js'\nimport { assertRunningOnApple } from './utils/index.js'\nimport VoltraModule from './VoltraModule.js'\n\nexport type BasicVoltraEvent = {\n source: string\n timestamp: number\n}\n\nexport type VoltraActivityState = 'active' | 'dismissed' | 'pending' | 'stale' | 'ended' | string\nexport type VoltraActivityTokenReceivedEvent = BasicVoltraEvent & {\n type: 'activityTokenReceived'\n activityName: string\n pushToken: string\n}\nexport type VoltraActivityPushToStartTokenReceivedEvent = BasicVoltraEvent & {\n type: 'activityPushToStartTokenReceived'\n pushToStartToken: string\n}\nexport type VoltraActivityUpdateEvent = BasicVoltraEvent & {\n type: 'stateChange'\n activityName: string\n activityState: VoltraActivityState\n}\n\nexport type VoltraInteractionEvent = BasicVoltraEvent & {\n type: 'interaction'\n identifier: string\n payload: string\n}\n\nconst noopSubscription: EventSubscription = {\n remove: () => {},\n}\n\nexport type VoltraEventMap = {\n activityTokenReceived: VoltraActivityTokenReceivedEvent\n activityPushToStartTokenReceived: VoltraActivityPushToStartTokenReceivedEvent\n stateChange: VoltraActivityUpdateEvent\n interaction: VoltraInteractionEvent\n}\n\nexport function addVoltraListener<K extends keyof VoltraEventMap>(\n event: K,\n listener: (event: VoltraEventMap[K]) => void\n): EventSubscription {\n if (!assertRunningOnApple()) {\n return noopSubscription\n }\n\n return VoltraModule.addListener(event, listener)\n}\n"]}
|
|
@@ -140,7 +140,7 @@ export declare const updateLiveActivity: (targetId: string, variants: LiveActivi
|
|
|
140
140
|
* ```tsx
|
|
141
141
|
* import { stopLiveActivity } from 'voltra'
|
|
142
142
|
*
|
|
143
|
-
* await stopLiveActivity('activity-123', { dismissalPolicy: '
|
|
143
|
+
* await stopLiveActivity('activity-123', { dismissalPolicy: 'immediate' })
|
|
144
144
|
* ```
|
|
145
145
|
*/
|
|
146
146
|
export declare const stopLiveActivity: (targetId: string, options?: EndLiveActivityOptions) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,yBAAyB,CAAA;AAE7B,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAA;AAEjE,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEvE,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,yBAAyB,CAAA;AAE7B,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAA;AAEjE,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,oBAAoB,EAC9B,UAAU,sBAAsB,KAC/B,qBAwFF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,oBAAoB,EAC9B,UAAU,wBAAwB,KACjC,OAAO,CAAC,MAAM,CAahB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,UAAU,oBAAoB,EAC9B,UAAU,yBAAyB,KAClC,OAAO,CAAC,IAAI,CAOd,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAU,UAAU,MAAM,EAAE,UAAU,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAKvG,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAAI,cAAc,MAAM,KAAG,OAI3D,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1D"}
|
|
@@ -27,6 +27,20 @@ const normalizeSharedLiveActivityOptions = (options) => {
|
|
|
27
27
|
}
|
|
28
28
|
return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined;
|
|
29
29
|
};
|
|
30
|
+
const normalizeEndLiveActivityOptions = (options) => {
|
|
31
|
+
if (!options?.dismissalPolicy)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (typeof options.dismissalPolicy === 'string') {
|
|
34
|
+
if (options.dismissalPolicy === 'immediate') {
|
|
35
|
+
return { dismissalPolicy: { type: 'immediate' } };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (typeof options.dismissalPolicy === 'object' && 'after' in options.dismissalPolicy) {
|
|
39
|
+
return { dismissalPolicy: { type: 'after', date: options.dismissalPolicy.after } };
|
|
40
|
+
}
|
|
41
|
+
// Default to immediate if unrecognized
|
|
42
|
+
return { dismissalPolicy: { type: 'immediate' } };
|
|
43
|
+
};
|
|
30
44
|
/**
|
|
31
45
|
* React hook for managing Live Activities with automatic lifecycle handling.
|
|
32
46
|
*
|
|
@@ -198,13 +212,14 @@ export const updateLiveActivity = async (targetId, variants, options) => {
|
|
|
198
212
|
* ```tsx
|
|
199
213
|
* import { stopLiveActivity } from 'voltra'
|
|
200
214
|
*
|
|
201
|
-
* await stopLiveActivity('activity-123', { dismissalPolicy: '
|
|
215
|
+
* await stopLiveActivity('activity-123', { dismissalPolicy: 'immediate' })
|
|
202
216
|
* ```
|
|
203
217
|
*/
|
|
204
218
|
export const stopLiveActivity = async (targetId, options) => {
|
|
205
219
|
if (!assertRunningOnApple())
|
|
206
220
|
return Promise.resolve();
|
|
207
|
-
|
|
221
|
+
const normalizedOptions = normalizeEndLiveActivityOptions(options);
|
|
222
|
+
return VoltraModule.endLiveActivity(targetId, normalizedOptions);
|
|
208
223
|
};
|
|
209
224
|
/**
|
|
210
225
|
* Check if a Live Activity with the given name is currently active.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { addVoltraListener } from '../events.js'\nimport { logger } from '../logger.js'\nimport { assertRunningOnApple, useUpdateOnHMR } from '../utils/index.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderLiveActivityToString } from './renderer.js'\nimport type { DismissalPolicy, LiveActivityVariants } from './types.js'\n\nexport type SharedLiveActivityOptions = {\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0\n * @default 0.0\n */\n relevanceScore?: number\n /**\n * How the Live Activity should be dismissed after ending\n * @default 'immediate'\n */\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type StartLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n} & SharedLiveActivityOptions\n\nexport type UpdateLiveActivityOptions = SharedLiveActivityOptions\n\nexport type EndLiveActivityOptions = {\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type UseLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * Automatically start the Live Activity when the component mounts.\n */\n autoStart?: boolean\n /**\n * Automatically update the Live Activity when the component updates.\n */\n autoUpdate?: boolean\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n}\n\nexport type UseLiveActivityResult = {\n start: (options?: StartLiveActivityOptions) => Promise<void>\n update: (options?: UpdateLiveActivityOptions) => Promise<void>\n end: (options?: EndLiveActivityOptions) => Promise<void>\n isActive: boolean\n}\n\nconst normalizeSharedLiveActivityOptions = (\n options?: SharedLiveActivityOptions\n): SharedLiveActivityOptions | undefined => {\n if (!options) return undefined\n\n const normalizedOptions: SharedLiveActivityOptions = {}\n\n if (options.staleDate !== undefined) {\n if (options.staleDate < Date.now()) {\n logger.warn('Ignoring staleDate because it is in the past, the Live Activity would be dismissed immediately.')\n } else {\n normalizedOptions.staleDate = options.staleDate\n }\n }\n\n // Always include relevanceScore, defaulting to 0.0 if not provided\n const relevanceScore = options.relevanceScore ?? 0.0\n if (relevanceScore < 0 || relevanceScore > 1) {\n logger.warn('Ignoring relevanceScore because it is out of range [0.0, 1.0], using default 0.0')\n normalizedOptions.relevanceScore = 0.0\n } else {\n normalizedOptions.relevanceScore = relevanceScore\n }\n\n return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined\n}\n\n/**\n * React hook for managing Live Activities with automatic lifecycle handling.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the hook\n * @returns Object with start, update, end methods and isActive state\n *\n * @example\n * ```tsx\n * import { useLiveActivity, Voltra } from 'voltra'\n *\n * const MyLiveActivity = () => {\n * const { start, update, end, isActive } = useLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * autoStart: true,\n * autoUpdate: true\n * })\n *\n * return (\n * <View>\n * <Button title={isActive ? \"Stop\" : \"Start\"} onPress={isActive ? end : start} />\n * </View>\n * )\n * }\n * ```\n */\nexport const useLiveActivity = (\n variants: LiveActivityVariants,\n options?: UseLiveActivityOptions\n): UseLiveActivityResult => {\n const [targetId, setTargetId] = useState<string | null>(() => {\n if (options?.activityName) {\n return isLiveActivityActive(options.activityName) ? options.activityName : null\n }\n\n return null\n })\n const isActive = targetId !== null\n const optionsRef = useRef(options)\n const variantsRef = useRef(variants)\n const lastUpdateOptionsRef = useRef<UpdateLiveActivityOptions | undefined>(undefined)\n\n // Update refs when values change\n useEffect(() => {\n optionsRef.current = options\n }, [options])\n\n useEffect(() => {\n variantsRef.current = variants\n }, [variants])\n\n useUpdateOnHMR()\n\n const start = useCallback(async (options?: StartLiveActivityOptions) => {\n const id = await startLiveActivity(variantsRef.current, { ...optionsRef.current, ...options })\n setTargetId(id)\n }, [])\n\n const update = useCallback(\n async (options?: UpdateLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n const updateOptions = { ...optionsRef.current, ...options }\n lastUpdateOptionsRef.current = updateOptions\n await updateLiveActivity(targetId, variantsRef.current, updateOptions)\n },\n [targetId]\n )\n\n const end = useCallback(\n async (options?: EndLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n await stopLiveActivity(targetId, options)\n setTargetId(null)\n },\n [targetId]\n )\n\n useEffect(() => {\n if (!options?.autoStart) {\n return\n }\n\n start()\n }, [options?.autoStart, start])\n\n useEffect(() => {\n if (!options?.autoUpdate) return\n update(lastUpdateOptionsRef.current)\n }, [options?.autoUpdate, update, variants])\n\n useEffect(() => {\n if (!targetId) return\n\n const subscription = addVoltraListener('stateChange', (event) => {\n if (event.activityName !== targetId) return\n\n if (event.activityState === 'dismissed' || event.activityState === 'ended') {\n // Live Activity is no longer active.\n setTargetId(null)\n }\n })\n\n return () => subscription.remove()\n }, [targetId])\n\n return {\n start,\n update,\n end,\n isActive,\n }\n}\n\n/**\n * Start a new Live Activity with the provided content variants.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the Live Activity\n * @returns Promise resolving to the activity ID\n *\n * @example\n * ```tsx\n * import { startLiveActivity, Voltra } from 'voltra'\n *\n * const activityId = await startLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * deepLinkUrl: '/details',\n * relevanceScore: 0.8\n * })\n * ```\n */\nexport const startLiveActivity = async (\n variants: LiveActivityVariants,\n options?: StartLiveActivityOptions\n): Promise<string> => {\n if (!assertRunningOnApple()) return Promise.resolve('')\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n const targetId = await VoltraModule.startLiveActivity(payload, {\n target: 'liveActivity',\n deepLinkUrl: options?.deepLinkUrl,\n activityId: options?.activityName,\n ...normalizedSharedOptions,\n })\n return targetId\n}\n\n/**\n * Update an existing Live Activity with new content.\n *\n * @param targetId - The ID of the Live Activity to update\n * @param variants - The new Live Activity content variants\n * @param options - Update options like relevance score\n *\n * @example\n * ```tsx\n * import { updateLiveActivity, Voltra } from 'voltra'\n *\n * await updateLiveActivity('activity-123', {\n * minimal: <Voltra.Text>Updated: Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * relevanceScore: 0.9\n * })\n * ```\n */\nexport const updateLiveActivity = async (\n targetId: string,\n variants: LiveActivityVariants,\n options?: UpdateLiveActivityOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n return VoltraModule.updateLiveActivity(targetId, payload, normalizedSharedOptions)\n}\n\n/**\n * Stop a Live Activity.\n *\n * @param targetId - The ID of the Live Activity to stop\n * @param options - Options for how to end the activity\n *\n * @example\n * ```tsx\n * import { stopLiveActivity } from 'voltra'\n *\n * await stopLiveActivity('activity-123', { dismissalPolicy: 'afterDate' })\n * ```\n */\nexport const stopLiveActivity = async (targetId: string, options?: EndLiveActivityOptions): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.endLiveActivity(targetId, options)\n}\n\n/**\n * Check if a Live Activity with the given name is currently active.\n *\n * @param activityName - The name of the Live Activity to check\n * @returns true if the activity is active, false otherwise\n *\n * @example\n * ```tsx\n * import { isLiveActivityActive } from 'voltra'\n *\n * if (isLiveActivityActive('my-activity')) {\n * console.log('Activity is running')\n * }\n * ```\n */\nexport const isLiveActivityActive = (activityName: string): boolean => {\n if (!assertRunningOnApple()) return false\n\n return VoltraModule.isLiveActivityActive(activityName)\n}\n\n/**\n * End all active Live Activities.\n *\n * This function stops and dismisses all currently running Live Activities in the app.\n * It's useful for cleanup operations, such as when the app is being closed or\n * when you want to reset all Live Activity states.\n *\n * @example\n * ```typescript\n * import { endAllLiveActivities } from 'voltra'\n *\n * // End all active Live Activities\n * await endAllLiveActivities()\n * ```\n */\nexport async function endAllLiveActivities(): Promise<void> {\n if (!assertRunningOnApple()) return Promise.resolve()\n return VoltraModule.endAllLiveActivities()\n}\n"]}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/live-activity/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { addVoltraListener } from '../events.js'\nimport { logger } from '../logger.js'\nimport { assertRunningOnApple, useUpdateOnHMR } from '../utils/index.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderLiveActivityToString } from './renderer.js'\nimport type { DismissalPolicy, LiveActivityVariants } from './types.js'\n\nexport type SharedLiveActivityOptions = {\n /**\n * Unix timestamp in milliseconds\n */\n staleDate?: number\n /**\n * Double value between 0.0 and 1.0\n * @default 0.0\n */\n relevanceScore?: number\n /**\n * How the Live Activity should be dismissed after ending\n * @default 'immediate'\n */\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type StartLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n} & SharedLiveActivityOptions\n\nexport type UpdateLiveActivityOptions = SharedLiveActivityOptions\n\nexport type EndLiveActivityOptions = {\n dismissalPolicy?: DismissalPolicy\n}\n\nexport type UseLiveActivityOptions = {\n /**\n * The name of the Live Activity.\n * Allows you to rebind to the same activity on app restart.\n */\n activityName?: string\n /**\n * Automatically start the Live Activity when the component mounts.\n */\n autoStart?: boolean\n /**\n * Automatically update the Live Activity when the component updates.\n */\n autoUpdate?: boolean\n /**\n * URL to open when the Live Activity is tapped.\n */\n deepLinkUrl?: string\n}\n\nexport type UseLiveActivityResult = {\n start: (options?: StartLiveActivityOptions) => Promise<void>\n update: (options?: UpdateLiveActivityOptions) => Promise<void>\n end: (options?: EndLiveActivityOptions) => Promise<void>\n isActive: boolean\n}\n\nconst normalizeSharedLiveActivityOptions = (\n options?: SharedLiveActivityOptions\n): SharedLiveActivityOptions | undefined => {\n if (!options) return undefined\n\n const normalizedOptions: SharedLiveActivityOptions = {}\n\n if (options.staleDate !== undefined) {\n if (options.staleDate < Date.now()) {\n logger.warn('Ignoring staleDate because it is in the past, the Live Activity would be dismissed immediately.')\n } else {\n normalizedOptions.staleDate = options.staleDate\n }\n }\n\n // Always include relevanceScore, defaulting to 0.0 if not provided\n const relevanceScore = options.relevanceScore ?? 0.0\n if (relevanceScore < 0 || relevanceScore > 1) {\n logger.warn('Ignoring relevanceScore because it is out of range [0.0, 1.0], using default 0.0')\n normalizedOptions.relevanceScore = 0.0\n } else {\n normalizedOptions.relevanceScore = relevanceScore\n }\n\n return Object.keys(normalizedOptions).length > 0 ? normalizedOptions : undefined\n}\n\nconst normalizeEndLiveActivityOptions = (\n options?: EndLiveActivityOptions\n): { dismissalPolicy?: { type: 'immediate' | 'after'; date?: number } } | undefined => {\n if (!options?.dismissalPolicy) return undefined\n\n if (typeof options.dismissalPolicy === 'string') {\n if (options.dismissalPolicy === 'immediate') {\n return { dismissalPolicy: { type: 'immediate' } }\n }\n } else if (typeof options.dismissalPolicy === 'object' && 'after' in options.dismissalPolicy) {\n return { dismissalPolicy: { type: 'after', date: options.dismissalPolicy.after } }\n }\n\n // Default to immediate if unrecognized\n return { dismissalPolicy: { type: 'immediate' } }\n}\n\n/**\n * React hook for managing Live Activities with automatic lifecycle handling.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the hook\n * @returns Object with start, update, end methods and isActive state\n *\n * @example\n * ```tsx\n * import { useLiveActivity, Voltra } from 'voltra'\n *\n * const MyLiveActivity = () => {\n * const { start, update, end, isActive } = useLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * autoStart: true,\n * autoUpdate: true\n * })\n *\n * return (\n * <View>\n * <Button title={isActive ? \"Stop\" : \"Start\"} onPress={isActive ? end : start} />\n * </View>\n * )\n * }\n * ```\n */\nexport const useLiveActivity = (\n variants: LiveActivityVariants,\n options?: UseLiveActivityOptions\n): UseLiveActivityResult => {\n const [targetId, setTargetId] = useState<string | null>(() => {\n if (options?.activityName) {\n return isLiveActivityActive(options.activityName) ? options.activityName : null\n }\n\n return null\n })\n const isActive = targetId !== null\n const optionsRef = useRef(options)\n const variantsRef = useRef(variants)\n const lastUpdateOptionsRef = useRef<UpdateLiveActivityOptions | undefined>(undefined)\n\n // Update refs when values change\n useEffect(() => {\n optionsRef.current = options\n }, [options])\n\n useEffect(() => {\n variantsRef.current = variants\n }, [variants])\n\n useUpdateOnHMR()\n\n const start = useCallback(async (options?: StartLiveActivityOptions) => {\n const id = await startLiveActivity(variantsRef.current, { ...optionsRef.current, ...options })\n setTargetId(id)\n }, [])\n\n const update = useCallback(\n async (options?: UpdateLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n const updateOptions = { ...optionsRef.current, ...options }\n lastUpdateOptionsRef.current = updateOptions\n await updateLiveActivity(targetId, variantsRef.current, updateOptions)\n },\n [targetId]\n )\n\n const end = useCallback(\n async (options?: EndLiveActivityOptions) => {\n if (!targetId) {\n return\n }\n\n await stopLiveActivity(targetId, options)\n setTargetId(null)\n },\n [targetId]\n )\n\n useEffect(() => {\n if (!options?.autoStart) {\n return\n }\n\n start()\n }, [options?.autoStart, start])\n\n useEffect(() => {\n if (!options?.autoUpdate) return\n update(lastUpdateOptionsRef.current)\n }, [options?.autoUpdate, update, variants])\n\n useEffect(() => {\n if (!targetId) return\n\n const subscription = addVoltraListener('stateChange', (event) => {\n if (event.activityName !== targetId) return\n\n if (event.activityState === 'dismissed' || event.activityState === 'ended') {\n // Live Activity is no longer active.\n setTargetId(null)\n }\n })\n\n return () => subscription.remove()\n }, [targetId])\n\n return {\n start,\n update,\n end,\n isActive,\n }\n}\n\n/**\n * Start a new Live Activity with the provided content variants.\n *\n * @param variants - The Live Activity content variants to display\n * @param options - Configuration options for the Live Activity\n * @returns Promise resolving to the activity ID\n *\n * @example\n * ```tsx\n * import { startLiveActivity, Voltra } from 'voltra'\n *\n * const activityId = await startLiveActivity({\n * minimal: <Voltra.Text>Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * activityName: 'my-activity',\n * deepLinkUrl: '/details',\n * relevanceScore: 0.8\n * })\n * ```\n */\nexport const startLiveActivity = async (\n variants: LiveActivityVariants,\n options?: StartLiveActivityOptions\n): Promise<string> => {\n if (!assertRunningOnApple()) return Promise.resolve('')\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n const targetId = await VoltraModule.startLiveActivity(payload, {\n target: 'liveActivity',\n deepLinkUrl: options?.deepLinkUrl,\n activityId: options?.activityName,\n ...normalizedSharedOptions,\n })\n return targetId\n}\n\n/**\n * Update an existing Live Activity with new content.\n *\n * @param targetId - The ID of the Live Activity to update\n * @param variants - The new Live Activity content variants\n * @param options - Update options like relevance score\n *\n * @example\n * ```tsx\n * import { updateLiveActivity, Voltra } from 'voltra'\n *\n * await updateLiveActivity('activity-123', {\n * minimal: <Voltra.Text>Updated: Live Activity</Voltra.Text>,\n * compact: <Voltra.HStack>...</Voltra.HStack>,\n * expanded: <Voltra.VStack>...</Voltra.VStack>\n * }, {\n * relevanceScore: 0.9\n * })\n * ```\n */\nexport const updateLiveActivity = async (\n targetId: string,\n variants: LiveActivityVariants,\n options?: UpdateLiveActivityOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderLiveActivityToString(variants)\n\n const normalizedSharedOptions = normalizeSharedLiveActivityOptions(options)\n return VoltraModule.updateLiveActivity(targetId, payload, normalizedSharedOptions)\n}\n\n/**\n * Stop a Live Activity.\n *\n * @param targetId - The ID of the Live Activity to stop\n * @param options - Options for how to end the activity\n *\n * @example\n * ```tsx\n * import { stopLiveActivity } from 'voltra'\n *\n * await stopLiveActivity('activity-123', { dismissalPolicy: 'immediate' })\n * ```\n */\nexport const stopLiveActivity = async (targetId: string, options?: EndLiveActivityOptions): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const normalizedOptions = normalizeEndLiveActivityOptions(options)\n return VoltraModule.endLiveActivity(targetId, normalizedOptions)\n}\n\n/**\n * Check if a Live Activity with the given name is currently active.\n *\n * @param activityName - The name of the Live Activity to check\n * @returns true if the activity is active, false otherwise\n *\n * @example\n * ```tsx\n * import { isLiveActivityActive } from 'voltra'\n *\n * if (isLiveActivityActive('my-activity')) {\n * console.log('Activity is running')\n * }\n * ```\n */\nexport const isLiveActivityActive = (activityName: string): boolean => {\n if (!assertRunningOnApple()) return false\n\n return VoltraModule.isLiveActivityActive(activityName)\n}\n\n/**\n * End all active Live Activities.\n *\n * This function stops and dismisses all currently running Live Activities in the app.\n * It's useful for cleanup operations, such as when the app is being closed or\n * when you want to reset all Live Activity states.\n *\n * @example\n * ```typescript\n * import { endAllLiveActivities } from 'voltra'\n *\n * // End all active Live Activities\n * await endAllLiveActivities()\n * ```\n */\nexport async function endAllLiveActivities(): Promise<void> {\n if (!assertRunningOnApple()) return Promise.resolve()\n return VoltraModule.endAllLiveActivities()\n}\n"]}
|
package/build/preload.d.ts
CHANGED
|
@@ -1,40 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
|
-
export type PreloadImageOptions = {
|
|
5
|
-
/**
|
|
6
|
-
* The URL to download the image from
|
|
7
|
-
*/
|
|
8
|
-
url: string;
|
|
9
|
-
/**
|
|
10
|
-
* The key to use when referencing this image (used as assetName in Image component)
|
|
11
|
-
*/
|
|
12
|
-
key: string;
|
|
13
|
-
/**
|
|
14
|
-
* HTTP method to use. Defaults to 'GET'.
|
|
15
|
-
*/
|
|
16
|
-
method?: 'GET' | 'POST' | 'PUT';
|
|
17
|
-
/**
|
|
18
|
-
* Optional HTTP headers to include in the request
|
|
19
|
-
*/
|
|
20
|
-
headers?: Record<string, string>;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Result of preloading images
|
|
24
|
-
*/
|
|
25
|
-
export type PreloadImagesResult = {
|
|
26
|
-
/**
|
|
27
|
-
* Keys of images that were successfully preloaded
|
|
28
|
-
*/
|
|
29
|
-
succeeded: string[];
|
|
30
|
-
/**
|
|
31
|
-
* Images that failed to preload, with error messages
|
|
32
|
-
*/
|
|
33
|
-
failed: {
|
|
34
|
-
key: string;
|
|
35
|
-
error: string;
|
|
36
|
-
}[];
|
|
37
|
-
};
|
|
1
|
+
import type { PreloadImageOptions, PreloadImagesResult } from './types.js';
|
|
2
|
+
export type { PreloadImageOptions, PreloadImagesResult } from './types.js';
|
|
38
3
|
/**
|
|
39
4
|
* Preload images to App Group storage for use in Live Activities.
|
|
40
5
|
*
|
package/build/preload.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAI1E,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAQ1E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgB/F;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzE"}
|
package/build/preload.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGvC,OAAO,YAAY,MAAM,mBAAmB,CAAA;AAK5C,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAA;IAC7D,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAA6B;IAC/D,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC,EAAE,CAAA;IACpH,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAO,YAAoB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC3B,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAChE,CAAC,CAAC;SACJ,CAAA;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,aAAwB;IACjE,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;QAAE,OAAM;IAE9C,IAAI,CAAC;QACH,MAAO,YAAoB,CAAC,oBAAoB,CAAC,aAAa,IAAI,IAAI,CAAC,CAAA;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAe;IACxD,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;QAAE,OAAM;IAE9C,IAAI,CAAC;QACH,MAAO,YAAoB,CAAC,oBAAoB,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC","sourcesContent":["import { Platform } from 'react-native'\n\nimport type { PreloadImageOptions, PreloadImagesResult } from './types.js'\nimport VoltraModule from './VoltraModule.js'\n\n// Re-export types for public API\nexport type { PreloadImageOptions, PreloadImagesResult } from './types.js'\n\nfunction assertIOS(name: string): boolean {\n const isIOS = Platform.OS === 'ios'\n if (!isIOS) console.error(`${name} is only available on iOS`)\n return isIOS\n}\n\n/**\n * Preload images to App Group storage for use in Live Activities.\n *\n * Downloaded images are stored in shared storage accessible by both the app\n * and the Live Activity widget extension. Images can then be referenced using\n * the `assetName` property in the Image component.\n *\n * Images must be less than 4KB to comply with ActivityKit limits.\n *\n * @param images - Array of images to preload\n * @returns Result indicating which images succeeded or failed\n *\n * @example\n * ```typescript\n * const result = await preloadImages([\n * {\n * url: 'https://example.com/album-art.jpg',\n * key: 'current-album',\n * headers: { 'Authorization': 'Bearer token' }\n * }\n * ])\n *\n * // Use in Live Activity\n * <Voltra.Image source={{ assetName: 'current-album' }} />\n * ```\n */\nexport async function preloadImages(images: PreloadImageOptions[]): Promise<PreloadImagesResult> {\n if (!assertIOS('preloadImages')) {\n return { succeeded: [], failed: images.map((img) => ({ key: img.key, error: 'Not available on this platform' })) }\n }\n\n try {\n return await (VoltraModule as any).preloadImages(images)\n } catch (error) {\n return {\n succeeded: [],\n failed: images.map((img) => ({\n key: img.key,\n error: error instanceof Error ? error.message : 'Unknown error',\n })),\n }\n }\n}\n\n/**\n * Reload Live Activities to pick up newly preloaded images.\n *\n * This triggers an update on the specified Live Activities (or all if none specified)\n * with their current content state, forcing SwiftUI to re-render and load the\n * newly preloaded images from App Group storage.\n *\n * @param activityNames - Optional array of activity names to reload. If omitted, reloads all.\n *\n * @example\n * ```typescript\n * // Preload new image\n * await preloadImages([{ url: 'https://example.com/new-art.jpg', key: 'album-art' }])\n *\n * // Reload specific activity to pick up the new image\n * await reloadLiveActivities(['music-player'])\n *\n * // Or reload all activities\n * await reloadLiveActivities()\n * ```\n */\nexport async function reloadLiveActivities(activityNames?: string[]): Promise<void> {\n if (!assertIOS('reloadLiveActivities')) return\n\n try {\n await (VoltraModule as any).reloadLiveActivities(activityNames ?? null)\n } catch (error) {\n console.error('Failed to reload Live Activities:', error)\n }\n}\n\n/**\n * Clear preloaded images from App Group storage.\n *\n * @param keys - Optional array of image keys to clear. If omitted, clears all preloaded images.\n *\n * @example\n * ```typescript\n * // Clear specific images\n * await clearPreloadedImages(['album-art', 'profile-pic'])\n *\n * // Clear all preloaded images\n * await clearPreloadedImages()\n * ```\n */\nexport async function clearPreloadedImages(keys?: string[]): Promise<void> {\n if (!assertIOS('clearPreloadedImages')) return\n\n try {\n await (VoltraModule as any).clearPreloadedImages(keys ?? null)\n } catch (error) {\n console.error('Failed to clear preloaded images:', error)\n }\n}\n"]}
|
package/build/types.d.ts
CHANGED
|
@@ -14,4 +14,62 @@ export type VoltraElementRef = {
|
|
|
14
14
|
$r: number;
|
|
15
15
|
};
|
|
16
16
|
export type VoltraNodeJson = VoltraElementJson | VoltraElementJson[] | VoltraElementRef | string;
|
|
17
|
+
/**
|
|
18
|
+
* Event subscription interface
|
|
19
|
+
*/
|
|
20
|
+
export type EventSubscription = {
|
|
21
|
+
remove: () => void;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Options for preloading a single image
|
|
25
|
+
*/
|
|
26
|
+
export type PreloadImageOptions = {
|
|
27
|
+
/**
|
|
28
|
+
* The URL to download the image from
|
|
29
|
+
*/
|
|
30
|
+
url: string;
|
|
31
|
+
/**
|
|
32
|
+
* The key to use when referencing this image (used as assetName in Image component)
|
|
33
|
+
*/
|
|
34
|
+
key: string;
|
|
35
|
+
/**
|
|
36
|
+
* HTTP method to use. Defaults to 'GET'.
|
|
37
|
+
*/
|
|
38
|
+
method?: 'GET' | 'POST' | 'PUT';
|
|
39
|
+
/**
|
|
40
|
+
* Optional HTTP headers to include in the request
|
|
41
|
+
*/
|
|
42
|
+
headers?: Record<string, string>;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Result of a failed image preload
|
|
46
|
+
*/
|
|
47
|
+
export type PreloadImageFailure = {
|
|
48
|
+
key: string;
|
|
49
|
+
error: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Result of preloading images
|
|
53
|
+
*/
|
|
54
|
+
export type PreloadImagesResult = {
|
|
55
|
+
/**
|
|
56
|
+
* Keys of images that were successfully preloaded
|
|
57
|
+
*/
|
|
58
|
+
succeeded: string[];
|
|
59
|
+
/**
|
|
60
|
+
* Images that failed to preload, with error messages
|
|
61
|
+
*/
|
|
62
|
+
failed: PreloadImageFailure[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Options for updating a home screen widget
|
|
66
|
+
*/
|
|
67
|
+
export type UpdateWidgetOptions = {
|
|
68
|
+
/**
|
|
69
|
+
* URL to open when the widget is tapped.
|
|
70
|
+
* Can be a full URL (e.g., "myapp://screen/details")
|
|
71
|
+
* or a path that will be prefixed with your app's URL scheme.
|
|
72
|
+
*/
|
|
73
|
+
deepLinkUrl?: string;
|
|
74
|
+
};
|
|
17
75
|
//# sourceMappingURL=types.d.ts.map
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,cAAc,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,cAAc,CAAA;IAClB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACpC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,iBAAiB,EAAE,GAAG,gBAAgB,GAAG,MAAM,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,cAAc,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,cAAc,CAAA;IAClB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACpC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,iBAAiB,EAAE,GAAG,gBAAgB,GAAG,MAAM,CAAA;AAEhG;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB;;OAEG;IACH,MAAM,EAAE,mBAAmB,EAAE,CAAA;CAC9B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA"}
|
package/build/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type VoltraPropValue = string | number | boolean | null | VoltraNodeJson // Allow component trees in props\n\nexport type VoltraElementJson = {\n t: number\n i?: string\n c?: VoltraNodeJson\n p?: Record<string, VoltraPropValue>\n}\n\n/**\n * Reference to a shared element by index.\n * Used for element deduplication - when the same JSX element (by reference)\n * appears multiple times in the tree.\n */\nexport type VoltraElementRef = {\n $r: number\n}\n\nexport type VoltraNodeJson = VoltraElementJson | VoltraElementJson[] | VoltraElementRef | string\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type VoltraPropValue = string | number | boolean | null | VoltraNodeJson // Allow component trees in props\n\nexport type VoltraElementJson = {\n t: number\n i?: string\n c?: VoltraNodeJson\n p?: Record<string, VoltraPropValue>\n}\n\n/**\n * Reference to a shared element by index.\n * Used for element deduplication - when the same JSX element (by reference)\n * appears multiple times in the tree.\n */\nexport type VoltraElementRef = {\n $r: number\n}\n\nexport type VoltraNodeJson = VoltraElementJson | VoltraElementJson[] | VoltraElementRef | string\n\n/**\n * Event subscription interface\n */\nexport type EventSubscription = {\n remove: () => void\n}\n\n/**\n * Options for preloading a single image\n */\nexport type PreloadImageOptions = {\n /**\n * The URL to download the image from\n */\n url: string\n /**\n * The key to use when referencing this image (used as assetName in Image component)\n */\n key: string\n /**\n * HTTP method to use. Defaults to 'GET'.\n */\n method?: 'GET' | 'POST' | 'PUT'\n /**\n * Optional HTTP headers to include in the request\n */\n headers?: Record<string, string>\n}\n\n/**\n * Result of a failed image preload\n */\nexport type PreloadImageFailure = {\n key: string\n error: string\n}\n\n/**\n * Result of preloading images\n */\nexport type PreloadImagesResult = {\n /**\n * Keys of images that were successfully preloaded\n */\n succeeded: string[]\n /**\n * Images that failed to preload, with error messages\n */\n failed: PreloadImageFailure[]\n}\n\n/**\n * Options for updating a home screen widget\n */\nexport type UpdateWidgetOptions = {\n /**\n * URL to open when the widget is tapped.\n * Can be a full URL (e.g., \"myapp://screen/details\")\n * or a path that will be prefixed with your app's URL scheme.\n */\n deepLinkUrl?: string\n}\n"]}
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
+
import type { UpdateWidgetOptions } from '../types.js';
|
|
1
2
|
import { WidgetVariants } from './types.js';
|
|
2
|
-
|
|
3
|
-
* Options for updating a home screen widget
|
|
4
|
-
*/
|
|
5
|
-
export type UpdateWidgetOptions = {
|
|
6
|
-
/**
|
|
7
|
-
* URL to open when the widget is tapped.
|
|
8
|
-
* Can be a full URL (e.g., "myapp://screen/details")
|
|
9
|
-
* or a path that will be prefixed with your app's URL scheme.
|
|
10
|
-
*/
|
|
11
|
-
deepLinkUrl?: string;
|
|
12
|
-
};
|
|
3
|
+
export type { UpdateWidgetOptions } from '../types.js';
|
|
13
4
|
/**
|
|
14
5
|
* Update a home screen widget with new content.
|
|
15
6
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-api.d.ts","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"widget-api.d.ts","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAItD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAG3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,UAAU,cAAc,EACxB,UAAU,mBAAmB,KAC5B,OAAO,CAAC,IAAI,CAQd,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,GAAU,YAAY,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAItE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAIhE,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,IAAI,CAIpD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-api.js","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"widget-api.js","sourceRoot":"","sources":["../../src/widgets/widget-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACvE,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAMpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAgB,EAChB,QAAwB,EACxB,OAA6B,EACd,EAAE;IACjB,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAE9C,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE;QAClD,WAAW,EAAE,OAAO,EAAE,WAAW;KAClC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,SAAoB,EAAiB,EAAE;IACzE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,aAAa,CAAC,SAAS,IAAI,IAAI,CAAC,CAAA;AACtD,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;IACnE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;AAC3C,CAAC,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAmB,EAAE;IACvD,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAErD,OAAO,YAAY,CAAC,eAAe,EAAE,CAAA;AACvC,CAAC,CAAA","sourcesContent":["import type { UpdateWidgetOptions } from '../types.js'\nimport { assertRunningOnApple } from '../utils/assertRunningOnApple.js'\nimport VoltraModule from '../VoltraModule.js'\nimport { renderWidgetToString } from './renderer.js'\nimport { WidgetVariants } from './types.js'\n\n// Re-export type for public API\nexport type { UpdateWidgetOptions } from '../types.js'\n\n/**\n * Update a home screen widget with new content.\n *\n * The content will be stored in App Group storage and the widget timeline\n * will be reloaded to display the new content.\n *\n * @param widgetId - The widget identifier (as defined in your config plugin)\n * @param variants - An object mapping widget families to specific content.\n * Each key corresponds to a widget size family.\n * @param options - Optional settings like deep link URL\n *\n * @example Different content per size\n * ```tsx\n * import { updateWidget, Voltra } from 'voltra'\n *\n * await updateWidget('weather', {\n * systemSmall: <Voltra.Text fontSize={32}>72°F</Voltra.Text>,\n * systemMedium: (\n * <Voltra.HStack>\n * <Voltra.Text fontSize={32}>72°F</Voltra.Text>\n * <Voltra.VStack>\n * <Voltra.Text>Sunny</Voltra.Text>\n * <Voltra.Text>High: 78° Low: 65°</Voltra.Text>\n * </Voltra.VStack>\n * </Voltra.HStack>\n * ),\n * }, { deepLinkUrl: '/weather' })\n * ```\n */\nexport const updateWidget = async (\n widgetId: string,\n variants: WidgetVariants,\n options?: UpdateWidgetOptions\n): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n const payload = renderWidgetToString(variants)\n\n return VoltraModule.updateWidget(widgetId, payload, {\n deepLinkUrl: options?.deepLinkUrl,\n })\n}\n\n/**\n * Reload widget timelines to refresh their content.\n *\n * Use this after updating data that widgets depend on (e.g., after preloading\n * new images) to force them to re-render.\n *\n * @param widgetIds - Optional array of widget IDs to reload. If omitted, reloads all widgets.\n *\n * @example\n * ```typescript\n * // Reload specific widgets\n * await reloadWidgets(['weather', 'calendar'])\n *\n * // Reload all widgets\n * await reloadWidgets()\n * ```\n */\nexport const reloadWidgets = async (widgetIds?: string[]): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.reloadWidgets(widgetIds ?? null)\n}\n\n/**\n * Clear a widget's stored data.\n *\n * This removes the JSON content and deep link URL for the specified widget,\n * causing it to show its placeholder state.\n *\n * @param widgetId - The widget identifier to clear\n *\n * @example\n * ```typescript\n * await clearWidget('weather')\n * ```\n */\nexport const clearWidget = async (widgetId: string): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.clearWidget(widgetId)\n}\n\n/**\n * Clear all widgets' stored data.\n *\n * This removes the JSON content and deep link URLs for all configured widgets,\n * causing them to show their placeholder states.\n *\n * @example\n * ```typescript\n * await clearAllWidgets()\n * ```\n */\nexport const clearAllWidgets = async (): Promise<void> => {\n if (!assertRunningOnApple()) return Promise.resolve()\n\n return VoltraModule.clearAllWidgets()\n}\n"]}
|
package/ios/Voltra.podspec
CHANGED
|
@@ -22,26 +22,11 @@ Pod::Spec.new do |s|
|
|
|
22
22
|
'DEFINES_MODULE' => 'YES',
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
s.default_subspecs = 'Core'
|
|
25
|
+
s.dependency 'ExpoModulesCore'
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"app/**/*.swift",
|
|
34
|
-
"shared/**/*.swift",
|
|
35
|
-
"ui/**/*.swift", # Add shared UI code
|
|
36
|
-
]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Widget subspec: Widget extension code
|
|
40
|
-
s.subspec 'Widget' do |ss|
|
|
41
|
-
ss.source_files = [
|
|
42
|
-
"shared/**/*.swift",
|
|
43
|
-
"ui/**/*.swift", # Add shared UI code
|
|
44
|
-
"target/**/*.swift", # Widget-specific files only
|
|
45
|
-
]
|
|
46
|
-
end
|
|
27
|
+
s.source_files = [
|
|
28
|
+
"app/**/*.swift",
|
|
29
|
+
"ui/**/*.swift",
|
|
30
|
+
"shared/**/*.swift",
|
|
31
|
+
]
|
|
47
32
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'VoltraWidget'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = 'Voltra Widget Extension support.'
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platforms = {
|
|
14
|
+
:ios => '16.2',
|
|
15
|
+
}
|
|
16
|
+
s.swift_version = '5.9'
|
|
17
|
+
s.source = { git: 'https://github.com/callstackincubator/voltra' }
|
|
18
|
+
s.static_framework = true
|
|
19
|
+
|
|
20
|
+
# Swift/Objective-C compatibility
|
|
21
|
+
s.pod_target_xcconfig = {
|
|
22
|
+
'DEFINES_MODULE' => 'YES',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
s.source_files = [
|
|
26
|
+
"ui/**/*.swift",
|
|
27
|
+
"shared/**/*.swift",
|
|
28
|
+
"target/**/*.swift",
|
|
29
|
+
]
|
|
30
|
+
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import SwiftUI
|
|
2
2
|
|
|
3
|
-
// TODO: Refactor to NOT overwrite defaults.
|
|
4
3
|
enum StyleConverter {
|
|
5
4
|
static func convert(_ js: [String: Any]) -> (LayoutStyle, DecorationStyle, RenderingStyle, TextStyle) {
|
|
6
5
|
(parseLayout(js), parseDecoration(js), parseRendering(js), parseText(js))
|
|
@@ -12,9 +11,9 @@ enum StyleConverter {
|
|
|
12
11
|
let flexGrow = JSStyleParser.number(js["flexGrow"]) ?? 0
|
|
13
12
|
let finalFlex = max(flexVal, flexGrow)
|
|
14
13
|
|
|
15
|
-
// If it flexes, give it priority 1 so it beats fixed items
|
|
16
|
-
//
|
|
17
|
-
let priority: Double = finalFlex > 0 ? 1.0 :
|
|
14
|
+
// If it flexes, give it priority 1 so it beats fixed items.
|
|
15
|
+
// Only set layoutPriority when flex is active; nil means "don't apply modifier".
|
|
16
|
+
let priority: Double? = finalFlex > 0 ? 1.0 : nil
|
|
18
17
|
|
|
19
18
|
// Position parsing (offsetX/offsetY -> CGPoint)
|
|
20
19
|
var position: CGPoint?
|
|
@@ -26,8 +25,8 @@ enum StyleConverter {
|
|
|
26
25
|
position = CGPoint(x: 0, y: offsetY)
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
// zIndex
|
|
30
|
-
let zIndex = JSStyleParser.number(js["zIndex"])
|
|
28
|
+
// zIndex: only set if explicitly provided in JS
|
|
29
|
+
let zIndex = JSStyleParser.number(js["zIndex"])
|
|
31
30
|
|
|
32
31
|
return LayoutStyle(
|
|
33
32
|
// Dimensions
|
|
@@ -49,7 +48,7 @@ enum StyleConverter {
|
|
|
49
48
|
|
|
50
49
|
// Positioning
|
|
51
50
|
position: position,
|
|
52
|
-
zIndex: zIndex
|
|
51
|
+
zIndex: zIndex.map { Double($0) }
|
|
53
52
|
)
|
|
54
53
|
}
|
|
55
54
|
|
package/package.json
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "voltra",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Build Live Activities with JSX in React Native",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"build",
|
|
9
|
-
"plugin/build",
|
|
10
|
-
"app.plugin.js",
|
|
11
|
-
"expo-module.config.json",
|
|
12
|
-
"ios-files",
|
|
13
|
-
"ios"
|
|
14
|
-
],
|
|
15
7
|
"exports": {
|
|
16
8
|
".": {
|
|
17
9
|
"types": "./build/index.d.ts",
|
|
@@ -57,7 +57,7 @@ function generateWidgetBundleSwift(widgets) {
|
|
|
57
57
|
|
|
58
58
|
import SwiftUI
|
|
59
59
|
import WidgetKit
|
|
60
|
-
import
|
|
60
|
+
import VoltraWidget
|
|
61
61
|
|
|
62
62
|
@main
|
|
63
63
|
struct VoltraWidgetBundle: WidgetBundle {
|
|
@@ -90,7 +90,7 @@ function generateDefaultWidgetBundleSwift() {
|
|
|
90
90
|
|
|
91
91
|
import SwiftUI
|
|
92
92
|
import WidgetKit
|
|
93
|
-
import
|
|
93
|
+
import VoltraWidget // Import Voltra widgets
|
|
94
94
|
|
|
95
95
|
@main
|
|
96
96
|
struct VoltraWidgetBundle: WidgetBundle {
|
|
@@ -26,7 +26,7 @@ target '${targetName}' do
|
|
|
26
26
|
voltra_module = JSON.parse(${backtick}npx expo-modules-autolinking search -p apple --json --project-root #{project_root}${backtick})
|
|
27
27
|
podspec_dir_path = Pathname.new(File.join(voltra_module['${libraryName}']['path'], 'ios')).relative_path_from(Pathname.new(__dir__)).to_path
|
|
28
28
|
|
|
29
|
-
pod '
|
|
29
|
+
pod 'VoltraWidget', :path => podspec_dir_path
|
|
30
30
|
end`;
|
|
31
31
|
}
|
|
32
32
|
/**
|