despia-native 1.0.0 → 1.0.1
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/README.md +52 -51
- package/index.d.ts +4 -6
- package/index.js +184 -0
- package/package.json +25 -5
package/README.md
CHANGED
|
@@ -27,11 +27,11 @@ npm install despia
|
|
|
27
27
|
```javascript
|
|
28
28
|
import despia from 'despia';
|
|
29
29
|
|
|
30
|
-
// Execute a Despia protocol command (no response)
|
|
31
|
-
|
|
30
|
+
// Execute a Despia protocol command (no response needed)
|
|
31
|
+
despia('lighthaptic://');
|
|
32
32
|
|
|
33
|
-
// Execute command and watch for response variables
|
|
34
|
-
const result = await despia('getappversion://', ['versionNumber', 'bundleNumber']
|
|
33
|
+
// Execute command and watch for response variables (await needed)
|
|
34
|
+
const result = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
|
|
35
35
|
console.log(result); // { versionNumber: '1.0.0', bundleNumber: '123' }
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -39,74 +39,74 @@ console.log(result); // { versionNumber: '1.0.0', bundleNumber: '123' }
|
|
|
39
39
|
|
|
40
40
|
```javascript
|
|
41
41
|
// Native Widgets
|
|
42
|
-
|
|
42
|
+
despia('widget://${svg}?refresh=${refresh_time}');
|
|
43
43
|
|
|
44
44
|
// RevenueCat In-App Purchases
|
|
45
|
-
|
|
45
|
+
despia('revenuecat://purchase?external_id=user_777&product=monthly_premium');
|
|
46
46
|
|
|
47
47
|
// Contact Permissions
|
|
48
|
-
|
|
48
|
+
despia('requestcontactpermission://');
|
|
49
49
|
const contacts = await despia('readcontacts://', ['contacts']);
|
|
50
50
|
|
|
51
51
|
// Background Location
|
|
52
|
-
|
|
52
|
+
despia('backgroundlocationon://');
|
|
53
53
|
// Use native browser geolocation API (not despia wrapper)
|
|
54
54
|
const watchId = navigator.geolocation.watchPosition(
|
|
55
55
|
(position) => console.log('Location:', position),
|
|
56
56
|
(error) => console.error('Location error:', error)
|
|
57
57
|
);
|
|
58
58
|
// To stop
|
|
59
|
-
|
|
59
|
+
despia('backgroundlocationoff://');
|
|
60
60
|
navigator.geolocation.clearWatch(watchId);
|
|
61
61
|
|
|
62
62
|
// Push Notifications
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
despia('registerpush://');
|
|
64
|
+
despia('sendlocalpushmsg://push.send?s=60&msg=Hello&!#New Message&!#https://myapp.com');
|
|
65
65
|
const oneSignalData = await despia('getonesignalplayerid://', ['onesignalplayerid']);
|
|
66
66
|
|
|
67
67
|
// Haptic Feedback
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
despia('lighthaptic://');
|
|
69
|
+
despia('heavyhaptic://');
|
|
70
|
+
despia('successhaptic://');
|
|
71
|
+
despia('warninghaptic://');
|
|
72
|
+
despia('errorhaptic://');
|
|
73
73
|
|
|
74
74
|
// App Information
|
|
75
75
|
const appInfo = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
|
|
76
76
|
const deviceInfo = await despia('get-uuid://', ['uuid']);
|
|
77
77
|
|
|
78
78
|
// Screenshots and Scanning
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
despia('takescreenshot://');
|
|
80
|
+
despia('scanningmode://auto');
|
|
81
|
+
despia('scanningmode://on');
|
|
82
|
+
despia('scanningmode://off');
|
|
83
83
|
|
|
84
84
|
// Store and Location
|
|
85
85
|
const storeData = await despia('getstorelocation://', ['storeLocation']);
|
|
86
86
|
|
|
87
87
|
// Image and File Operations
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
despia('savethisimage://?url=${image_url}');
|
|
89
|
+
despia('file://${file_url}');
|
|
90
90
|
|
|
91
91
|
// App Control
|
|
92
|
-
|
|
92
|
+
despia('reset://');
|
|
93
93
|
const trackingData = await despia('user-disable-tracking://', ['trackingDisabled']);
|
|
94
94
|
|
|
95
95
|
// UI Controls
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
despia('spinneron://');
|
|
97
|
+
despia('spinneroff://');
|
|
98
|
+
despia('hidebars://on');
|
|
99
|
+
despia('hidebars://off');
|
|
100
100
|
|
|
101
101
|
// Sharing
|
|
102
|
-
|
|
102
|
+
despia('shareapp://message?=${message}&url=${url}');
|
|
103
103
|
|
|
104
104
|
// Status Bar Styling
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
despia('statusbarcolor://{255, 255, 255}');
|
|
106
|
+
despia('statusbartextcolor://{black}');
|
|
107
107
|
|
|
108
108
|
// Biometric Authentication
|
|
109
|
-
|
|
109
|
+
despia('bioauth://');
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
### Direct Window Variable Access
|
|
@@ -121,13 +121,13 @@ const appVersion = despia.appVersion;
|
|
|
121
121
|
### Advanced Usage with Variable Watching
|
|
122
122
|
|
|
123
123
|
```javascript
|
|
124
|
-
// Watch multiple response variables
|
|
125
|
-
const appData = await despia('getappversion://', ['versionNumber', 'bundleNumber']
|
|
124
|
+
// Watch multiple response variables
|
|
125
|
+
const appData = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
|
|
126
126
|
|
|
127
127
|
// Chain multiple Despia commands
|
|
128
|
-
|
|
129
|
-
await despia('getappversion://', ['versionNumber', 'bundleNumber']);
|
|
130
|
-
|
|
128
|
+
despia('lighthaptic://');
|
|
129
|
+
const appData2 = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
|
|
130
|
+
despia('successhaptic://');
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
### Background Location Workflow
|
|
@@ -136,7 +136,7 @@ Background location tracking requires a two-step process:
|
|
|
136
136
|
|
|
137
137
|
```javascript
|
|
138
138
|
// Step 1: Enable native background location tracking via Despia
|
|
139
|
-
|
|
139
|
+
despia('backgroundlocationon://');
|
|
140
140
|
|
|
141
141
|
// Step 2: Use native browser geolocation API for actual tracking (not despia wrapper)
|
|
142
142
|
const watchId = navigator.geolocation.watchPosition(
|
|
@@ -160,7 +160,7 @@ const watchId = navigator.geolocation.watchPosition(
|
|
|
160
160
|
|
|
161
161
|
// To stop tracking:
|
|
162
162
|
// Step 1: Disable native background tracking via Despia
|
|
163
|
-
|
|
163
|
+
despia('backgroundlocationoff://');
|
|
164
164
|
// Step 2: Clear browser geolocation watch (native API)
|
|
165
165
|
navigator.geolocation.clearWatch(watchId);
|
|
166
166
|
```
|
|
@@ -169,7 +169,7 @@ navigator.geolocation.clearWatch(watchId);
|
|
|
169
169
|
|
|
170
170
|
```javascript
|
|
171
171
|
// Step 1: Request contact permission
|
|
172
|
-
|
|
172
|
+
despia('requestcontactpermission://');
|
|
173
173
|
|
|
174
174
|
// Step 2: Read contacts after permission granted
|
|
175
175
|
const contactData = await despia('readcontacts://', ['contacts']);
|
|
@@ -182,13 +182,13 @@ All haptic feedback commands have no response - they provide immediate tactile f
|
|
|
182
182
|
|
|
183
183
|
```javascript
|
|
184
184
|
// Basic haptic feedback
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
despia('lighthaptic://'); // Light haptic feedback - subtle vibration
|
|
186
|
+
despia('heavyhaptic://'); // Heavy haptic feedback - strong vibration
|
|
187
187
|
|
|
188
188
|
// Contextual haptic feedback
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
despia('successhaptic://'); // Success haptic feedback - positive confirmation
|
|
190
|
+
despia('warninghaptic://'); // Warning haptic feedback - attention alert
|
|
191
|
+
despia('errorhaptic://'); // Error haptic feedback - negative feedback
|
|
192
192
|
|
|
193
193
|
// Use cases:
|
|
194
194
|
// - Button press feedback (light/heavy)
|
|
@@ -248,7 +248,7 @@ window.bioauthUnavailable = function() {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// Step 3: Trigger biometric authentication
|
|
251
|
-
|
|
251
|
+
despia('bioauth://');
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
### App Information & Device Data
|
|
@@ -329,8 +329,6 @@ Access native safe area insets via CSS custom properties:
|
|
|
329
329
|
.my-element {
|
|
330
330
|
padding-top: var(--safe-area-top);
|
|
331
331
|
padding-bottom: var(--safe-area-bottom);
|
|
332
|
-
padding-left: var(--safe-area-left);
|
|
333
|
-
padding-right: var(--safe-area-right);
|
|
334
332
|
}
|
|
335
333
|
|
|
336
334
|
/* Full height with safe area consideration */
|
|
@@ -339,19 +337,22 @@ Access native safe area insets via CSS custom properties:
|
|
|
339
337
|
}
|
|
340
338
|
```
|
|
341
339
|
|
|
340
|
+
**Note:** Despia only supports top and bottom safe area insets. Left and right safe area variables are not available.
|
|
341
|
+
|
|
342
342
|
These CSS variables are automatically provided by the Despia native runtime and represent the device's safe area insets (notches, home indicators, etc.).
|
|
343
343
|
|
|
344
344
|
|
|
345
345
|
|
|
346
346
|
## API Reference
|
|
347
347
|
|
|
348
|
-
### `despia(command, watch
|
|
348
|
+
### `despia(command, watch?)`
|
|
349
349
|
|
|
350
|
-
- **command** (string): The Despia protocol command (e.g., `'
|
|
350
|
+
- **command** (string): The Despia protocol command (e.g., `'lighthaptic://'`)
|
|
351
351
|
- **watch** (string[], optional): Array of variable names to watch for in the response
|
|
352
|
-
- **timeout** (number, optional): Timeout in milliseconds (default: 10000)
|
|
353
352
|
|
|
354
|
-
Returns a Promise that resolves when all watched variables are available
|
|
353
|
+
Returns a Promise that resolves when all watched variables are available:
|
|
354
|
+
- **Single variable**: 5-second timeout with simple observation
|
|
355
|
+
- **Multiple variables**: Uses VariableTracker with 5-minute auto-cleanup
|
|
355
356
|
|
|
356
357
|
### Direct Property Access
|
|
357
358
|
|
package/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* Despia protocol command types
|
|
5
5
|
*/
|
|
6
6
|
type DespiaCommand =
|
|
7
|
-
| `applinks://${string}`
|
|
8
7
|
| `widget://${string}`
|
|
9
8
|
| `revenuecat://${string}`
|
|
10
9
|
| `requestcontactpermission://`
|
|
@@ -70,16 +69,15 @@ interface DespiaFunction {
|
|
|
70
69
|
* Execute a Despia protocol command and watch for specific response variables
|
|
71
70
|
* @param command - The Despia protocol command
|
|
72
71
|
* @param watch - Array of variable names to watch for in the response
|
|
73
|
-
* @
|
|
74
|
-
* @returns Promise that resolves with the watched variables or times out
|
|
72
|
+
* @returns Promise that resolves with the watched variables
|
|
75
73
|
*
|
|
76
74
|
* @example
|
|
77
75
|
* ```typescript
|
|
78
|
-
* const result = await despia('
|
|
79
|
-
* const purchase = await despia('purchase
|
|
76
|
+
* const result = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
|
|
77
|
+
* const purchase = await despia('revenuecat://purchase?external_id=user_777&product=monthly_premium', ['purchaseResult', 'transactionID']);
|
|
80
78
|
* ```
|
|
81
79
|
*/
|
|
82
|
-
<T = Record<string, any>>(command: DespiaCommand, watch: string[]
|
|
80
|
+
<T = Record<string, any>>(command: DespiaCommand, watch: string[]): Promise<T>;
|
|
83
81
|
|
|
84
82
|
/**
|
|
85
83
|
* Access any window variable directly (useful for Despia response data)
|
package/index.js
CHANGED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// index.js
|
|
2
|
+
(function (root, factory) {
|
|
3
|
+
if (typeof define === 'function' && define.amd) {
|
|
4
|
+
define([], factory);
|
|
5
|
+
} else if (typeof module === 'object' && module.exports) {
|
|
6
|
+
module.exports = factory();
|
|
7
|
+
} else {
|
|
8
|
+
root.despia = factory();
|
|
9
|
+
}
|
|
10
|
+
}(typeof self !== 'undefined' ? self : this, function () {
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
// Command queue for sequential execution
|
|
14
|
+
const commandQueue = [];
|
|
15
|
+
let processing = false;
|
|
16
|
+
|
|
17
|
+
// Process command queue with 1ms delay between commands
|
|
18
|
+
function processQueue() {
|
|
19
|
+
if (processing || commandQueue.length === 0) return;
|
|
20
|
+
|
|
21
|
+
processing = true;
|
|
22
|
+
const { command, native } = commandQueue.shift();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
native({ command });
|
|
26
|
+
} catch (e) {}
|
|
27
|
+
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
processing = false;
|
|
30
|
+
processQueue();
|
|
31
|
+
}, 1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Add command to queue
|
|
35
|
+
function queueCommand(command) {
|
|
36
|
+
const native = typeof window !== 'undefined'
|
|
37
|
+
? window.despia
|
|
38
|
+
: (typeof global !== 'undefined' ? global.despia : null);
|
|
39
|
+
|
|
40
|
+
if (native) {
|
|
41
|
+
commandQueue.push({ command, native });
|
|
42
|
+
processQueue();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Simple variable observer with 5-second timeout
|
|
47
|
+
function observeDespiaVariable(variableName, callback, timeout = 5000) {
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
|
|
50
|
+
function checkVariable() {
|
|
51
|
+
if (window[variableName] !== undefined) {
|
|
52
|
+
callback(window[variableName]);
|
|
53
|
+
} else if (Date.now() - startTime < timeout) {
|
|
54
|
+
setTimeout(checkVariable, 100);
|
|
55
|
+
} else {
|
|
56
|
+
console.error(`Despia timeout: ${variableName} was not set within ${timeout} ms`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
checkVariable();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// VariableTracker class for complex multi-variable observation
|
|
64
|
+
class VariableTracker {
|
|
65
|
+
constructor(variables, onReady) {
|
|
66
|
+
this.variables = variables;
|
|
67
|
+
this.onReady = onReady;
|
|
68
|
+
this.triggered = false;
|
|
69
|
+
this.processing = false;
|
|
70
|
+
|
|
71
|
+
// Create tracker element
|
|
72
|
+
this.tracker = document.createElement('div');
|
|
73
|
+
this.tracker.style.display = 'none';
|
|
74
|
+
document.body.appendChild(this.tracker);
|
|
75
|
+
|
|
76
|
+
// Setup observer with debounce
|
|
77
|
+
let timeout;
|
|
78
|
+
this.observer = new MutationObserver(() => {
|
|
79
|
+
clearTimeout(timeout);
|
|
80
|
+
timeout = setTimeout(() => this.check(), 100);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Start observing and checking
|
|
84
|
+
this.observer.observe(this.tracker, { attributes: true });
|
|
85
|
+
this.check();
|
|
86
|
+
this.interval = setInterval(() => this.check(), 1000);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
check() {
|
|
90
|
+
if (this.processing || this.triggered) return;
|
|
91
|
+
this.processing = true;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const values = {};
|
|
95
|
+
const allSet = this.variables.every(name => {
|
|
96
|
+
const val = window[name];
|
|
97
|
+
// Check for undefined, "n/a" string, or null values
|
|
98
|
+
if (val === undefined || val === "n/a" || val === null) return false;
|
|
99
|
+
values[name] = val;
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (allSet && !this.triggered) {
|
|
104
|
+
this.triggered = true;
|
|
105
|
+
this.cleanup();
|
|
106
|
+
this.onReady(values);
|
|
107
|
+
}
|
|
108
|
+
} catch (err) {
|
|
109
|
+
console.error("Error during check:", err);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this.processing = false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
cleanup() {
|
|
116
|
+
this.observer.disconnect();
|
|
117
|
+
clearInterval(this.interval);
|
|
118
|
+
this.tracker.remove();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Observe variables - simple for single variable, tracker for multiple
|
|
123
|
+
function observeVariables(variables, timeout) {
|
|
124
|
+
if (!variables || variables.length === 0) {
|
|
125
|
+
return Promise.resolve({});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (variables.length === 1) {
|
|
129
|
+
// Simple single variable observation with 5-second timeout
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
observeDespiaVariable(variables[0], (value) => {
|
|
132
|
+
resolve({ [variables[0]]: value });
|
|
133
|
+
}, 5000);
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
// Multiple variables - use VariableTracker (no timeout, expires after 5 minutes)
|
|
137
|
+
return new Promise((resolve) => {
|
|
138
|
+
const tracker = new VariableTracker(variables, resolve);
|
|
139
|
+
// Auto-cleanup after 5 minutes if not triggered
|
|
140
|
+
setTimeout(() => {
|
|
141
|
+
if (!tracker.triggered) {
|
|
142
|
+
tracker.cleanup();
|
|
143
|
+
resolve({});
|
|
144
|
+
}
|
|
145
|
+
}, 300000); // 5 minutes
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Main despia function
|
|
151
|
+
function despiaFunction(command, watch = []) {
|
|
152
|
+
// Queue command execution
|
|
153
|
+
queueCommand(command);
|
|
154
|
+
|
|
155
|
+
// No variables to watch
|
|
156
|
+
if (!watch || watch.length === 0) {
|
|
157
|
+
return Promise.resolve();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Watch for variables (timeout handled internally)
|
|
161
|
+
return observeVariables(watch);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Create proxy for window access
|
|
165
|
+
const despia = new Proxy(despiaFunction, {
|
|
166
|
+
get(target, prop) {
|
|
167
|
+
if (prop in target || prop === 'then' || typeof prop === 'symbol') {
|
|
168
|
+
return target[prop];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (typeof window !== 'undefined' && prop in window) {
|
|
172
|
+
return window[prop];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return undefined;
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
apply(target, thisArg, args) {
|
|
179
|
+
return target(...args);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return despia;
|
|
184
|
+
}));
|
package/package.json
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "despia-native",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "JavaScript SDK for Despia native integrations with command queuing and variable watching",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
|
-
"keywords": [
|
|
8
|
+
"keywords": [
|
|
9
|
+
"despia",
|
|
10
|
+
"sdk",
|
|
11
|
+
"mobile",
|
|
12
|
+
"native",
|
|
13
|
+
"bridge",
|
|
14
|
+
"applinks",
|
|
15
|
+
"biometric",
|
|
16
|
+
"purchase",
|
|
17
|
+
"push",
|
|
18
|
+
"camera",
|
|
19
|
+
"location",
|
|
20
|
+
"download",
|
|
21
|
+
"haptic",
|
|
22
|
+
"widget",
|
|
23
|
+
"revenuecat",
|
|
24
|
+
"contacts"
|
|
25
|
+
],
|
|
9
26
|
"author": "Despia Native <developers@despia.com>",
|
|
10
27
|
"license": "MIT",
|
|
11
|
-
|
|
12
28
|
"scripts": {
|
|
13
29
|
"test": "echo \"No tests specified\"",
|
|
14
30
|
"prepublishOnly": "npm test"
|
|
15
31
|
},
|
|
16
|
-
"files": [
|
|
17
|
-
|
|
32
|
+
"files": [
|
|
33
|
+
"index.js",
|
|
34
|
+
"index.d.ts",
|
|
35
|
+
"README.md"
|
|
36
|
+
]
|
|
37
|
+
}
|