@bty/feed_app-runtime-sdk 0.1.3 → 0.1.5
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 +32 -19
- package/dist/ai/index.js +1 -1
- package/dist/chunk-H42VJJAC.js +1 -0
- package/dist/chunk-V73IHZAF.js +1 -0
- package/dist/device/index.d.ts +81 -69
- package/dist/device/index.js +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -1
- package/dist/types-CLujY9ck.d.ts +15 -0
- package/dist/user/index.d.ts +2 -2
- package/dist/user/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AKZVV563.js +0 -1
- package/dist/chunk-ALNJCFV4.js +0 -1
- package/dist/types-DryABknE.d.ts +0 -23
package/README.md
CHANGED
|
@@ -20,15 +20,16 @@ Two failure styles, split by sub-entry — know which you're calling:
|
|
|
20
20
|
| Sub-entry | On failure | Why |
|
|
21
21
|
|---|---|---|
|
|
22
22
|
| `/ai` | **throws** a typed `AiError` subclass | callers must distinguish 401 / 402 / 429 / 4xx / 5xx to react correctly |
|
|
23
|
-
| `/user
|
|
23
|
+
| `/user` | **returns an empty value** (never throws) | no host user context is a normal runtime state |
|
|
24
|
+
| `/device` | **returns `DeviceResult<T>`** (never throws) | denied / cancelled / unsupported native capability is normal control flow — branch on `result.ok` |
|
|
24
25
|
|
|
25
26
|
Empty value = `""` for the one string API (`getAuthTokenAsync`), `null`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
for `getUserInfoAsync`. Device APIs use one envelope instead:
|
|
28
|
+
`{ ok: true, source, value }` or
|
|
29
|
+
`{ ok: false, source, reason, errorCode?, errorMessage? }`.
|
|
29
30
|
|
|
30
31
|
Rule of thumb: wrap `/ai` calls in `try/catch`; branch on the return value for
|
|
31
|
-
`/user`
|
|
32
|
+
`/user`; branch on `result.ok` for `/device`.
|
|
32
33
|
|
|
33
34
|
## User
|
|
34
35
|
|
|
@@ -152,7 +153,7 @@ entry do not need to install React.
|
|
|
152
153
|
## Device
|
|
153
154
|
|
|
154
155
|
Six host-bridged capabilities, each with a layered fallback: native App bridge
|
|
155
|
-
→ iframe parent relay → browser Web API →
|
|
156
|
+
→ iframe parent relay → browser Web API → SDK failure. Import the `device`
|
|
156
157
|
namespace, or the individual capabilities for tree-shaking.
|
|
157
158
|
|
|
158
159
|
```ts
|
|
@@ -166,26 +167,38 @@ import {
|
|
|
166
167
|
} from '@bty/feed_app-runtime-sdk/device'
|
|
167
168
|
|
|
168
169
|
await haptics.impact('medium')
|
|
169
|
-
const pos = await geolocation.getCurrentPosition() // PositionSample
|
|
170
|
-
const
|
|
171
|
-
const photo = await camera.capturePhoto({ camera: 'back' }) // CapturedPhoto
|
|
170
|
+
const pos = await geolocation.getCurrentPosition() // DeviceResult<PositionSample>
|
|
171
|
+
const motion = await sensors.watchMotion((s) => console.log(s.accelerationWithGravity))
|
|
172
|
+
const photo = await camera.capturePhoto({ camera: 'back' }) // DeviceResult<CapturedPhoto>
|
|
172
173
|
const picked = await files.pickFiles({ accept: ['image/*'], multiple: true })
|
|
173
|
-
const
|
|
174
|
-
const clip = await microphone.recordAudio({ maxDurationMs: 5000 }) // AudioRecording
|
|
175
|
-
|
|
174
|
+
const saved = await files.saveFile(blob, 'export.json') // DeviceResult<{ path?: string }>
|
|
175
|
+
const clip = await microphone.recordAudio({ maxDurationMs: 5000 }) // DeviceResult<AudioRecording>
|
|
176
|
+
|
|
177
|
+
if (pos.ok) console.log(pos.value.latitude, pos.value.longitude)
|
|
178
|
+
if (motion.ok) motion.value() // dispose the motion subscription
|
|
179
|
+
if (!saved.ok) console.warn(saved.reason, saved.errorCode, saved.errorMessage)
|
|
176
180
|
```
|
|
177
181
|
|
|
178
|
-
Every call returns
|
|
179
|
-
|
|
180
|
-
`
|
|
181
|
-
`
|
|
182
|
+
Every device call returns `DeviceResult<T>` and never throws for normal runtime
|
|
183
|
+
states. On success, read `result.value`; on failure, branch on `result.reason`
|
|
184
|
+
(`"cancelled"`, `"permission_denied"`, `"not_supported"`, `"timeout"`,
|
|
185
|
+
`"invalid_response"`, or `"failed"`). `source` is `"native"`, `"iframe"`,
|
|
186
|
+
`"web"`, or `"sdk"` and is useful for diagnostics.
|
|
187
|
+
|
|
188
|
+
`pickFiles` succeeds with `{ files: { file, path? }[] }` (path present only on
|
|
189
|
+
the native bridge). `watchPosition`, `watchMotion`, and `watchOrientation`
|
|
190
|
+
succeed with a cleanup function in `value`. `haptics.*` and `camera.stopStream`
|
|
191
|
+
succeed with `value: undefined`.
|
|
182
192
|
|
|
183
193
|
For native/App saves, `saveFile` sends the Blob bytes through the bridge as
|
|
184
194
|
base64 with `{ filename, mime, size, base64 }`. The host App must return an
|
|
185
195
|
`ok: true` envelope with `result.saved === true`; older metadata-only success
|
|
186
|
-
responses are ignored. `USER_CANCELLED` maps to `"cancelled"`;
|
|
187
|
-
failure responses
|
|
188
|
-
|
|
196
|
+
responses are ignored. `USER_CANCELLED` maps to `reason: "cancelled"`; native
|
|
197
|
+
failure responses keep `errorCode` / `errorMessage` on the returned
|
|
198
|
+
`FileSaveResult`. Top-level HostApp WebViews do not trust browser download
|
|
199
|
+
fallbacks after a native save failure, because WebView downloads can report
|
|
200
|
+
success without writing a file. Diagnostics are part of the normal `saveFile`
|
|
201
|
+
Result envelope.
|
|
189
202
|
|
|
190
203
|
Capability detection (synchronous, cheap — gate UI ahead of a call):
|
|
191
204
|
|
package/dist/ai/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {d as d$1,c}from'../chunk-
|
|
1
|
+
import {d as d$1,c}from'../chunk-V73IHZAF.js';import {a as a$1}from'../chunk-H42VJJAC.js';import {createParser}from'eventsource-parser';var D={version:"0.1.5"};var m="/v1/feed-app/runtime/ai",T=`${m}/chat/completions`,_=`${m}/messages`,B=`${m}/images/generations`,M=`${m}/audio/speech`,N=`${m}/video/generations`,H="Authorization",j="x-bty-extend",G="x-bty-app",h=D.version;var q=()=>{};async function*U(e){let t=e.getReader(),r=new TextDecoder,n=[],o=createParser({onEvent(c){n.push({event:c.event||"message",data:c.data});},onRetry:q,onComment:q}),s=false;try{for(;;){let{done:c,value:p}=await t.read();for(p&&o.feed(r.decode(p,{stream:!0}));n.length>0;)yield n.shift();if(c){for(o.reset({consume:!0});n.length>0;)yield n.shift();s=!0;return}}}finally{if(!s)try{await t.cancel();}catch{}t.releaseLock();}}async function*J(e){for await(let t of U(e)){if(t.data==="[DONE]")return;t.data&&(yield JSON.parse(t.data));}}async function*V(e){for await(let t of U(e))t.data&&(yield JSON.parse(t.data));}var Z="https://reactus-api.happyseeds.ai",$=e=>{try{let t=e();if(typeof t=="string"&&t.length>0)return t}catch{}},ee=()=>$(()=>typeof __BTY_RUNTIME_API_BASE_URL__=="string"?__BTY_RUNTIME_API_BASE_URL__:void 0),te=()=>$(()=>typeof __BTY_RUNTIME_PROJECT_ID__=="string"?__BTY_RUNTIME_PROJECT_ID__:void 0),x={apiBaseUrl:(ee()??Z).replace(/\/+$/,""),projectId:te()??""},re=e=>{x={...x,...e,...e.apiBaseUrl?{apiBaseUrl:e.apiBaseUrl.replace(/\/+$/,"")}:{}};},g=()=>x;var a=class extends Error{status;code;body;constructor(t,r,n,o=null){super(t),this.name="AiError",this.code=r,this.status=n,this.body=o;}},i=class extends a{constructor(t="Auth required",r=null){super(t,"auth_required",401,r),this.name="AuthRequiredError";}},y=class extends a{constructor(t="Rate limit exceeded",r=null){super(t,"rate_limit",429,r),this.name="RateLimitError";}},E=class extends a{constructor(t="Quota exceeded",r=null){super(t,"quota_exceeded",402,r),this.name="QuotaExceededError";}},A=class extends a{constructor(t,r=400,n=null){super(t,"bad_input",r,n),this.name="BadInputError";}},R=class extends a{constructor(t,r=500,n=null){super(t,"server",r,n),this.name="ServerError";}},d=class extends a{constructor(t="Network error",r){super(t,"network",-1,r),this.name="NetworkError";}},l=class extends a{constructor(t="Request aborted"){super(t,"aborted",-1,null),this.name="AbortedError";}},L=e=>typeof e=="object"&&e!==null,ne=(e,t)=>{if(typeof e=="string")return e||t;if(!L(e))return t;let r=e.message;if(typeof r=="string"&&r.length>0)return r;let n=e.error;if(typeof n=="string"&&n.length>0)return n;if(L(n)&&typeof n.message=="string"&&n.message.length>0)return n.message;let o=e.detail;return typeof o=="string"&&o.length>0?o:t},P=(e,t)=>{let r=ne(t,`HTTP ${e}`);return e===401||e===403?new i(r,t):e===402?new E(r,t):e===429?new y(r,t):e>=400&&e<500?new A(r,e,t):e>=500?new R(r,e,t):new a(r,"unknown",e,t)};var oe=e=>JSON.stringify({"sdk-version":h,...e}),F=async(e={})=>{let t=await c(),r=new Headers;t&&r.set(H,`Bearer ${t}`),r.set(j,oe(e.extend));let{projectId:n}=g();if(n&&r.set(G,n),e.contentType&&r.set("Content-Type",e.contentType),e.accept&&r.set("Accept",e.accept),e.extra)for(let[o,s]of Object.entries(e.extra))r.set(o,s);return r};var S="feed-app-runtime-sdk:ai-error",se=e=>typeof e=="object"&&e!==null,ae=(e,t)=>{if(se(e))for(let r of t){let n=e[r];if(typeof n=="string"&&n.length>0)return n}},Y=e=>{let t=ae(e.body,["request_id","requestId"]);return {source:"feed-app-runtime-sdk/ai",status:e.error.status,code:e.error.code,message:e.error.message,path:e.path,method:e.method,sdkVersion:h,timestamp:Date.now(),...t?{requestId:t}:{},...e.traceId?{traceId:e.traceId}:{},...e.willRetryAuth!==void 0?{willRetryAuth:e.willRetryAuth}:{}}},K=e=>{if(a$1()&&(window.dispatchEvent(new CustomEvent(S,{detail:e})),window.parent!==window))try{window.parent.postMessage({type:S,detail:e},"*");}catch{}};var ie="feed-app-runtime-sdk:auth-required",k=e=>{a$1()&&window.dispatchEvent(new CustomEvent(ie,{detail:e}));};var ce=e=>e instanceof DOMException&&e.name==="AbortError",pe=async e=>{let t=e.headers.get("content-type")??"";try{return t.includes("application/json")?await e.json():await e.text()}catch{return null}},de=e=>typeof e=="object"&&e!==null,ue=(e,t)=>{if(!de(e)||typeof e.success!="boolean")return e;if(e.success)return e.data;let r=typeof e.code=="number"?e.code:t;throw P(r,e)},Q=async(e,t)=>{let{apiBaseUrl:r}=g(),n=`${r}${e}`,o=await F(t),s;try{s=await fetch(n,{method:t.method??"POST",headers:o,body:t.body,signal:t.signal});}catch(b){throw ce(b)?new l:new d("Failed to reach AI backend",b)}if(s.ok)return s;let c=await pe(s),p=P(s.status,c);throw K(Y({error:p,path:e,method:t.method??"POST",body:c,traceId:s.headers.get("x-trace-id")??void 0,willRetryAuth:p instanceof i&&!t.skipAuthRetry&&!t.signal?.aborted})),p},v=async(e,t={})=>{try{return await Q(e,t)}catch(r){if(r instanceof i&&!t.skipAuthRetry&&!t.signal?.aborted){if(!await d$1())throw k({reason:"refresh_failed",error:r}),r;try{return await Q(e,{...t,skipAuthRetry:!0})}catch(o){throw o instanceof i&&k({reason:"retry_rejected",error:o}),o}}throw r}},u=async(e,t,r={})=>{let n=await v(e,{...r,method:"POST",contentType:"application/json",body:JSON.stringify(t)});return ue(await n.json(),n.status)};var w=async(e,t,r={})=>{let n=await v(e,{...r,method:"POST",contentType:"application/json",accept:"text/event-stream",body:JSON.stringify(t)});if(!n.body)throw new d("Streaming response has no body");return n.body},X=async(e,t,r={})=>await(await v(e,{...r,method:"POST",contentType:"application/json",body:JSON.stringify(t)})).blob();var C=e=>{let{signal:t,headers:r,...n}=e;return {transport:{signal:t,extra:r},payload:n}},me=(async e=>{let{transport:t,payload:r}=C(e);if(e.stream){let n=await w(T,r,t);return J(n)}return await u(T,r,t)}),le={create:me},fe={async generate(e){let{transport:t,payload:r}=C(e);return u(B,r,t)}},he={speech:{async create(e){let{transport:t,payload:r}=C(e);return X(M,r,t)}}},ge={generations:{async create(e){let{transport:t,payload:r}=C(e);return u(N,r,t)}}},ye={chat:{completions:le},images:fe,audio:he,video:ge};var Ee=e=>{let{signal:t,headers:r,...n}=e;return {transport:{signal:t,extra:r},payload:n}},Ae=(async e=>{let{transport:t,payload:r}=Ee(e);if(e.stream){let n=await w(_,r,t);return V(n)}return await u(_,r,t)}),Re={messages:{create:Ae}};
|
|
2
2
|
export{S as AI_ERROR_EVENT,l as AbortedError,a as AiError,i as AuthRequiredError,A as BadInputError,d as NetworkError,E as QuotaExceededError,y as RateLimitError,R as ServerError,Re as anthropic,re as configureRuntime,ye as openai};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var o=()=>typeof window<"u"&&typeof document<"u";var f="hostRuntime",i=class{listeners=new Map;on(e,r){let s=this.listeners.get(e),n=s??new Set;return s||this.listeners.set(e,n),n.add(r),()=>{n.delete(r),n.size===0&&this.listeners.delete(e);}}emit(e,r){let s=this.listeners.get(e);if(s)for(let n of s)n(r);}},_=new i,u=0,N=t=>(u+=1,`${t}.${u}`),a=false,T=()=>{if(!o()||a)return;a=true,Reflect.set(window,f,{receiveMessage(e){if(!e)return;let r=e.endpoint;r&&_.emit(r,e.data??e);}});};var E="HostApp",M="hostListener";var x="processUserCredentials",I="processUserInfo",O="user.getCredentials",L="user.getUserInfo",v="user.credentials",H="user.info",U="user-credentials-request",k="user-credentials-response",y="user-info-request",P="user-info-response";var S=new RegExp(`${E}\\/(\\d+\\.\\d+\\.\\d+)\\/(\\d+)\\/(iOS|Android)`),R=t=>{let e=t.match(S);if(!e)return null;let[,r,s,n]=e;return !r||!s||n!=="iOS"&&n!=="Android"?null:{type:"native_app",platform:n,appVersion:r,buildNumber:s}},C=()=>{if(!o())return {type:"web"};let t=R(navigator.userAgent??"");return t||(window.parent!==window?{type:"iframe"}:{type:"web"})};var l=t=>typeof t!="object"||t===null?false:typeof Reflect.get(t,"postMessage")=="function",w=t=>{let e=Reflect.get(window,"webkit");if(typeof e=="object"&&e!==null){let s=Reflect.get(e,"messageHandlers");if(typeof s=="object"&&s!==null){let n=Reflect.get(s,t);if(l(n))return n}}let r=Reflect.get(window,t);return l(r)?r:null},B=(t,e={})=>{let{pollIntervalMs:r=50,timeoutMs:s=1500}=e;return new Promise(n=>{let d=Date.now(),c=()=>{let p=w(t);if(p){n(p);return}if(Date.now()-d>=s){n(null);return}setTimeout(c,r);};c();})};export{o as a,_ as b,N as c,T as d,M as e,x as f,I as g,O as h,L as i,v as j,H as k,U as l,k as m,y as n,P as o,C as p,w as q,B as r};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a as a$1,b as b$1,j as j$1,d,f,g,k,o,m,p,r,e,q as q$1,c as c$1,l,n,h,i}from'./chunk-H42VJJAC.js';var E=e=>typeof e=="object"&&e!==null,a=(e,n)=>{if(e)for(let t of n){let r=e[t];if(typeof r=="string"&&r.length>0)return r}},W=(e,n)=>{if(e)for(let t of n){let r=e[t];if(typeof r=="string"&&r.length>0||typeof r=="number"&&Number.isFinite(r))return r}},u=e=>{if(!E(e))return null;let n=E(e.credentials)?e.credentials:void 0,t=E(e.user)?e.user:void 0,r=a(e,["uid","userId","id"])??a(n,["uid","userId","id"])??a(t,["uid","userId","id"]),o=a(e,["token","authToken"])??a(n,["token","authToken"]);return !r||!o?null:{uid:r,token:o}},c=e=>{if(!E(e))return null;let n=E(e.data)?e.data:e,t=W(n,["userId","id","uid"]);if(t===void 0)return null;let r=a(n,["username","nickname","nickName","name"]),o=a(n,["nickname","nickName","username"]);return {...n,userId:t,...r?{username:r}:{},...o?{nickname:o}:{}}};var X=e=>typeof e!="object"||e===null?false:typeof Reflect.get(e,"type")=="string",b=false,D=()=>{!a$1()||b||(b=true,d(),Reflect.set(window,f,e=>{u(e)&&b$1.emit(j$1,e);}),Reflect.set(window,g,e=>{c(e)&&b$1.emit(k,e);}),window.addEventListener("message",e=>{let n=e.data;if(X(n))switch(n.type){case m:b$1.emit("iframe.credentials",n);break;case o:b$1.emit("iframe.userinfo",n);break}}));};var q=(e,n,t)=>new Promise(r=>{let o=false,f=i=>{o||(o=true,y(),clearTimeout(T),r(i));},y=b$1.on(n,i=>{let g=t(i);g&&f(g);}),T=setTimeout(()=>f(null),500);try{window.parent.postMessage({type:e,timestamp:Date.now()},"*");}catch{f(null);}}),B=()=>q(l,"iframe.credentials",u),H=()=>q(n,"iframe.userinfo",c);var j=async(e$1,n,t,r$1)=>{let o=e$1.platform==="Android"?await r(e,{pollIntervalMs:50,timeoutMs:1500}):q$1(e);if(!o)return null;let f=c$1(t);return new Promise(y=>{let T=false,i=d=>{T||(T=true,g(),z(),clearTimeout(K),y(d));},g=b$1.on(f,d=>{let p=r$1(d);p&&i(p);}),z=b$1.on(t,d=>{let p=r$1(d);p&&i(p);}),K=setTimeout(()=>i(null),3e3);try{o.postMessage({command:n,parameters:JSON.stringify({timestamp:Date.now(),endpoint:f})});}catch{i(null);}})},G=e=>j(e,h,j$1,u),Q=e=>j(e,i,k,c);D();var C=null,I=null,R=new Set,ne=e=>{switch(e.type){case "native_app":return G(e);case "iframe":return B();case "web":return Promise.resolve(null)}},re=e=>{switch(e.type){case "native_app":return Q(e);case "iframe":return H();case "web":return Promise.resolve(null)}},V=e=>{let n=C?.token??"",t=e?.token??"";if(C=e,n!==t)for(let r of R)try{r();}catch{}},Ne=()=>C?.token??"",ve=e=>(R.add(e),()=>{R.delete(e);}),J=()=>I||(I=ne(p()).then(e=>(e&&V(e),e)).finally(()=>{I=null;}),I);a$1()&&b$1.on(j$1,e=>{let n=u(e);n&&V(n);});var te=async()=>a$1()?C?C.token:(await J())?.token??"":"",we=async()=>a$1()?(await J())?.token??"":"",se=async()=>a$1()?re(p()):null;export{Ne as a,ve as b,te as c,we as d,se as e};
|
package/dist/device/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { A as AppEnvironment } from '../types-DryABknE.js';
|
|
2
|
-
|
|
3
1
|
type HapticImpactStrength = "light" | "medium" | "heavy" | "soft" | "rigid";
|
|
4
2
|
type HapticNotificationKind = "success" | "warning" | "error";
|
|
5
3
|
interface PositionRequestOptions {
|
|
@@ -79,7 +77,10 @@ interface PickedFile {
|
|
|
79
77
|
interface PickedFiles {
|
|
80
78
|
files: PickedFile[];
|
|
81
79
|
}
|
|
82
|
-
|
|
80
|
+
interface SavedFile {
|
|
81
|
+
path?: string;
|
|
82
|
+
}
|
|
83
|
+
type FileSaveResult = DeviceResult<SavedFile>;
|
|
83
84
|
interface AudioRecordingOptions {
|
|
84
85
|
maxDurationMs?: number;
|
|
85
86
|
mimeType?: string;
|
|
@@ -92,10 +93,23 @@ interface AudioRecording {
|
|
|
92
93
|
size: number;
|
|
93
94
|
}
|
|
94
95
|
interface AudioRecorder {
|
|
95
|
-
stop(): Promise<AudioRecording
|
|
96
|
+
stop(): Promise<DeviceResult<AudioRecording>>;
|
|
96
97
|
cancel(): void;
|
|
97
98
|
readonly active: boolean;
|
|
98
99
|
}
|
|
100
|
+
type DeviceResultSource = "native" | "iframe" | "web" | "sdk";
|
|
101
|
+
type DeviceErrorReason = "cancelled" | "permission_denied" | "not_supported" | "timeout" | "invalid_response" | "failed";
|
|
102
|
+
type DeviceResult<T> = {
|
|
103
|
+
ok: true;
|
|
104
|
+
source: DeviceResultSource;
|
|
105
|
+
value: T;
|
|
106
|
+
} | {
|
|
107
|
+
ok: false;
|
|
108
|
+
source: DeviceResultSource;
|
|
109
|
+
reason: DeviceErrorReason;
|
|
110
|
+
errorCode?: string;
|
|
111
|
+
errorMessage?: string;
|
|
112
|
+
};
|
|
99
113
|
|
|
100
114
|
declare const camera: {
|
|
101
115
|
isSupported(): boolean;
|
|
@@ -103,13 +117,13 @@ declare const camera: {
|
|
|
103
117
|
* Open the camera, capture one photo, close the stream. The native bridge
|
|
104
118
|
* variant runs the host App's full-screen capture UI (better quality, save
|
|
105
119
|
* to gallery, etc.); the web fallback does a headless `getUserMedia +
|
|
106
|
-
* canvas` shot.
|
|
107
|
-
*
|
|
120
|
+
* canvas` shot. Permission denial, hardware absence, or any failure returns
|
|
121
|
+
* a DeviceResult failure.
|
|
108
122
|
*
|
|
109
123
|
* Must be called inside a user-gesture handler to satisfy autoplay /
|
|
110
124
|
* permission requirements on iOS Safari and modern Android browsers.
|
|
111
125
|
*/
|
|
112
|
-
capturePhoto(opts?: PhotoCaptureOptions): Promise<CapturedPhoto
|
|
126
|
+
capturePhoto(opts?: PhotoCaptureOptions): Promise<DeviceResult<CapturedPhoto>>;
|
|
113
127
|
/**
|
|
114
128
|
* Open a live MediaStream — for QR scanning, AR overlays, or any case
|
|
115
129
|
* where a single still photo is not enough. Web-only by design: streaming
|
|
@@ -117,11 +131,12 @@ declare const camera: {
|
|
|
117
131
|
* need camera access usually push it through capturePhoto's full-screen UI
|
|
118
132
|
* instead.
|
|
119
133
|
*
|
|
120
|
-
* Returns
|
|
121
|
-
* Caller must invoke `camera.stopStream(
|
|
134
|
+
* Returns a DeviceResult failure when getUserMedia is unavailable or the
|
|
135
|
+
* user denies access. Caller must invoke `camera.stopStream(result.value)`
|
|
136
|
+
* when done.
|
|
122
137
|
*/
|
|
123
|
-
openStream(opts?: StreamOptions): Promise<MediaStream
|
|
124
|
-
stopStream(stream: MediaStream): void
|
|
138
|
+
openStream(opts?: StreamOptions): Promise<DeviceResult<MediaStream>>;
|
|
139
|
+
stopStream(stream: MediaStream): DeviceResult<void>;
|
|
125
140
|
};
|
|
126
141
|
|
|
127
142
|
declare const files: {
|
|
@@ -133,24 +148,22 @@ declare const files: {
|
|
|
133
148
|
*/
|
|
134
149
|
isPickerSupported(): boolean;
|
|
135
150
|
/**
|
|
136
|
-
* Pick one or more files.
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* it. Pairing path with its file
|
|
140
|
-
* `paths[]` array invites.
|
|
151
|
+
* Pick one or more files. User cancel or unavailability returns a
|
|
152
|
+
* DeviceResult failure. On success, each entry is a `{ file, path? }` —
|
|
153
|
+
* `path` is set only when the native bridge serves the request; web
|
|
154
|
+
* fallbacks have no path concept and omit it. Pairing path with its file
|
|
155
|
+
* avoids the index drift a separate `paths[]` array invites.
|
|
141
156
|
*/
|
|
142
|
-
pickFiles(opts?: PickFilesOptions): Promise<PickedFiles
|
|
157
|
+
pickFiles(opts?: PickFilesOptions): Promise<DeviceResult<PickedFiles>>;
|
|
143
158
|
/**
|
|
144
159
|
* Save a Blob to a file the user nominates. Native handler can prompt for
|
|
145
160
|
* a directory and write in place; web fallback uses the File System Access
|
|
146
161
|
* save dialog when available, otherwise triggers an anchor download.
|
|
147
162
|
*
|
|
148
|
-
* Resolves to a `
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* assuming success. There is no progress callback — web Blobs write
|
|
153
|
-
* atomically.
|
|
163
|
+
* Resolves to a `DeviceResult<SavedFile>`. Never throws, so an "Export"
|
|
164
|
+
* button can branch on `ok` and inspect `reason` / `errorCode` /
|
|
165
|
+
* `errorMessage` for UI or diagnostics. There is no progress callback —
|
|
166
|
+
* web Blobs write atomically.
|
|
154
167
|
*/
|
|
155
168
|
saveFile(blob: Blob, filename: string): Promise<FileSaveResult>;
|
|
156
169
|
/**
|
|
@@ -158,29 +171,29 @@ declare const files: {
|
|
|
158
171
|
* not consult the native bridge. The blob already lives in the page's
|
|
159
172
|
* memory by the time this is called.
|
|
160
173
|
*/
|
|
161
|
-
readAsText(file: File | Blob): Promise<string
|
|
174
|
+
readAsText(file: File | Blob): Promise<DeviceResult<string>>;
|
|
162
175
|
/**
|
|
163
176
|
* Read the contents of a File / Blob as a base64 data URL — useful for
|
|
164
177
|
* `<img src>` previews. Pure web.
|
|
165
178
|
*/
|
|
166
|
-
readAsDataUrl(file: File | Blob): Promise<string
|
|
179
|
+
readAsDataUrl(file: File | Blob): Promise<DeviceResult<string>>;
|
|
167
180
|
};
|
|
168
181
|
|
|
169
182
|
declare const geolocation: {
|
|
170
183
|
isSupported(): boolean;
|
|
171
184
|
/**
|
|
172
|
-
* Single position read.
|
|
173
|
-
*
|
|
174
|
-
* default; pass `timeoutMs` to override.
|
|
185
|
+
* Single position read. Permission denial, timeout, or absence of
|
|
186
|
+
* geolocation hardware returns a DeviceResult failure. Default timeout is
|
|
187
|
+
* the browser/native default; pass `timeoutMs` to override.
|
|
175
188
|
*/
|
|
176
|
-
getCurrentPosition(opts?: PositionRequestOptions): Promise<PositionSample
|
|
189
|
+
getCurrentPosition(opts?: PositionRequestOptions): Promise<DeviceResult<PositionSample>>;
|
|
177
190
|
/**
|
|
178
|
-
* Continuous position updates.
|
|
179
|
-
*
|
|
191
|
+
* Continuous position updates. On success, `value` is a cleanup function.
|
|
192
|
+
* Native subscription may be still warming up; cleanup is safe to call
|
|
180
193
|
* before that resolves, the subscription will be torn down as soon as it
|
|
181
194
|
* is installed.
|
|
182
195
|
*/
|
|
183
|
-
watchPosition(onSample: (sample: PositionSample) => void, opts?: PositionRequestOptions): () => void
|
|
196
|
+
watchPosition(onSample: (sample: PositionSample) => void, opts?: PositionRequestOptions): Promise<DeviceResult<() => void>>;
|
|
184
197
|
};
|
|
185
198
|
|
|
186
199
|
declare const haptics: {
|
|
@@ -196,25 +209,25 @@ declare const haptics: {
|
|
|
196
209
|
* VibrationEffect.EFFECT_CLICK / EFFECT_HEAVY_CLICK on Android (native
|
|
197
210
|
* bridge); a short navigator.vibrate pulse on the web. Default `medium`.
|
|
198
211
|
*/
|
|
199
|
-
impact(strength?: HapticImpactStrength): Promise<void
|
|
212
|
+
impact(strength?: HapticImpactStrength): Promise<DeviceResult<void>>;
|
|
200
213
|
/**
|
|
201
214
|
* "Tick" feedback for changing a selected item (segmented control, picker).
|
|
202
215
|
* Maps to UISelectionFeedbackGenerator on iOS; a very short pulse on web.
|
|
203
216
|
*/
|
|
204
|
-
selection(): Promise<void
|
|
217
|
+
selection(): Promise<DeviceResult<void>>;
|
|
205
218
|
/**
|
|
206
219
|
* Status feedback after a discrete action (form submit, transaction).
|
|
207
220
|
* Maps to UINotificationFeedbackGenerator on iOS; a small multi-segment
|
|
208
221
|
* pattern on web.
|
|
209
222
|
*/
|
|
210
|
-
notification(kind: HapticNotificationKind): Promise<void
|
|
223
|
+
notification(kind: HapticNotificationKind): Promise<DeviceResult<void>>;
|
|
211
224
|
/**
|
|
212
225
|
* Low-level Android-style pattern. Number = single pulse in ms; array =
|
|
213
226
|
* alternating vibrate/pause durations. Native bridge forwards verbatim;
|
|
214
227
|
* iOS handler may approximate by mapping pattern length/intensity to its
|
|
215
228
|
* Impact generator.
|
|
216
229
|
*/
|
|
217
|
-
vibrate(pattern: number | number[]): Promise<void
|
|
230
|
+
vibrate(pattern: number | number[]): Promise<DeviceResult<void>>;
|
|
218
231
|
};
|
|
219
232
|
|
|
220
233
|
declare const microphone: {
|
|
@@ -227,9 +240,10 @@ declare const microphone: {
|
|
|
227
240
|
* camera/sensors. The native-bridge variant routes through the App's own
|
|
228
241
|
* permission prompt and has no gesture requirement.
|
|
229
242
|
*
|
|
230
|
-
* Returns
|
|
243
|
+
* Returns a successful DeviceResult with `value: true` if recording is
|
|
244
|
+
* permitted. Denial / no hardware returns a DeviceResult failure.
|
|
231
245
|
*/
|
|
232
|
-
requestPermission(): Promise<boolean
|
|
246
|
+
requestPermission(): Promise<DeviceResult<boolean>>;
|
|
233
247
|
/**
|
|
234
248
|
* Record one audio clip and resolve when capture finishes. The native
|
|
235
249
|
* bridge runs the host App's recording UI (record button, waveform, native
|
|
@@ -238,13 +252,13 @@ declare const microphone: {
|
|
|
238
252
|
* since the headless path has no UI for the user to tap "done".
|
|
239
253
|
*
|
|
240
254
|
* Must be called inside a user-gesture handler to satisfy mic-permission /
|
|
241
|
-
* autoplay rules on iOS Safari and modern Android browsers.
|
|
242
|
-
*
|
|
255
|
+
* autoplay rules on iOS Safari and modern Android browsers. Permission
|
|
256
|
+
* denial, hardware absence, or any failure returns a DeviceResult failure.
|
|
243
257
|
*
|
|
244
258
|
* For press-and-hold or tap-to-stop UIs where the caller decides when to
|
|
245
259
|
* stop, use `startRecording` instead.
|
|
246
260
|
*/
|
|
247
|
-
recordAudio(opts?: AudioRecordingOptions): Promise<AudioRecording
|
|
261
|
+
recordAudio(opts?: AudioRecordingOptions): Promise<DeviceResult<AudioRecording>>;
|
|
248
262
|
/**
|
|
249
263
|
* Begin caller-controlled recording and return a handle to stop / cancel on
|
|
250
264
|
* your own schedule — for push-to-talk, tap-to-start/tap-to-stop, or any UI
|
|
@@ -252,11 +266,11 @@ declare const microphone: {
|
|
|
252
266
|
* audio through a JS bridge is impractical, and host Apps that need mic
|
|
253
267
|
* access route it through `recordAudio`'s full-screen UI instead.
|
|
254
268
|
*
|
|
255
|
-
* Must be called inside a user-gesture handler. Returns
|
|
256
|
-
* unavailable or the user denies access. The caller
|
|
257
|
-
* `.stop()` or `.cancel()` to release the microphone.
|
|
269
|
+
* Must be called inside a user-gesture handler. Returns a DeviceResult
|
|
270
|
+
* failure when the mic is unavailable or the user denies access. The caller
|
|
271
|
+
* MUST eventually call `.stop()` or `.cancel()` to release the microphone.
|
|
258
272
|
*/
|
|
259
|
-
startRecording(opts?: AudioRecordingOptions): Promise<AudioRecorder
|
|
273
|
+
startRecording(opts?: AudioRecordingOptions): Promise<DeviceResult<AudioRecorder>>;
|
|
260
274
|
};
|
|
261
275
|
|
|
262
276
|
declare const sensors: {
|
|
@@ -269,7 +283,7 @@ declare const sensors: {
|
|
|
269
283
|
* variant has no such gesture requirement because the App's own iOS
|
|
270
284
|
* permission prompt is independent of the web view's gesture stack.
|
|
271
285
|
*/
|
|
272
|
-
requestMotionPermission(): Promise<boolean
|
|
286
|
+
requestMotionPermission(): Promise<DeviceResult<boolean>>;
|
|
273
287
|
/**
|
|
274
288
|
* Subscribe to device motion samples. Native handler streams sensor-rate
|
|
275
289
|
* data through the bridge; web fallback uses the `devicemotion` event.
|
|
@@ -278,57 +292,55 @@ declare const sensors: {
|
|
|
278
292
|
* `autoRequestPermission: true` from inside a click handler if you want
|
|
279
293
|
* the subscription to also request permission as part of setup.
|
|
280
294
|
*/
|
|
281
|
-
watchMotion(onSample: (s: MotionSample) => void, opts?: MotionWatchOptions): () => void
|
|
295
|
+
watchMotion(onSample: (s: MotionSample) => void, opts?: MotionWatchOptions): Promise<DeviceResult<() => void>>;
|
|
282
296
|
/**
|
|
283
297
|
* Subscribe to device orientation samples. Mirrors watchMotion but uses
|
|
284
298
|
* the `deviceorientation` event on the web fallback path.
|
|
285
299
|
*/
|
|
286
|
-
watchOrientation(onSample: (s: OrientationSample) => void): () => void
|
|
300
|
+
watchOrientation(onSample: (s: OrientationSample) => void): Promise<DeviceResult<() => void>>;
|
|
287
301
|
};
|
|
288
302
|
|
|
289
303
|
type DeviceFeature = "haptics" | "geolocation" | "sensors" | "camera" | "files" | "microphone";
|
|
290
304
|
|
|
291
|
-
declare const meetsFeatureMinVersion: (feature: DeviceFeature, env: AppEnvironment) => boolean;
|
|
292
|
-
|
|
293
305
|
declare const device: {
|
|
294
306
|
readonly haptics: {
|
|
295
307
|
isSupported(): boolean;
|
|
296
|
-
impact(strength?: HapticImpactStrength): Promise<void
|
|
297
|
-
selection(): Promise<void
|
|
298
|
-
notification(kind: HapticNotificationKind): Promise<void
|
|
299
|
-
vibrate(pattern: number | number[]): Promise<void
|
|
308
|
+
impact(strength?: HapticImpactStrength): Promise<DeviceResult<void>>;
|
|
309
|
+
selection(): Promise<DeviceResult<void>>;
|
|
310
|
+
notification(kind: HapticNotificationKind): Promise<DeviceResult<void>>;
|
|
311
|
+
vibrate(pattern: number | number[]): Promise<DeviceResult<void>>;
|
|
300
312
|
};
|
|
301
313
|
readonly geolocation: {
|
|
302
314
|
isSupported(): boolean;
|
|
303
|
-
getCurrentPosition(opts?: PositionRequestOptions): Promise<PositionSample
|
|
304
|
-
watchPosition(onSample: (sample: PositionSample) => void, opts?: PositionRequestOptions): () => void
|
|
315
|
+
getCurrentPosition(opts?: PositionRequestOptions): Promise<DeviceResult<PositionSample>>;
|
|
316
|
+
watchPosition(onSample: (sample: PositionSample) => void, opts?: PositionRequestOptions): Promise<DeviceResult<() => void>>;
|
|
305
317
|
};
|
|
306
318
|
readonly sensors: {
|
|
307
319
|
isMotionSupported(): boolean;
|
|
308
320
|
isOrientationSupported(): boolean;
|
|
309
|
-
requestMotionPermission(): Promise<boolean
|
|
310
|
-
watchMotion(onSample: (s: MotionSample) => void, opts?: MotionWatchOptions): () => void
|
|
311
|
-
watchOrientation(onSample: (s: OrientationSample) => void): () => void
|
|
321
|
+
requestMotionPermission(): Promise<DeviceResult<boolean>>;
|
|
322
|
+
watchMotion(onSample: (s: MotionSample) => void, opts?: MotionWatchOptions): Promise<DeviceResult<() => void>>;
|
|
323
|
+
watchOrientation(onSample: (s: OrientationSample) => void): Promise<DeviceResult<() => void>>;
|
|
312
324
|
};
|
|
313
325
|
readonly camera: {
|
|
314
326
|
isSupported(): boolean;
|
|
315
|
-
capturePhoto(opts?: PhotoCaptureOptions): Promise<CapturedPhoto
|
|
316
|
-
openStream(opts?: StreamOptions): Promise<MediaStream
|
|
317
|
-
stopStream(stream: MediaStream): void
|
|
327
|
+
capturePhoto(opts?: PhotoCaptureOptions): Promise<DeviceResult<CapturedPhoto>>;
|
|
328
|
+
openStream(opts?: StreamOptions): Promise<DeviceResult<MediaStream>>;
|
|
329
|
+
stopStream(stream: MediaStream): DeviceResult<void>;
|
|
318
330
|
};
|
|
319
331
|
readonly files: {
|
|
320
332
|
isPickerSupported(): boolean;
|
|
321
|
-
pickFiles(opts?: PickFilesOptions): Promise<PickedFiles
|
|
333
|
+
pickFiles(opts?: PickFilesOptions): Promise<DeviceResult<PickedFiles>>;
|
|
322
334
|
saveFile(blob: Blob, filename: string): Promise<FileSaveResult>;
|
|
323
|
-
readAsText(file: File | Blob): Promise<string
|
|
324
|
-
readAsDataUrl(file: File | Blob): Promise<string
|
|
335
|
+
readAsText(file: File | Blob): Promise<DeviceResult<string>>;
|
|
336
|
+
readAsDataUrl(file: File | Blob): Promise<DeviceResult<string>>;
|
|
325
337
|
};
|
|
326
338
|
readonly microphone: {
|
|
327
339
|
isSupported(): boolean;
|
|
328
|
-
requestPermission(): Promise<boolean
|
|
329
|
-
recordAudio(opts?: AudioRecordingOptions): Promise<AudioRecording
|
|
330
|
-
startRecording(opts?: AudioRecordingOptions): Promise<AudioRecorder
|
|
340
|
+
requestPermission(): Promise<DeviceResult<boolean>>;
|
|
341
|
+
recordAudio(opts?: AudioRecordingOptions): Promise<DeviceResult<AudioRecording>>;
|
|
342
|
+
startRecording(opts?: AudioRecordingOptions): Promise<DeviceResult<AudioRecorder>>;
|
|
331
343
|
};
|
|
332
344
|
};
|
|
333
345
|
|
|
334
|
-
export { type AudioRecorder, type AudioRecording, type AudioRecordingOptions, type CameraFacing, type CapturedPhoto, type DeviceFeature, type HapticImpactStrength, type HapticNotificationKind, type MotionSample, type MotionWatchOptions, type OrientationSample, type PhotoCaptureOptions, type PhotoFormat, type PhotoQuality, type PickFilesOptions, type PickedFiles, type PositionRequestOptions, type PositionSample, type StreamOptions, type Vector3, camera, device, files, geolocation, haptics,
|
|
346
|
+
export { type AudioRecorder, type AudioRecording, type AudioRecordingOptions, type CameraFacing, type CapturedPhoto, type DeviceErrorReason, type DeviceFeature, type DeviceResult, type DeviceResultSource, type FileSaveResult, type HapticImpactStrength, type HapticNotificationKind, type MotionSample, type MotionWatchOptions, type OrientationSample, type PhotoCaptureOptions, type PhotoFormat, type PhotoQuality, type PickFilesOptions, type PickedFile, type PickedFiles, type PositionRequestOptions, type PositionSample, type SavedFile, type StreamOptions, type Vector3, camera, device, files, geolocation, haptics, microphone, sensors };
|
package/dist/device/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {a,d as d$1,b,u,t,v as v$1,c,x as x$1,e,s,r,w as w$1}from'../chunk-ALNJCFV4.js';import {fileSave,directoryOpen,fileOpen}from'browser-fs-access';var j="device.haptics",I="device.geolocation",G="device.sensors.motion",z="device.sensors.orientation",Q="device.sensors.permission",K="device.camera",A="device.files",Y="device.microphone",J="device.microphone.permission",X="device.haptics.impact",$="device.haptics.selection",Z="device.haptics.notification",ee="device.haptics.vibrate",te="device.geolocation.get",ne="device.geolocation.watch.start",oe="device.geolocation.watch.stop",ie="device.sensors.motion.start",re="device.sensors.motion.stop",ae="device.sensors.orientation.start",se="device.sensors.orientation.stop",le="device.sensors.requestPermission",ce="device.camera.capture",ue="device.files.pick",de="device.files.save",me="device.microphone.record",pe="device.microphone.requestPermission",fe="device-request",ge="device-response";var ve={haptics:{iOS:null,Android:null},geolocation:{iOS:null,Android:null},sensors:{iOS:null,Android:null},camera:{iOS:null,Android:null},files:{iOS:null,Android:null},microphone:{iOS:null,Android:null}};var Ee="USER_CANCELLED";var ye=false,Ge=e=>typeof e!="object"||e===null?false:Reflect.get(e,"type")===ge&&typeof Reflect.get(e,"endpoint")=="string",R=()=>{!a()||ye||(ye=true,d$1(),window.addEventListener("message",e=>{let t=e.data;Ge(t)&&b.emit(t.endpoint,t.data??t);}));};var N=(e,t$1)=>{if(t$1.type!=="native_app"||!t$1.platform||!t$1.appVersion)return false;let n=ve[e][t$1.platform];return n?u(t(t$1.appVersion),n):false},w=e=>JSON.stringify(e),ze=()=>a()&&window.parent!==window,Qe=(e,t)=>{let n=D(e,t);return n?.ok===true?n.result:null},D=(e,t)=>{if(typeof e!="object"||e===null)return null;let n=Reflect.get(e,"ok");if(n===true){let o=t(Reflect.get(e,"result"));return o===null?{ok:false}:{ok:true,result:o}}if(n===false){let o=Reflect.get(e,"errorCode"),i=Reflect.get(e,"errorMessage");return {ok:false,errorCode:typeof o=="string"?o:void 0,errorMessage:typeof i=="string"?i:void 0}}return null},Se=async e$1=>e$1.platform==="Android"?x$1(e,{pollIntervalMs:r,timeoutMs:s}):w$1(e),Ke=async e=>{let t=await Pe(e);return t?.ok===true?t.result:null},Pe=async e=>{let t=v$1();if(!N(e.feature,t))return null;let n=await Se(t);if(!n)return null;let o=c(e.endpointPrefix),i=e.timeoutMs??3e3;return new Promise(r=>{let a=false,s=f=>{a||(a=true,l(),clearTimeout(u),r(f));},l=b.on(o,f=>{let h=D(f,e.parseResult);s(h);}),u=setTimeout(()=>s(null),i);try{n.postMessage({command:e.command,parameters:w({endpoint:o,timestamp:Date.now(),payload:e.payload})});}catch{s(null);}})},Ye=async e=>{let t=await Re(e);return t?.ok===true?t.result:null},Re=async e=>{if(!ze())return null;let t=c(e.endpointPrefix),n=e.timeoutMs??3e3;return new Promise(o=>{let i=false,r=l=>{i||(i=true,a(),clearTimeout(s),o(l));},a=b.on(t,l=>{let u=D(l,e.parseResult);r(u);}),s=setTimeout(()=>r(null),n);try{window.parent.postMessage({type:fe,command:e.command,parameters:w({endpoint:t,timestamp:Date.now(),payload:e.payload})},"*");}catch{r(null);}})},p=async e=>{if(!a())return null;R();let t=await Ke(e);return t!==null?t:Ye(e)},Te=async e=>{if(!a())return null;R();let t=await Pe(e);return t!==null?t:Re(e)},M=async e=>{if(!a())return null;R();let t=v$1();if(!N(e.feature,t))return null;let n=await Se(t);if(!n)return null;let o=c(e.endpointPrefix),i=b.on(o,r=>{let a=Qe(r,e.parseEvent);a&&e.onEvent(a);});try{n.postMessage({command:e.startCommand,parameters:w({endpoint:o,timestamp:Date.now(),payload:e.payload})});}catch{return i(),null}return ()=>{i();try{n.postMessage({command:e.stopCommand,parameters:w({endpoint:o,timestamp:Date.now(),payload:null})});}catch{}}};var g=async e=>{if(!a())return e.safeDefault;let t=await e.native();if(t!==null)return t;try{let n=await e.web();if(n!==null)return n}catch{}return e.safeDefault};var Oe=e=>e==="front"?"user":"environment",Je={low:.5,medium:.8,high:.95},Xe=e=>{let t=e.indexOf(",");if(t<0)return null;let n=e.slice(5,t),o=e.slice(t+1),r=/^([^;]+)/.exec(n)?.[1]??"application/octet-stream";try{if(/;base64/.test(n)){let s=atob(o),l=new Uint8Array(s.length);for(let u=0;u<s.length;u++)l[u]=s.charCodeAt(u);return new Blob([l],{type:r})}return new Blob([decodeURIComponent(o)],{type:r})}catch{return null}},$e=e=>new Promise(t=>{let n=new FileReader;n.onload=()=>t(typeof n.result=="string"?n.result:null),n.onerror=()=>t(null),n.readAsDataURL(e);}),Ze=e=>new Promise(t=>{let n=new Image;n.onload=()=>{t({width:n.naturalWidth,height:n.naturalHeight}),n.remove();},n.onerror=()=>{t(null),n.remove();},n.src=e;}),et=e=>{if(typeof e!="object"||e===null)return null;let t=Reflect.get(e,"dataUrl"),n=Reflect.get(e,"width"),o=Reflect.get(e,"height");if(typeof t!="string"||t.length===0||typeof n!="number"||typeof o!="number")return null;let i=Xe(t);return i?{blob:i,dataUrl:t,width:n,height:o}:null},tt=async(e,t)=>{if(t?.format!==void 0||t?.quality!==void 0||t?.width!==void 0||t?.height!==void 0)return null;let n=Reflect.get(window,"ImageCapture");if(typeof n!="function")return null;let o=e.getVideoTracks()[0];if(!o)return null;try{let r=await new n(o).takePhoto(),a=await $e(r);if(!a)return null;let s=await Ze(a);return s?{blob:r,dataUrl:a,width:s.width,height:s.height}:null}catch{return null}},Me=()=>new Promise(e=>requestAnimationFrame(()=>e())),x=(e,t,n)=>new Promise(o=>{let i=false,r=()=>{i||(i=true,window.clearTimeout(a),e.removeEventListener(t,r),o());},a=window.setTimeout(r,n);e.addEventListener(t,r,{once:true});}),be=(e,t)=>new Promise(n=>{let o=e.requestVideoFrameCallback;if(!o){requestAnimationFrame(()=>requestAnimationFrame(()=>n()));return}let i=false,r=()=>{i||(i=true,window.clearTimeout(a),n());},a=window.setTimeout(r,t);o.call(e,r);}),nt=async e=>{let t=()=>e.videoWidth>0&&e.videoHeight>0;return t()||await x(e,"loadedmetadata",2e3),e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA&&await x(e,"loadeddata",2e3),e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA&&await x(e,"canplay",2e3),await be(e,1e3),await Me(),t()},ot=e=>{if(e.videoWidth<=0||e.videoHeight<=0)return true;let t=document.createElement("canvas");t.width=24,t.height=24;let n=t.getContext("2d");if(!n)return false;try{n.drawImage(e,0,0,t.width,t.height);let o=n.getImageData(0,0,t.width,t.height).data,i=0,r=0;for(let s=0;s<o.length;s+=4){let l=o[s]*.2126+o[s+1]*.7152+o[s+2]*.0722;i=Math.max(i,l),r+=l;}let a=r/(o.length/4);return i<18&&a<6}catch{return false}},it=async(e,t)=>{let n=performance.now();for(;performance.now()-n<t;)if(await be(e,700),await Me(),!ot(e))return},rt=async e=>{if(!a()||!navigator.mediaDevices?.getUserMedia)return null;let t=null,n=null;try{t=await navigator.mediaDevices.getUserMedia({video:{facingMode:Oe(e?.camera),width:e?.width,height:e?.height}});let o=await tt(t,e);if(o)return o;if(n=document.createElement("video"),n.srcObject=t,n.autoplay=!0,n.muted=!0,n.playsInline=!0,n.style.position="fixed",n.style.left="0",n.style.top="0",n.style.width="2px",n.style.height="2px",n.style.opacity="0.01",n.style.pointerEvents="none",n.style.zIndex="-1",(document.body??document.documentElement).appendChild(n),await n.play(),!await nt(n))return null;await it(n,3e3);let a=e?.width??n.videoWidth??640,s=e?.height??n.videoHeight??480,l=document.createElement("canvas");l.width=a,l.height=s;let u=l.getContext("2d");if(!u)return null;u.drawImage(n,0,0,a,s);let h=`image/${e?.format??"jpeg"}`,E=Je[e?.quality??"medium"],T=l.toDataURL(h,E),m=await new Promise(S=>{l.toBlob(je=>S(je),h,E);});return m?{blob:m,dataUrl:T,width:a,height:s}:null}catch{return null}finally{if(n&&(n.pause(),n.srcObject=null,n.remove()),t)for(let o of t.getTracks())o.stop();}},we={isSupported(){return a()?!!navigator.mediaDevices?.getUserMedia:false},capturePhoto(e){return g({native:()=>p({feature:"camera",command:ce,endpointPrefix:K,payload:e??{},parseResult:et,timeoutMs:6e4}),web:()=>rt(e),safeDefault:null})},async openStream(e){if(!a()||!navigator.mediaDevices?.getUserMedia)return null;try{return await navigator.mediaDevices.getUserMedia({video:{facingMode:Oe(e?.camera),width:e?.width,height:e?.height}})}catch{return null}},stopStream(e){try{for(let t of e.getTracks())t.stop();}catch{}}};var lt=8*1024*1024,Ce=(e,t)=>{let n=atob(e),o=new Uint8Array(n.length);for(let i=0;i<n.length;i++)o[i]=n.charCodeAt(i);return new Blob([o],{type:t})},ct=e=>{let t=null;if(e.dataUrl){let n=e.dataUrl.indexOf(",");if(n>0){let o=e.dataUrl.slice(5,n),i=e.dataUrl.slice(n+1),r=/^([^;]+)/.exec(o)?.[1]??"application/octet-stream";try{t=/;base64/.test(o)?Ce(i,r):new Blob([decodeURIComponent(i)],{type:r});}catch{t=null;}}}else e.base64&&(t=Ce(e.base64,e.mime??"application/octet-stream"));return t?new File([t],e.name,{type:e.mime??t.type,lastModified:Date.now()}):null},ut=e=>{if(typeof e!="object"||e===null)return null;let t=Reflect.get(e,"files");if(!Array.isArray(t))return null;let n=Reflect.get(e,"paths"),o=r=>{if(!Array.isArray(n))return;let a=n[r];return typeof a=="string"?a:void 0},i=[];for(let r=0;r<t.length;r++){let a=t[r];if(typeof a!="object"||a===null)continue;let s=a,l=ct(s);if(!l)continue;let u=typeof s.path=="string"?s.path:o(r);i.push(u!==void 0?{file:l,path:u}:{file:l});}return i.length===0?null:{files:i}},dt=e=>{let t=[],n=[];if(!e)return {mimeTypes:t,extensions:n};for(let o of e)for(let i of o.split(",")){let r=i.trim();r&&(r.startsWith(".")?n.push(r):t.push(r));}return {mimeTypes:t,extensions:n}},Ae=e=>e instanceof DOMException&&e.name==="AbortError",Ie=e=>e.length>0?{files:e.map(t=>({file:t}))}:null,mt=async e=>{if(!a())return null;try{if(e?.directory){let i=await directoryOpen({recursive:!0});return Ie(i)}let{mimeTypes:t,extensions:n}=dt(e?.accept);if(e?.multiple){let i=await fileOpen({mimeTypes:t,extensions:n,multiple:!0});return Ie(i)}return {files:[{file:await fileOpen({mimeTypes:t,extensions:n})}]}}catch(t){return Ae(t),null}},pt=async(e,t)=>{if(!a())return "failed";try{return await fileSave(e,{fileName:t}),"saved"}catch(n){return Ae(n)?"cancelled":"failed"}},ft=e=>new Promise(t=>{let n=new FileReader;n.onload=()=>{let o=typeof n.result=="string"?n.result:"",i=o.indexOf(",");t(i>=0?o.slice(i+1):null);},n.onerror=()=>t(null),n.readAsDataURL(e);}),gt=e=>e===true?true:typeof e!="object"||e===null?null:Reflect.get(e,"saved")===true?true:null,Ne={isPickerSupported(){return a()?typeof window.showOpenFilePicker=="function":false},pickFiles(e){return g({native:()=>p({feature:"files",command:ue,endpointPrefix:A,payload:e??{},parseResult:ut,timeoutMs:6e4}),web:()=>mt(e),safeDefault:null})},async saveFile(e,t){if(!a())return "failed";if(e.size<=lt){let n=await ft(e);if(n!==null){let o=await Te({feature:"files",command:de,endpointPrefix:A,payload:{filename:t,mime:e.type||"application/octet-stream",size:e.size,base64:n},parseResult:gt,timeoutMs:6e4});if(o?.ok===true)return "saved";if(o?.ok===false)return o.errorCode===Ee?"cancelled":"failed"}}return v$1().type==="native_app"?"failed":pt(e,t)},readAsText(e){return typeof e.text=="function"?e.text():new Promise((t,n)=>{let o=new FileReader;o.onload=()=>{t(typeof o.result=="string"?o.result:"");},o.onerror=()=>n(o.error),o.readAsText(e);})},readAsDataUrl(e){return new Promise((t,n)=>{let o=new FileReader;o.onload=()=>{t(typeof o.result=="string"?o.result:"");},o.onerror=()=>n(o.error),o.readAsDataURL(e);})}};var v=(e,...t)=>{for(let n of t){let o=Reflect.get(e,n);if(typeof o=="number"&&!Number.isNaN(o))return o}},De=e=>{if(typeof e!="object"||e===null)return null;let t=v(e,"latitude"),n=v(e,"longitude"),o=v(e,"accuracyMeters","accuracy");if(t===void 0||n===void 0||o===void 0)return null;let i={latitude:t,longitude:n,accuracyMeters:o,timestamp:v(e,"timestamp")??Date.now()},r=v(e,"altitudeMeters","altitude");r!==void 0&&(i.altitudeMeters=r);let a=v(e,"altitudeAccuracyMeters","altitudeAccuracy");a!==void 0&&(i.altitudeAccuracyMeters=a);let s=v(e,"headingDegrees","heading");s!==void 0&&(i.headingDegrees=s);let l=v(e,"speedMetersPerSecond","speed");return l!==void 0&&(i.speedMetersPerSecond=l),i},xe=e=>({latitude:e.coords.latitude,longitude:e.coords.longitude,accuracyMeters:e.coords.accuracy,altitudeMeters:e.coords.altitude??void 0,altitudeAccuracyMeters:e.coords.altitudeAccuracy??void 0,headingDegrees:e.coords.heading??void 0,speedMetersPerSecond:e.coords.speed??void 0,timestamp:e.timestamp}),ke=e=>e?{enableHighAccuracy:e.enableHighAccuracy,timeout:e.timeoutMs,maximumAge:e.maximumAgeMs}:void 0,vt=e=>!a()||!navigator.geolocation?Promise.resolve(null):new Promise(t=>{navigator.geolocation.getCurrentPosition(n=>t(xe(n)),()=>t(null),ke(e));}),Fe={isSupported(){return a()?!!navigator.geolocation:false},getCurrentPosition(e){return g({native:()=>p({feature:"geolocation",command:te,endpointPrefix:I,payload:e??{},parseResult:De,timeoutMs:e?.timeoutMs}),web:()=>vt(e),safeDefault:null})},watchPosition(e,t){let n=false,o=null,i=null;return M({feature:"geolocation",startCommand:ne,stopCommand:oe,endpointPrefix:I,payload:t??{},parseEvent:De,onEvent:r=>{n||e(r);}}).then(r=>{if(n){r?.();return}if(r){o=r;return}if(!(!a()||!navigator.geolocation))try{i=navigator.geolocation.watchPosition(a=>{n||e(xe(a));},()=>{},ke(t));}catch{}}),()=>{if(n=true,o&&o(),i!==null&&a()&&navigator.geolocation)try{navigator.geolocation.clearWatch(i);}catch{}}}};var Et={light:10,medium:20,heavy:40,soft:15,rigid:30},yt={success:[20,60,20],warning:[40,40,40],error:[50,30,100]},ht=e=>{if(typeof navigator>"u"||typeof navigator.vibrate!="function")return false;try{return navigator.vibrate(e)}catch{return false}},_=(e,t,n)=>g({native:()=>p({feature:"haptics",command:e,endpointPrefix:j,payload:t,parseResult:()=>true}),web:async()=>ht(n),safeDefault:false}),Le={isSupported(){return a()?typeof navigator<"u"&&"vibrate"in navigator:false},async impact(e="medium"){await _(X,{strength:e},Et[e]);},async selection(){await _($,{},8);},async notification(e){await _(Z,{kind:e},yt[e]);},async vibrate(e){await _(ee,{pattern:e},e);}};var k=()=>{if(!a())return null;let e=window.MediaRecorder;return typeof e=="function"?e:null},He=()=>a()&&!!navigator.mediaDevices?.getUserMedia&&k()!==null,St=e=>{let t=e.indexOf(",");if(t<0)return null;let n=e.slice(5,t),o=e.slice(t+1),r=/^([^;]+)/.exec(n)?.[1]??"application/octet-stream";try{if(/;base64/.test(n)){let a=atob(o),s=new Uint8Array(a.length);for(let l=0;l<a.length;l++)s[l]=a.charCodeAt(l);return new Blob([s],{type:r})}return new Blob([decodeURIComponent(o)],{type:r})}catch{return null}},Pt=e=>{if(typeof e!="object"||e===null)return null;let t=Reflect.get(e,"dataUrl");if(typeof t!="string"||t.length===0)return null;let n=St(t);if(!n)return null;let o=Reflect.get(e,"mimeType"),i=Reflect.get(e,"durationMs"),r=typeof o=="string"&&o.length>0?o:n.type||"audio/octet-stream",a=typeof i=="number"&&i>=0?i:0;return {blob:n,mimeType:r,durationMs:a,size:n.size}},Rt=e=>{let t=k();if(!(!e||!t?.isTypeSupported))return t.isTypeSupported(e)?e:void 0},Ue=async e=>{if(!He())return null;let t=k();if(!t)return null;let n;try{n=await navigator.mediaDevices.getUserMedia({audio:!0});}catch{return null}let o=()=>{for(let m of n.getTracks())m.stop();},i;try{i=new t(n,{mimeType:Rt(e?.mimeType),audioBitsPerSecond:e?.audioBitsPerSecond});}catch{return o(),null}let r=[],a=Date.now(),s=false,l=false,u=null,f,h=new Promise(m=>{f=m;}),E=()=>{u!==null&&(clearTimeout(u),u=null);};i.ondataavailable=m=>{m.data&&m.data.size>0&&r.push(m.data);},i.onstop=()=>{if(E(),o(),s){f(null);return}let m=i.mimeType||e?.mimeType||"audio/webm",S=new Blob(r,{type:m});f(S.size===0?null:{blob:S,mimeType:S.type||m,durationMs:Date.now()-a,size:S.size});},i.onerror=()=>{E(),o(),f(null);};let T=()=>{if(!l){if(l=true,i.state==="inactive"){E(),o(),f(null);return}try{i.stop();}catch{E(),o(),f(null);}}};try{i.start();}catch{return o(),null}return e?.maxDurationMs&&e.maxDurationMs>0&&(u=setTimeout(T,e.maxDurationMs)),{get active(){return !l&&!s&&i.state==="recording"},stop(){return T(),h},cancel(){l||s||(s=true,T());}}},Be={isSupported(){return He()},async requestPermission(){if(!a())return false;let e=await p({feature:"microphone",command:pe,endpointPrefix:J,payload:{},parseResult:t=>{if(typeof t=="boolean")return t;if(typeof t=="object"&&t!==null){let n=Reflect.get(t,"granted");if(typeof n=="boolean")return n}return null}});if(e!==null)return e;if(!a()||!navigator.mediaDevices?.getUserMedia)return false;try{let t=await navigator.mediaDevices.getUserMedia({audio:!0});for(let n of t.getTracks())n.stop();return !0}catch{return false}},async recordAudio(e){return g({native:()=>p({feature:"microphone",command:me,endpointPrefix:Y,payload:e??{},parseResult:Pt,timeoutMs:6e4}),web:async()=>{let n=await Ue(e);if(!n)return null;let o=e?.maxDurationMs??6e4;return new Promise(i=>{setTimeout(()=>{n.stop().then(i);},o);})},safeDefault:null})},startRecording(e){return a()?Ue(e):Promise.resolve(null)}};var qe=()=>typeof DeviceMotionEvent>"u"?false:typeof DeviceMotionEvent.requestPermission=="function",Ve=async()=>{if(!qe())return true;try{let e=DeviceMotionEvent.requestPermission;return e?await e()==="granted":!0}catch{return false}},d=(e,...t)=>{for(let n of t){let o=Reflect.get(e,n);if(typeof o=="number"&&!Number.isNaN(o))return o}},F=(e,t)=>{let n=Reflect.get(e,t);if(typeof n!="object"||n===null)return;let o=d(n,"x"),i=d(n,"y"),r=d(n,"z");if(!(o===void 0||i===void 0||r===void 0))return {x:o,y:i,z:r}},Tt=e=>{if(typeof e!="object"||e===null)return null;let t=F(e,"accelerationWithGravity")??F(e,"accelerationIncludingGravity");if(!t)return null;let n=Reflect.get(e,"rotationRate"),o={alpha:0,beta:0,gamma:0};typeof n=="object"&&n!==null&&(o={alpha:d(n,"alpha")??0,beta:d(n,"beta")??0,gamma:d(n,"gamma")??0});let i={accelerationWithGravity:t,rotationRate:o,timestamp:d(e,"timestamp")??Date.now()},r=F(e,"acceleration");r&&(i.acceleration=r);let a=Reflect.get(e,"attitude");if(typeof a=="object"&&a!==null){let s=d(a,"yaw"),l=d(a,"pitch"),u=d(a,"roll");s!==void 0&&l!==void 0&&u!==void 0&&(i.attitude={yaw:s,pitch:l,roll:u});}return i},Ot=e=>{if(typeof e!="object"||e===null)return null;let t=d(e,"alpha"),n=d(e,"beta"),o=d(e,"gamma");return t===void 0||n===void 0||o===void 0?null:{alpha:t,beta:n,gamma:o,timestamp:d(e,"timestamp")??Date.now()}},Mt=e=>{let t=e.accelerationIncludingGravity,n=e.acceleration,o=e.rotationRate,i={accelerationWithGravity:{x:t?.x??0,y:t?.y??0,z:t?.z??0},rotationRate:{alpha:o?.alpha??0,beta:o?.beta??0,gamma:o?.gamma??0},timestamp:e.timeStamp||Date.now()};return n&&(n.x!==null||n.y!==null||n.z!==null)&&(i.acceleration={x:n.x??0,y:n.y??0,z:n.z??0}),i},bt=e=>({alpha:e.alpha??0,beta:e.beta??0,gamma:e.gamma??0,timestamp:e.timeStamp||Date.now()}),We={isMotionSupported(){return a()?typeof DeviceMotionEvent<"u":false},isOrientationSupported(){return a()?typeof DeviceOrientationEvent<"u":false},async requestMotionPermission(){if(!a())return false;let e=await p({feature:"sensors",command:le,endpointPrefix:Q,payload:{},parseResult:t=>{if(typeof t=="boolean")return t;if(typeof t=="object"&&t!==null){let n=Reflect.get(t,"granted");if(typeof n=="boolean")return n}return null}});return e!==null?e:Ve()},watchMotion(e,t){let n=false,o=null,i=null,r=()=>{if(n||!a())return;let s=l=>{n||e(Mt(l));};window.addEventListener("devicemotion",s),i=s;};return (async()=>{let s=await M({feature:"sensors",startCommand:ie,stopCommand:re,endpointPrefix:G,payload:t??{},parseEvent:Tt,onEvent:l=>{n||e(l);}});if(n){s?.();return}if(s){o=s;return}t?.autoRequestPermission&&qe()&&(!await Ve()||n)||r();})(),()=>{n=true,o&&o(),i&&a()&&(window.removeEventListener("devicemotion",i),i=null);}},watchOrientation(e){let t=false,n=null,o=null,i=()=>{if(t||!a())return;let a$1=s=>{t||e(bt(s));};window.addEventListener("deviceorientation",a$1),o=a$1;};return (async()=>{let a=await M({feature:"sensors",startCommand:ae,stopCommand:se,endpointPrefix:z,payload:{},parseEvent:Ot,onEvent:s=>{t||e(s);}});if(t){a?.();return}if(a){n=a;return}i();})(),()=>{t=true,n&&n(),o&&a()&&(window.removeEventListener("deviceorientation",o),o=null);}}};R();var Pn={haptics:Le,geolocation:Fe,sensors:We,camera:we,files:Ne,microphone:Be};export{we as camera,Pn as device,Ne as files,Fe as geolocation,Le as haptics,N as meetsFeatureMinVersion,Be as microphone,We as sensors};
|
|
1
|
+
import {a as a$1,d as d$1,b,p,c,r,e,q}from'../chunk-H42VJJAC.js';import {fileSave,directoryOpen,fileOpen}from'browser-fs-access';var j="device.haptics",F="device.geolocation",z="device.sensors.motion",Q="device.sensors.orientation",K="device.sensors.permission",Y="device.camera",x="device.files",$="device.microphone",J="device.microphone.permission",X="device.haptics.impact",Z="device.haptics.selection",ee="device.haptics.notification",te="device.haptics.vibrate",re="device.geolocation.get",oe="device.geolocation.watch.start",ne="device.geolocation.watch.stop",ie="device.sensors.motion.start",se="device.sensors.motion.stop",ae="device.sensors.orientation.start",ce="device.sensors.orientation.stop",le="device.sensors.requestPermission",ue="device.camera.capture",de="device.files.pick",me="device.files.save",pe="device.microphone.record",fe="device.microphone.requestPermission",ve="device-request",Ee="device-response";var ge="PERMISSION_DENIED",T="NOT_SUPPORTED",h="USER_CANCELLED";var Re="TIMEOUT";var Se=false,je=e=>typeof e!="object"||e===null?false:Reflect.get(e,"type")===Ee&&typeof Reflect.get(e,"endpoint")=="string",D=()=>{!a$1()||Se||(Se=true,d$1(),window.addEventListener("message",e=>{let r=e.data;je(r)&&b.emit(r.endpoint,r.data??r);}));};var d=(e,r)=>({ok:true,source:r,value:e}),ze=e=>{switch(e){case h:return "cancelled";case ge:return "permission_denied";case T:return "not_supported";case Re:return "timeout";case "INVALID_RESPONSE":return "invalid_response";default:return "failed"}},a=e=>({ok:false,source:e.source,reason:e.reason??ze(e.errorCode),...e.errorCode?{errorCode:e.errorCode}:{},...e.errorMessage?{errorMessage:e.errorMessage}:{}}),E=e=>{if(e instanceof Error)return e.message;if(typeof e=="string")return e};var A=e=>JSON.stringify(e),Ye=()=>a$1()&&window.parent!==window,$e=(e,r)=>{let t=L(e,r);return t?.ok===true?t.result:null},L=(e,r)=>{if(typeof e!="object"||e===null)return null;let t=Reflect.get(e,"ok");if(t===true){let o=r(Reflect.get(e,"result"));return o===null?{ok:false,errorCode:"INVALID_RESPONSE",errorMessage:"Native bridge returned an invalid response."}:{ok:true,result:o}}if(t===false){let o=Reflect.get(e,"errorCode"),n=Reflect.get(e,"errorMessage");return {ok:false,errorCode:typeof o=="string"?o:void 0,errorMessage:typeof n=="string"?n:void 0}}return null},Me=(e,r)=>e.ok?{...e,source:r}:{...e,source:r},ye=async e$1=>e$1.platform==="Android"?r(e,{pollIntervalMs:50,timeoutMs:1500}):q(e);var Je=async e=>{let r=p();if(r.type!=="native_app")return null;let t=await ye(r);if(!t)return null;let o=c(e.endpointPrefix),n=e.timeoutMs??3e3;return new Promise(i=>{let s=false,c=g=>{s||(s=true,l(),clearTimeout(m),i(g));},l=b.on(o,g=>{let M=L(g,e.parseResult);c(M?Me(M,"native"):null);}),m=setTimeout(()=>c(null),n);try{t.postMessage({command:e.command,parameters:A({endpoint:o,timestamp:Date.now(),payload:e.payload})});}catch{c(null);}})};var Xe=async e=>{if(!Ye())return null;let r=c(e.endpointPrefix),t=e.timeoutMs??3e3;return new Promise(o=>{let n=false,i=l=>{n||(n=true,s(),clearTimeout(c),o(l));},s=b.on(r,l=>{let m=L(l,e.parseResult);i(m?Me(m,"iframe"):null);}),c=setTimeout(()=>i(null),t);try{window.parent.postMessage({type:ve,command:e.command,parameters:A({endpoint:r,timestamp:Date.now(),payload:e.payload})},"*");}catch{i(null);}})};var U=async e=>{if(!a$1())return null;D();let r=await Je(e);return r!==null?r:Xe(e)},v=async e=>{let r=await U(e);return r?r.ok?d(r.result,r.source):a({source:r.source,errorCode:r.errorCode,errorMessage:r.errorMessage}):null},C=async e=>{if(!a$1())return null;D();let r=p();if(r.type!=="native_app")return null;let t=await ye(r);if(!t)return null;let o=c(e.endpointPrefix),n=b.on(o,i=>{let s=$e(i,e.parseEvent);s&&e.onEvent(s);});try{t.postMessage({command:e.startCommand,parameters:A({endpoint:o,timestamp:Date.now(),payload:e.payload})});}catch{return n(),null}return ()=>{n();try{t.postMessage({command:e.stopCommand,parameters:A({endpoint:o,timestamp:Date.now(),payload:null})});}catch{}}};var R=async e=>{if(!a$1())return e.unavailable??a({source:"sdk",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Device API is not available outside the browser."});let r=await e.native();if(r?.ok)return r;let t=null;try{if(t=await e.web(),t.ok)return t}catch(o){t=a({source:"web",errorCode:"WEB_ERROR",errorMessage:o instanceof Error?o.message:String(o)});}return r??t??e.unavailable??a({source:"sdk",reason:"not_supported",errorCode:"NOT_SUPPORTED"})};var Te=e=>e==="front"?"user":"environment",Ze={low:.5,medium:.8,high:.95},et=e=>{let r=e.indexOf(",");if(r<0)return null;let t=e.slice(5,r),o=e.slice(r+1),i=/^([^;]+)/.exec(t)?.[1]??"application/octet-stream";try{if(/;base64/.test(t)){let c=atob(o),l=new Uint8Array(c.length);for(let m=0;m<c.length;m++)l[m]=c.charCodeAt(m);return new Blob([l],{type:i})}return new Blob([decodeURIComponent(o)],{type:i})}catch{return null}},tt=e=>new Promise(r=>{let t=new FileReader;t.onload=()=>r(typeof t.result=="string"?t.result:null),t.onerror=()=>r(null),t.readAsDataURL(e);}),rt=e=>new Promise(r=>{let t=new Image;t.onload=()=>{r({width:t.naturalWidth,height:t.naturalHeight}),t.remove();},t.onerror=()=>{r(null),t.remove();},t.src=e;}),ot=e=>{if(typeof e!="object"||e===null)return null;let r=Reflect.get(e,"dataUrl"),t=Reflect.get(e,"width"),o=Reflect.get(e,"height");if(typeof r!="string"||r.length===0||typeof t!="number"||typeof o!="number")return null;let n=et(r);return n?{blob:n,dataUrl:r,width:t,height:o}:null},nt=async(e,r)=>{if(r?.format!==void 0||r?.quality!==void 0||r?.width!==void 0||r?.height!==void 0)return null;let t=Reflect.get(window,"ImageCapture");if(typeof t!="function")return null;let o=e.getVideoTracks()[0];if(!o)return null;try{let i=await new t(o).takePhoto(),s=await tt(i);if(!s)return null;let c=await rt(s);return c?{blob:i,dataUrl:s,width:c.width,height:c.height}:null}catch{return null}},he=()=>new Promise(e=>requestAnimationFrame(()=>e())),B=(e,r,t)=>new Promise(o=>{let n=false,i=()=>{n||(n=true,window.clearTimeout(s),e.removeEventListener(r,i),o());},s=window.setTimeout(i,t);e.addEventListener(r,i,{once:true});}),_e=(e,r)=>new Promise(t=>{let o=e.requestVideoFrameCallback;if(!o){requestAnimationFrame(()=>requestAnimationFrame(()=>t()));return}let n=false,i=()=>{n||(n=true,window.clearTimeout(s),t());},s=window.setTimeout(i,r);o.call(e,i);}),it=async e=>{let r=()=>e.videoWidth>0&&e.videoHeight>0;return r()||await B(e,"loadedmetadata",2e3),e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA&&await B(e,"loadeddata",2e3),e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA&&await B(e,"canplay",2e3),await _e(e,1e3),await he(),r()},st=e=>{if(e.videoWidth<=0||e.videoHeight<=0)return true;let r=document.createElement("canvas");r.width=24,r.height=24;let t=r.getContext("2d");if(!t)return false;try{t.drawImage(e,0,0,r.width,r.height);let o=t.getImageData(0,0,r.width,r.height).data,n=0,i=0;for(let c=0;c<o.length;c+=4){let l=o[c]*.2126+o[c+1]*.7152+o[c+2]*.0722;n=Math.max(n,l),i+=l;}let s=i/(o.length/4);return n<18&&s<6}catch{return false}},at=async(e,r)=>{let t=performance.now();for(;performance.now()-t<r;)if(await _e(e,700),await he(),!st(e))return},ct=async e=>{if(!a$1()||!navigator.mediaDevices?.getUserMedia)return null;let r=null,t=null;try{r=await navigator.mediaDevices.getUserMedia({video:{facingMode:Te(e?.camera),width:e?.width,height:e?.height}});let o=await nt(r,e);if(o)return o;if(t=document.createElement("video"),t.srcObject=r,t.autoplay=!0,t.muted=!0,t.playsInline=!0,t.style.position="fixed",t.style.left="0",t.style.top="0",t.style.width="2px",t.style.height="2px",t.style.opacity="0.01",t.style.pointerEvents="none",t.style.zIndex="-1",(document.body??document.documentElement).appendChild(t),await t.play(),!await it(t))return null;await at(t,3e3);let s=e?.width??t.videoWidth??640,c=e?.height??t.videoHeight??480,l=document.createElement("canvas");l.width=s,l.height=c;let m=l.getContext("2d");if(!m)return null;m.drawImage(t,0,0,s,c);let M=`image/${e?.format??"jpeg"}`,y=Ze[e?.quality??"medium"],w=l.toDataURL(M,y),p=await new Promise(O=>{l.toBlob(Ge=>O(Ge),M,y);});return p?{blob:p,dataUrl:w,width:s,height:c}:null}catch{return null}finally{if(t&&(t.pause(),t.srcObject=null,t.remove()),r)for(let o of r.getTracks())o.stop();}},lt=async e=>{let r=await ct(e);return r?d(r,"web"):a({source:"web",errorCode:"WEB_CAMERA_FAILED",errorMessage:"Camera capture failed or was denied."})},Oe={isSupported(){return a$1()?!!navigator.mediaDevices?.getUserMedia:false},capturePhoto(e){return R({native:()=>v({feature:"camera",command:ue,endpointPrefix:Y,payload:e??{},parseResult:ot,timeoutMs:6e4}),web:()=>lt(e)})},async openStream(e){if(!a$1()||!navigator.mediaDevices?.getUserMedia)return a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"getUserMedia is not available."});try{return d(await navigator.mediaDevices.getUserMedia({video:{facingMode:Te(e?.camera),width:e?.width,height:e?.height}}),"web")}catch(r){return a({source:"web",errorCode:"WEB_CAMERA_STREAM_FAILED",errorMessage:E(r)})}},stopStream(e){try{for(let r of e.getTracks())r.stop();return d(void 0,"web")}catch(r){return a({source:"web",errorCode:"WEB_CAMERA_STOP_FAILED",errorMessage:E(r)})}}};var we=8*1024*1024,De=(e,r)=>{let t=atob(e),o=new Uint8Array(t.length);for(let n=0;n<t.length;n++)o[n]=t.charCodeAt(n);return new Blob([o],{type:r})},mt=e=>{let r=null;if(e.dataUrl){let t=e.dataUrl.indexOf(",");if(t>0){let o=e.dataUrl.slice(5,t),n=e.dataUrl.slice(t+1),i=/^([^;]+)/.exec(o)?.[1]??"application/octet-stream";try{r=/;base64/.test(o)?De(n,i):new Blob([decodeURIComponent(n)],{type:i});}catch{r=null;}}}else typeof e.base64=="string"&&(r=De(e.base64,e.mime??"application/octet-stream"));return r?new File([r],e.name,{type:e.mime??r.type,lastModified:Date.now()}):null},pt=e=>{if(typeof e!="object"||e===null)return null;let r=Reflect.get(e,"files");if(!Array.isArray(r))return null;let t=Reflect.get(e,"paths"),o=i=>{if(!Array.isArray(t))return;let s=t[i];return typeof s=="string"?s:void 0},n=[];for(let i=0;i<r.length;i++){let s=r[i];if(typeof s!="object"||s===null)continue;let c=s,l=mt(c);if(!l)continue;let m=typeof c.path=="string"?c.path:o(i);n.push(m!==void 0?{file:l,path:m}:{file:l});}return n.length===0?null:{files:n}},ft=e=>{let r=[],t=[];if(!e)return {mimeTypes:r,extensions:t};for(let o of e)for(let n of o.split(",")){let i=n.trim();i&&(i.startsWith(".")?t.push(i):r.push(i));}return {mimeTypes:r,extensions:t}},Ie=e=>e instanceof DOMException&&e.name==="AbortError",Ce=e=>e.length>0?{files:e.map(r=>({file:r}))}:null,vt=async e=>{if(!a$1())return a({source:"sdk",reason:"not_supported",errorCode:T,errorMessage:"File picker is not available outside the browser."});try{if(e?.directory){let n=await directoryOpen({recursive:!0}),i=Ce(n);return i?d(i,"web"):a({source:"web",reason:"cancelled",errorCode:h,errorMessage:"File picking cancelled."})}let{mimeTypes:r,extensions:t}=ft(e?.accept);if(e?.multiple){let n=await fileOpen({mimeTypes:r,extensions:t,multiple:!0}),i=Ce(n);return i?d(i,"web"):a({source:"web",reason:"cancelled",errorCode:h,errorMessage:"File picking cancelled."})}let o=await fileOpen({mimeTypes:r,extensions:t});return d({files:[{file:o}]},"web")}catch(r){return Ie(r)?a({source:"web",reason:"cancelled",errorCode:h,errorMessage:"File picking cancelled."}):a({source:"web",errorCode:"WEB_PICK_FAILED",errorMessage:E(r)})}},Et=async(e,r)=>{if(!a$1())return a({source:"sdk",reason:"not_supported",errorCode:T,errorMessage:"File save is not available outside the browser."});try{return await fileSave(e,{fileName:r}),d({},"web")}catch(t){return Ie(t)?a({source:"web",reason:"cancelled",errorCode:h,errorMessage:"File save cancelled."}):a({source:"web",errorCode:"WEB_SAVE_FAILED",errorMessage:E(t)})}},gt=e=>new Promise(r=>{let t=new FileReader;t.onload=()=>{let o=typeof t.result=="string"?t.result:"",n=o.indexOf(",");r(n>=0?o.slice(n+1):null);},t.onerror=()=>r(null),t.readAsDataURL(e);}),Rt=e=>{if(e===true)return {saved:true};if(typeof e!="object"||e===null||Reflect.get(e,"saved")!==true)return null;let r=Reflect.get(e,"path");return {saved:true,...typeof r=="string"&&r?{path:r}:{}}},Ae={isPickerSupported(){return a$1()?typeof window.showOpenFilePicker=="function":false},pickFiles(e){return R({native:()=>v({feature:"files",command:de,endpointPrefix:x,payload:e??{},parseResult:pt,timeoutMs:6e4}),web:()=>vt(e)})},async saveFile(e,r){if(!a$1())return a({source:"sdk",reason:"not_supported",errorCode:T,errorMessage:"File save is not available outside the browser."});if(e.size<=we){let t=await gt(e);if(t!==null){let o=await U({feature:"files",command:me,endpointPrefix:x,payload:{filename:r,mime:e.type||"application/octet-stream",size:e.size,base64:t},parseResult:Rt,timeoutMs:6e4});if(o?.ok===true)return d(o.result.path?{path:o.result.path}:{},o.source);if(o?.ok===false&&(o.errorCode!==T||p().type==="native_app"))return a({source:o.source,errorCode:o.errorCode??"NATIVE_SAVE_FAILED",errorMessage:o.errorMessage})}else if(p().type==="native_app")return a({source:"sdk",errorCode:"FILE_READ_FAILED",errorMessage:"Failed to read file content for native save."})}else if(p().type==="native_app")return a({source:"sdk",errorCode:"FILE_TOO_LARGE",errorMessage:`File exceeds native bridge limit (${we} bytes).`});return p().type==="native_app"?a({source:"sdk",errorCode:"NATIVE_SAVE_UNAVAILABLE",errorMessage:"Native file save did not return a success envelope."}):Et(e,r)},async readAsText(e){try{return typeof e.text=="function"?d(await e.text(),"web"):await new Promise(r=>{let t=new FileReader;t.onload=()=>{r(d(typeof t.result=="string"?t.result:"","web"));},t.onerror=()=>{r(a({source:"web",errorCode:"READ_FAILED",errorMessage:E(t.error)}));},t.readAsText(e);})}catch(r){return a({source:"web",errorCode:"READ_FAILED",errorMessage:E(r)})}},readAsDataUrl(e){return new Promise(r=>{let t=new FileReader;t.onload=()=>{r(d(typeof t.result=="string"?t.result:"","web"));},t.onerror=()=>{r(a({source:"web",errorCode:"READ_FAILED",errorMessage:E(t.error)}));};try{t.readAsDataURL(e);}catch(o){r(a({source:"web",errorCode:"READ_FAILED",errorMessage:E(o)}));}})}};var P=(e,...r)=>{for(let t of r){let o=Reflect.get(e,t);if(typeof o=="number"&&!Number.isNaN(o))return o}},Ne=e=>{if(typeof e!="object"||e===null)return null;let r=P(e,"latitude"),t=P(e,"longitude"),o=P(e,"accuracyMeters","accuracy");if(r===void 0||t===void 0||o===void 0)return null;let n={latitude:r,longitude:t,accuracyMeters:o,timestamp:P(e,"timestamp")??Date.now()},i=P(e,"altitudeMeters","altitude");i!==void 0&&(n.altitudeMeters=i);let s=P(e,"altitudeAccuracyMeters","altitudeAccuracy");s!==void 0&&(n.altitudeAccuracyMeters=s);let c=P(e,"headingDegrees","heading");c!==void 0&&(n.headingDegrees=c);let l=P(e,"speedMetersPerSecond","speed");return l!==void 0&&(n.speedMetersPerSecond=l),n},ke=e=>({latitude:e.coords.latitude,longitude:e.coords.longitude,accuracyMeters:e.coords.accuracy,altitudeMeters:e.coords.altitude??void 0,altitudeAccuracyMeters:e.coords.altitudeAccuracy??void 0,headingDegrees:e.coords.heading??void 0,speedMetersPerSecond:e.coords.speed??void 0,timestamp:e.timestamp}),Fe=e=>e?{enableHighAccuracy:e.enableHighAccuracy,timeout:e.timeoutMs,maximumAge:e.maximumAgeMs}:void 0,St=e=>!a$1()||!navigator.geolocation?Promise.resolve(a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Geolocation API is not available."})):new Promise(r=>{navigator.geolocation.getCurrentPosition(t=>r(d(ke(t),"web")),t=>r(a({source:"web",reason:t.code===t.PERMISSION_DENIED?"permission_denied":t.code===t.TIMEOUT?"timeout":"failed",errorCode:t.code===t.PERMISSION_DENIED?"PERMISSION_DENIED":t.code===t.TIMEOUT?"TIMEOUT":"POSITION_UNAVAILABLE",errorMessage:t.message})),Fe(e));}),xe={isSupported(){return a$1()?!!navigator.geolocation:false},getCurrentPosition(e){return R({native:()=>v({feature:"geolocation",command:re,endpointPrefix:F,payload:e??{},parseResult:Ne,timeoutMs:e?.timeoutMs}),web:()=>St(e)})},async watchPosition(e,r){let t=false,o=null,n=await C({feature:"geolocation",startCommand:oe,stopCommand:ne,endpointPrefix:F,payload:r??{},parseEvent:Ne,onEvent:i=>{t||e(i);}});if(n)return d(()=>{t=true,n();},"native");if(!a$1()||!navigator.geolocation)return a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Geolocation API is not available."});try{o=navigator.geolocation.watchPosition(i=>{t||e(ke(i));},()=>{},Fe(r));}catch(i){return a({source:"web",errorCode:"WEB_GEOLOCATION_WATCH_FAILED",errorMessage:i instanceof Error?i.message:String(i)})}return d(()=>{if(t=true,o!==null&&a$1()&&navigator.geolocation)try{navigator.geolocation.clearWatch(o);}catch{}},"web")}};var Pt={light:10,medium:20,heavy:40,soft:15,rigid:30},Mt={success:[20,60,20],warning:[40,40,40],error:[50,30,100]},yt=e=>{if(typeof navigator>"u"||typeof navigator.vibrate!="function")return false;try{return navigator.vibrate(e)}catch{return false}},N=(e,r,t)=>R({native:()=>v({feature:"haptics",command:e,endpointPrefix:j,payload:r,parseResult:()=>{}}),web:async()=>yt(t)?d(void 0,"web"):a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Vibration API is not available."})}),Le={isSupported(){return a$1()?typeof navigator<"u"&&"vibrate"in navigator:false},impact(e="medium"){return N(X,{strength:e},Pt[e])},selection(){return N(Z,{},8)},notification(e){return N(ee,{kind:e},Mt[e])},vibrate(e){return N(te,{pattern:e},e)}};var H=()=>{if(!a$1())return null;let e=window.MediaRecorder;return typeof e=="function"?e:null},Be=()=>a$1()&&!!navigator.mediaDevices?.getUserMedia&&H()!==null,Tt=e=>{let r=e.indexOf(",");if(r<0)return null;let t=e.slice(5,r),o=e.slice(r+1),i=/^([^;]+)/.exec(t)?.[1]??"application/octet-stream";try{if(/;base64/.test(t)){let s=atob(o),c=new Uint8Array(s.length);for(let l=0;l<s.length;l++)c[l]=s.charCodeAt(l);return new Blob([c],{type:i})}return new Blob([decodeURIComponent(o)],{type:i})}catch{return null}},ht=e=>{if(typeof e!="object"||e===null)return null;let r=Reflect.get(e,"dataUrl");if(typeof r!="string"||r.length===0)return null;let t=Tt(r);if(!t)return null;let o=Reflect.get(e,"mimeType"),n=Reflect.get(e,"durationMs"),i=typeof o=="string"&&o.length>0?o:t.type||"audio/octet-stream",s=typeof n=="number"&&n>=0?n:0;return {blob:t,mimeType:i,durationMs:s,size:t.size}},_t=e=>{let r=H();if(!(!e||!r?.isTypeSupported))return r.isTypeSupported(e)?e:void 0},Ue=async e=>{if(!Be())return null;let r=H();if(!r)return null;let t;try{t=await navigator.mediaDevices.getUserMedia({audio:!0});}catch{return null}let o=()=>{for(let p of t.getTracks())p.stop();},n;try{n=new r(t,{mimeType:_t(e?.mimeType),audioBitsPerSecond:e?.audioBitsPerSecond});}catch{return o(),null}let i=[],s=Date.now(),c=false,l=false,m=null,g,M=new Promise(p=>{g=p;}),y=()=>{m!==null&&(clearTimeout(m),m=null);};n.ondataavailable=p=>{p.data&&p.data.size>0&&i.push(p.data);},n.onstop=()=>{if(y(),o(),c){g(null);return}let p=n.mimeType||e?.mimeType||"audio/webm",O=new Blob(i,{type:p});g(O.size===0?null:{blob:O,mimeType:O.type||p,durationMs:Date.now()-s,size:O.size});},n.onerror=()=>{y(),o(),g(null);};let w=()=>{if(!l){if(l=true,n.state==="inactive"){y(),o(),g(null);return}try{n.stop();}catch{y(),o(),g(null);}}};try{n.start();}catch{return o(),null}return e?.maxDurationMs&&e.maxDurationMs>0&&(m=setTimeout(w,e.maxDurationMs)),{get active(){return !l&&!c&&n.state==="recording"},async stop(){w();let p=await M;return p?d(p,"web"):a({source:"web",errorCode:"WEB_MICROPHONE_FAILED",errorMessage:"Microphone recording produced no audio."})},cancel(){l||c||(c=true,w());}}},He={isSupported(){return Be()},async requestPermission(){if(!a$1())return a({source:"sdk",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Microphone is not available outside the browser."});let e=await v({feature:"microphone",command:fe,endpointPrefix:J,payload:{},parseResult:r=>{if(typeof r=="boolean")return r;if(typeof r=="object"&&r!==null){let t=Reflect.get(r,"granted");if(typeof t=="boolean")return t}return null}});if(e)return e.ok?e.value?e:a({source:e.source,reason:"permission_denied",errorCode:"PERMISSION_DENIED",errorMessage:"Microphone permission denied."}):e;if(!a$1()||!navigator.mediaDevices?.getUserMedia)return a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"getUserMedia is not available."});try{let r=await navigator.mediaDevices.getUserMedia({audio:!0});for(let t of r.getTracks())t.stop();return d(!0,"web")}catch(r){return a({source:"web",reason:"permission_denied",errorCode:"PERMISSION_DENIED",errorMessage:E(r)})}},async recordAudio(e){return R({native:()=>v({feature:"microphone",command:pe,endpointPrefix:$,payload:e??{},parseResult:ht,timeoutMs:6e4}),web:async()=>{let t=await Ue(e);if(!t)return a({source:"web",errorCode:"WEB_MICROPHONE_FAILED",errorMessage:"Microphone recording could not start."});let o=e?.maxDurationMs??6e4;return new Promise(n=>{setTimeout(()=>{t.stop().then(n);},o);})}})},async startRecording(e){if(!a$1())return a({source:"sdk",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Microphone is not available outside the browser."});let r=await Ue(e);return r?d(r,"web"):a({source:"web",errorCode:"WEB_MICROPHONE_FAILED",errorMessage:"Microphone recording could not start."})}};var We=()=>typeof DeviceMotionEvent>"u"?false:typeof DeviceMotionEvent.requestPermission=="function",Ve=async()=>{if(!We())return true;try{let e=DeviceMotionEvent.requestPermission;return e?await e()==="granted":!0}catch{return false}},f=(e,...r)=>{for(let t of r){let o=Reflect.get(e,t);if(typeof o=="number"&&!Number.isNaN(o))return o}},V=(e,r)=>{let t=Reflect.get(e,r);if(typeof t!="object"||t===null)return;let o=f(t,"x"),n=f(t,"y"),i=f(t,"z");if(!(o===void 0||n===void 0||i===void 0))return {x:o,y:n,z:i}},Ot=e=>{if(typeof e!="object"||e===null)return null;let r=V(e,"accelerationWithGravity")??V(e,"accelerationIncludingGravity");if(!r)return null;let t=Reflect.get(e,"rotationRate"),o={alpha:0,beta:0,gamma:0};typeof t=="object"&&t!==null&&(o={alpha:f(t,"alpha")??0,beta:f(t,"beta")??0,gamma:f(t,"gamma")??0});let n={accelerationWithGravity:r,rotationRate:o,timestamp:f(e,"timestamp")??Date.now()},i=V(e,"acceleration");i&&(n.acceleration=i);let s=Reflect.get(e,"attitude");if(typeof s=="object"&&s!==null){let c=f(s,"yaw"),l=f(s,"pitch"),m=f(s,"roll");c!==void 0&&l!==void 0&&m!==void 0&&(n.attitude={yaw:c,pitch:l,roll:m});}return n},bt=e=>{if(typeof e!="object"||e===null)return null;let r=f(e,"alpha"),t=f(e,"beta"),o=f(e,"gamma");return r===void 0||t===void 0||o===void 0?null:{alpha:r,beta:t,gamma:o,timestamp:f(e,"timestamp")??Date.now()}},wt=e=>{let r=e.accelerationIncludingGravity,t=e.acceleration,o=e.rotationRate,n={accelerationWithGravity:{x:r?.x??0,y:r?.y??0,z:r?.z??0},rotationRate:{alpha:o?.alpha??0,beta:o?.beta??0,gamma:o?.gamma??0},timestamp:e.timeStamp||Date.now()};return t&&(t.x!==null||t.y!==null||t.z!==null)&&(n.acceleration={x:t.x??0,y:t.y??0,z:t.z??0}),n},Dt=e=>({alpha:e.alpha??0,beta:e.beta??0,gamma:e.gamma??0,timestamp:e.timeStamp||Date.now()}),qe={isMotionSupported(){return a$1()?typeof DeviceMotionEvent<"u":false},isOrientationSupported(){return a$1()?typeof DeviceOrientationEvent<"u":false},async requestMotionPermission(){if(!a$1())return a({source:"sdk",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Motion sensors are not available outside the browser."});let e=await v({feature:"sensors",command:le,endpointPrefix:K,payload:{},parseResult:t=>{if(typeof t=="boolean")return t;if(typeof t=="object"&&t!==null){let o=Reflect.get(t,"granted");if(typeof o=="boolean")return o}return null}});return e?e.ok?e.value?e:a({source:e.source,reason:"permission_denied",errorCode:"PERMISSION_DENIED",errorMessage:"Motion permission denied."}):e:await Ve()?d(true,"web"):a({source:"web",reason:"permission_denied",errorCode:"PERMISSION_DENIED",errorMessage:"Motion permission denied."})},async watchMotion(e,r){let t=false,o=null,n=()=>{if(t||!a$1()||typeof DeviceMotionEvent>"u")return a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Motion sensors are not available."});let s=c=>{t||e(wt(c));};return window.addEventListener("devicemotion",s),o=s,d(()=>{t=true,o&&a$1()&&(window.removeEventListener("devicemotion",o),o=null);},"web")},i=await C({feature:"sensors",startCommand:ie,stopCommand:se,endpointPrefix:z,payload:r??{},parseEvent:Ot,onEvent:s=>{t||e(s);}});return i?d(()=>{t=true,i();},"native"):r?.autoRequestPermission&&We()&&(!await Ve()||t)?a({source:"web",reason:"permission_denied",errorCode:"PERMISSION_DENIED",errorMessage:"Motion permission denied."}):n()},async watchOrientation(e){let r=false,t=null,o=()=>{if(r||!a$1()||typeof DeviceOrientationEvent>"u")return a({source:"web",reason:"not_supported",errorCode:"NOT_SUPPORTED",errorMessage:"Orientation sensors are not available."});let i=s=>{r||e(Dt(s));};return window.addEventListener("deviceorientation",i),t=i,d(()=>{r=true,t&&a$1()&&(window.removeEventListener("deviceorientation",t),t=null);},"web")},n=await C({feature:"sensors",startCommand:ae,stopCommand:ce,endpointPrefix:Q,payload:{},parseEvent:bt,onEvent:i=>{r||e(i);}});return n?d(()=>{r=true,n();},"native"):o()}};D();var Ir={haptics:Le,geolocation:xe,sensors:qe,camera:Oe,files:Ae,microphone:He};export{Oe as camera,Ir as device,Ae as files,xe as geolocation,Le as haptics,He as microphone,qe as sensors};
|
package/dist/react/index.d.ts
CHANGED
package/dist/react/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {b,a,c,e}from'../chunk-
|
|
1
|
+
import {b,a,c,e}from'../chunk-V73IHZAF.js';import'../chunk-H42VJJAC.js';import {useSyncExternalStore,useState,useCallback,useEffect}from'react';var k="",d=()=>{let u=useSyncExternalStore(b,a,()=>k),[s,e]=useState(()=>a()===""),t=useCallback(async()=>{e(true),await c(),e(false);},[]);return useEffect(()=>{if(a()!==""){e(false);return}let o=true;return c().then(()=>{o&&e(false);}),()=>{o=false;}},[]),{token:u,loading:s,refetch:t}};var I=()=>{let[u,s]=useState(null),[e$1,t]=useState(true),o=useCallback(async()=>{t(true);let r=await e();s(r),t(false);},[]);return useEffect(()=>{let r=true;return e().then(c=>{r&&(s(c),t(false));}),()=>{r=false;}},[]),{user:u,loading:e$1,refetch:o}};export{d as useAuthToken,I as useUserInfo};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Credentials {
|
|
2
|
+
uid: string;
|
|
3
|
+
token: string;
|
|
4
|
+
}
|
|
5
|
+
interface UserInfo {
|
|
6
|
+
userId: string | number;
|
|
7
|
+
username?: string;
|
|
8
|
+
nickname?: string;
|
|
9
|
+
avatar?: string | null;
|
|
10
|
+
phone?: string | null;
|
|
11
|
+
email?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type { Credentials as C, UserInfo as U };
|
package/dist/user/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UserInfo } from '../types-
|
|
2
|
-
export { C as Credentials } from '../types-
|
|
1
|
+
import { U as UserInfo } from '../types-CLujY9ck.js';
|
|
2
|
+
export { C as Credentials } from '../types-CLujY9ck.js';
|
|
3
3
|
|
|
4
4
|
declare const getAuthTokenAsync: () => Promise<string>;
|
|
5
5
|
declare const getUserInfoAsync: () => Promise<UserInfo | null>;
|
package/dist/user/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{c as getAuthTokenAsync,e as getUserInfoAsync}from'../chunk-
|
|
1
|
+
export{c as getAuthTokenAsync,e as getUserInfoAsync}from'../chunk-V73IHZAF.js';import'../chunk-H42VJJAC.js';
|
package/package.json
CHANGED
package/dist/chunk-AKZVV563.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import {a as a$1,b,j as j$1,d,f,g,k,o,m,v,q,x,e,s,r,w,c as c$1,p,l,n,h,i}from'./chunk-ALNJCFV4.js';var E=e=>typeof e=="object"&&e!==null,a=(e,n)=>{if(e)for(let t of n){let r=e[t];if(typeof r=="string"&&r.length>0)return r}},$=(e,n)=>{if(e)for(let t of n){let r=e[t];if(typeof r=="string"&&r.length>0||typeof r=="number"&&Number.isFinite(r))return r}},u=e=>{if(!E(e))return null;let n=E(e.credentials)?e.credentials:void 0,t=E(e.user)?e.user:void 0,r=a(e,["uid","userId","id"])??a(n,["uid","userId","id"])??a(t,["uid","userId","id"]),o=a(e,["token","authToken"])??a(n,["token","authToken"]);return !r||!o?null:{uid:r,token:o}},c=e=>{if(!E(e))return null;let n=E(e.data)?e.data:e,t=$(n,["userId","id","uid"]);if(t===void 0)return null;let r=a(n,["username","nickname","nickName","name"]),o=a(n,["nickname","nickName","username"]);return {...n,userId:t,...r?{username:r}:{},...o?{nickname:o}:{}}};var ee=e=>typeof e!="object"||e===null?false:typeof Reflect.get(e,"type")=="string",H=false,V=()=>{!a$1()||H||(H=true,d(),Reflect.set(window,f,e=>{u(e)&&b.emit(j$1,e);}),Reflect.set(window,g,e=>{c(e)&&b.emit(k,e);}),window.addEventListener("message",e=>{let n=e.data;if(ee(n))switch(n.type){case m:b.emit("iframe.credentials",n);break;case o:b.emit("iframe.userinfo",n);break}}));};var j=(e,n,t)=>new Promise(r=>{let o=false,f=i=>{o||(o=true,y(),clearTimeout(T),r(i));},y=b.on(n,i=>{let g=t(i);g&&f(g);}),T=setTimeout(()=>f(null),q);try{window.parent.postMessage({type:e,timestamp:Date.now()},"*");}catch{f(null);}}),G=()=>j(l,"iframe.credentials",u),Q=()=>j(n,"iframe.userinfo",c);var J=async(e$1,n,t,r$1)=>{let o=e$1.platform==="Android"?await x(e,{pollIntervalMs:r,timeoutMs:s}):w(e);if(!o)return null;let f=c$1(t);return new Promise(y=>{let T=false,i=d=>{T||(T=true,g(),Y(),clearTimeout(Z),y(d));},g=b.on(f,d=>{let p=r$1(d);p&&i(p);}),Y=b.on(t,d=>{let p=r$1(d);p&&i(p);}),Z=setTimeout(()=>i(null),p);try{o.postMessage({command:n,parameters:JSON.stringify({timestamp:Date.now(),endpoint:f})});}catch{i(null);}})},z=e=>J(e,h,j$1,u),K=e=>J(e,i,k,c);V();var C=null,I=null,R=new Set,ne=e=>{switch(e.type){case "native_app":return e.meetsMinVersion?z(e):Promise.resolve(null);case "iframe":return G();case "web":return Promise.resolve(null)}},re=e=>{switch(e.type){case "native_app":return e.meetsMinVersion?K(e):Promise.resolve(null);case "iframe":return Q();case "web":return Promise.resolve(null)}},W=e=>{let n=C?.token??"",t=e?.token??"";if(C=e,n!==t)for(let r of R)try{r();}catch{}},Ne=()=>C?.token??"",ve=e=>(R.add(e),()=>{R.delete(e);}),X=()=>I||(I=ne(v()).then(e=>(e&&W(e),e)).finally(()=>{I=null;}),I);a$1()&&b.on(j$1,e=>{let n=u(e);n&&W(n);});var te=async()=>a$1()?C?C.token:(await X())?.token??"":"",Pe=async()=>a$1()?(await X())?.token??"":"",se=async()=>a$1()?re(v()):null;export{Ne as a,ve as b,te as c,Pe as d,se as e};
|
package/dist/chunk-ALNJCFV4.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var o=()=>typeof window<"u"&&typeof document<"u";var _="hostRuntime",p=class{listeners=new Map;on(e,t){let s=this.listeners.get(e),r=s??new Set;return s||this.listeners.set(e,r),r.add(t),()=>{r.delete(t),r.size===0&&this.listeners.delete(e);}}emit(e,t){let s=this.listeners.get(e);if(s)for(let r of s)r(t);}},R=new p,a=0,A=n=>(a+=1,`${n}.${a}`),l=false,I=()=>{if(!o()||l)return;l=true,Reflect.set(window,_,{receiveMessage(e){if(!e)return;let t=e.endpoint;t&&R.emit(t,e.data??e);}});};var E="HostApp",v="hostListener";var O="processUserCredentials",L="processUserInfo",H="user.getCredentials",b="user.getUserInfo",P="user.credentials",U="user.info",k="user-credentials-request",y="user-credentials-response",F="user-info-request",h="user-info-response",f={iOS:[1,6,7],Android:[1,1,8]},C=3e3,D=500,V=50,B=1500;var d=n=>{let e=n.split(".").map(t=>Number.parseInt(t,10));return [e[0]??0,e[1]??0,e[2]??0]},m=(n,e)=>{for(let t=0;t<3;t++){if(n[t]>e[t])return true;if(n[t]<e[t])return false}return true};var N=new RegExp(`${E}\\/(\\d+\\.\\d+\\.\\d+)\\/(\\d+)\\/(iOS|Android)`),g=n=>{let e=n.match(N);if(!e)return null;let[,t,s,r]=e;if(!t||!s||r!=="iOS"&&r!=="Android")return null;let i=m(d(t),f[r]);return {type:"native_app",platform:r,appVersion:t,buildNumber:s,meetsMinVersion:i}},Q=()=>{if(!o())return {type:"web",meetsMinVersion:false};let n=g(navigator.userAgent??"");return n||(window.parent!==window?{type:"iframe",meetsMinVersion:false}:{type:"web",meetsMinVersion:false})};var S=n=>typeof n!="object"||n===null?false:typeof Reflect.get(n,"postMessage")=="function",T=n=>{let e=Reflect.get(window,"webkit");if(typeof e=="object"&&e!==null){let s=Reflect.get(e,"messageHandlers");if(typeof s=="object"&&s!==null){let r=Reflect.get(s,n);if(S(r))return r}}let t=Reflect.get(window,n);return S(t)?t:null},X=(n,e={})=>{let{pollIntervalMs:t=50,timeoutMs:s=1500}=e;return new Promise(r=>{let i=Date.now(),u=()=>{let c=T(n);if(c){r(c);return}if(Date.now()-i>=s){r(null);return}setTimeout(u,t);};u();})};export{o as a,R as b,A as c,I as d,v as e,O as f,L as g,H as h,b as i,P as j,U as k,k as l,y as m,F as n,h as o,C as p,D as q,V as r,B as s,d as t,m as u,Q as v,T as w,X as x};
|
package/dist/types-DryABknE.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
interface Credentials {
|
|
2
|
-
uid: string;
|
|
3
|
-
token: string;
|
|
4
|
-
}
|
|
5
|
-
interface UserInfo {
|
|
6
|
-
userId: string | number;
|
|
7
|
-
username?: string;
|
|
8
|
-
nickname?: string;
|
|
9
|
-
avatar?: string | null;
|
|
10
|
-
phone?: string | null;
|
|
11
|
-
email?: string;
|
|
12
|
-
[key: string]: unknown;
|
|
13
|
-
}
|
|
14
|
-
type AppEnvironmentType = "native_app" | "iframe" | "web";
|
|
15
|
-
interface AppEnvironment {
|
|
16
|
-
type: AppEnvironmentType;
|
|
17
|
-
platform?: "iOS" | "Android";
|
|
18
|
-
appVersion?: string;
|
|
19
|
-
buildNumber?: string;
|
|
20
|
-
meetsMinVersion: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type { AppEnvironment as A, Credentials as C, UserInfo as U };
|