@stacksjs/mobile 0.75.87 → 0.75.88
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/dist/index.d.ts +46 -3
- package/dist/index.js +1 -1
- package/dist/indoor.d.ts +37 -0
- package/dist/types.d.ts +5 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bundled TypeScript declarations
|
|
3
|
-
* Generated from
|
|
3
|
+
* Generated from 7 source files
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// From: src/index.ts
|
|
@@ -234,6 +234,45 @@ declare interface RouteRecorder {
|
|
|
234
234
|
readonly stats: RouteStats
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
// From: src/indoor.ts
|
|
238
|
+
/**
|
|
239
|
+
* `elapsedS` is the session's own time, pauses left out. 'unsure' until it
|
|
240
|
+
* has run INDOOR_CHECK_AFTER_S; 'outside' as soon as the route has clearly
|
|
241
|
+
* gone somewhere.
|
|
242
|
+
*
|
|
243
|
+
* Measured robustly, because indoor GPS jumps: the middle is the median
|
|
244
|
+
* position and the spread is how far the nearest 80% of fixes lie from it,
|
|
245
|
+
* so one fix thrown 150 m across town neither hides a treadmill nor proves a
|
|
246
|
+
* run outside. A 400 m track (fixes within ~60 m of its middle, but sharp)
|
|
247
|
+
* is not mistaken for a treadmill: wandering only counts with a vague signal.
|
|
248
|
+
*/
|
|
249
|
+
declare function indoorVerdict(fixes: IndoorFix[], elapsedS: number): IndoorVerdict;
|
|
250
|
+
/** A distance typed off a treadmill's display, as kilometres: "8.4", "8,4", "8400 m". */
|
|
251
|
+
declare function typedDistanceKm(input: string): number | null;
|
|
252
|
+
/** Seconds a session runs before the verdict is trusted. */
|
|
253
|
+
declare const INDOOR_CHECK_AFTER_S: 150;
|
|
254
|
+
/**
|
|
255
|
+
* Whether a run or ride being recorded is happening indoors: on a treadmill,
|
|
256
|
+
* or a bike on a trainer. Read the recording (`location.readRecording()`)
|
|
257
|
+
* every half minute or so while it runs and switch to a timed, GPS-free
|
|
258
|
+
* session when this says 'indoors'.
|
|
259
|
+
*
|
|
260
|
+
* Indoors the phone still reports positions, wandering around the room
|
|
261
|
+
* by tens of metres, and those wanderings added up to kilometres and a pace
|
|
262
|
+
* from nowhere ("2.82 km" and a 5:31 average over fifty minutes on a
|
|
263
|
+
* treadmill). Outside, even a walk leaves a 60-metre circle within a couple
|
|
264
|
+
* of minutes. So once a session has run long enough to tell, a route that
|
|
265
|
+
* never left that circle, a signal that never got good, or no positions at
|
|
266
|
+
* all, means the session is indoors and GPS is the wrong source for it.
|
|
267
|
+
*/
|
|
268
|
+
declare interface IndoorFix {
|
|
269
|
+
latitude: number
|
|
270
|
+
longitude: number
|
|
271
|
+
accuracy?: number | null
|
|
272
|
+
timestamp: number
|
|
273
|
+
}
|
|
274
|
+
type IndoorVerdict = 'indoors' | 'outside' | 'unsure';
|
|
275
|
+
|
|
237
276
|
// From: src/spotlight.ts
|
|
238
277
|
/**
|
|
239
278
|
* Read configured kinds, leaving out any that could not work.
|
|
@@ -787,7 +826,11 @@ type PermissionType = | 'camera'
|
|
|
787
826
|
| 'motion'
|
|
788
827
|
| 'health';
|
|
789
828
|
type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'restricted';
|
|
790
|
-
|
|
829
|
+
/**
|
|
830
|
+
* The kind of biometric the device offers. Craft reports `'none'` as well
|
|
831
|
+
* since craft-native 0.0.119, so the type admits it.
|
|
832
|
+
*/
|
|
833
|
+
type BiometricType = 'faceId' | 'touchId' | 'fingerprint' | 'face' | 'iris' | 'none';
|
|
791
834
|
type AppState = 'active' | 'inactive' | 'background';
|
|
792
835
|
type HealthDataType = | 'steps'
|
|
793
836
|
| 'heartRate'
|
|
@@ -806,4 +849,4 @@ type HealthWorkoutActivity = | 'running' | 'cycling' | 'walking' | 'hiking' | 's
|
|
|
806
849
|
| 'stairClimbing' | 'yoga' | 'pilates' | 'strength' | 'hiit' | 'crossTraining'
|
|
807
850
|
| 'crossCountrySkiing' | 'skiing' | 'paddling' | 'climbing' | 'dance' | 'mobility' | 'other';
|
|
808
851
|
|
|
809
|
-
export { normalizeDeepLinkURL, getNativeMobileBridge, isNativeMobile, hasNativeMobileHost, whenNativeMobile, whenBridgeReady, onMobileReady, withNativeFeedback, biometrics, camera, device, haptics, lifecycle, location, notifications, permissions, secureStorage, share, appReview, deepLinks, keepAwake, speech, network, pushNotifications, health, liveActivities, watchConnectivity, mobile, pageScrollTop, observePageScroll, pullDistance, observePullToRefresh, ScrollHost, PullToRefreshOptions, canGoBack, goBack, enterNavTrail, backLabelFor, navTrail, deepLinkPath, followDeepLinks, HistoryHost, NavTrailEntry, fixDistance, usableFixes, routeStats, paceLabel, speedLabel, createRouteRecorder, ROUTE_GAP_S, RouteFix, RouteStats, RouteStatsOptions, RouteRecorderOptions, RouteRecorder, readSpotlightKinds, spotlightKind, spotlightAction, spotlightSlot, spotlightActions, spotlightActivityTypes, spotlightTitle, placeSpotlightItem, removeSpotlightItem, spotlightRoute, readSpotlightEntries, spotlightBridge, createSpotlightIndex, onSpotlightTap, MAX_SPOTLIGHT_SLOTS_PER_KIND, SpotlightKind, SpotlightKindInput, SpotlightItem, SpotlightEntry, SpotlightKindsResult, SpotlightPlacement, SpotlightBridge, SpotlightIndexOptions, SpotlightIndex, CraftMobileCapabilities, CraftMobileBridge, CraftReadyEvent, MobileApi, DeviceInfo, DeviceCapabilities, CameraOptions, PhotoResult, Location, LocationOptions, LocationRecordingState, LocationRecordingResult, ShareOptions, NotificationOptions, DeviceApi, HapticsApi, PermissionsApi, CameraApi, BiometricsApi, SecureStorageApi, LocationApi, ShareApi, LifecycleApi, NotificationsApi, KeepAwakeApi, SpeechOptions, SpeechApi, DeepLinksApi, NetworkStatus, NetworkApi, AppReviewApi, PushNotificationsApi, HealthDataOptions, HealthDataResult, HealthWorkoutLocation, HealthWorkout, HealthWorkoutResult, HealthWorkoutQuery, HealthWorkoutSample, HealthDailyValue, HealthAuthorizationOptions, HealthApi, LiveActivityState, LiveActivityOptions, LiveActivitiesApi, WatchConnectivityApi, HapticStyle, HapticNotificationType, PermissionType, PermissionStatus, BiometricType, AppState, HealthDataType, HealthDailyType, HealthWorkoutType, HealthWorkoutActivity };
|
|
852
|
+
export { normalizeDeepLinkURL, getNativeMobileBridge, isNativeMobile, hasNativeMobileHost, whenNativeMobile, whenBridgeReady, onMobileReady, withNativeFeedback, biometrics, camera, device, haptics, lifecycle, location, notifications, permissions, secureStorage, share, appReview, deepLinks, keepAwake, speech, network, pushNotifications, health, liveActivities, watchConnectivity, mobile, pageScrollTop, observePageScroll, pullDistance, observePullToRefresh, ScrollHost, PullToRefreshOptions, canGoBack, goBack, enterNavTrail, backLabelFor, navTrail, deepLinkPath, followDeepLinks, HistoryHost, NavTrailEntry, fixDistance, usableFixes, routeStats, paceLabel, speedLabel, createRouteRecorder, ROUTE_GAP_S, RouteFix, RouteStats, RouteStatsOptions, RouteRecorderOptions, RouteRecorder, indoorVerdict, typedDistanceKm, INDOOR_CHECK_AFTER_S, IndoorFix, IndoorVerdict, readSpotlightKinds, spotlightKind, spotlightAction, spotlightSlot, spotlightActions, spotlightActivityTypes, spotlightTitle, placeSpotlightItem, removeSpotlightItem, spotlightRoute, readSpotlightEntries, spotlightBridge, createSpotlightIndex, onSpotlightTap, MAX_SPOTLIGHT_SLOTS_PER_KIND, SpotlightKind, SpotlightKindInput, SpotlightItem, SpotlightEntry, SpotlightKindsResult, SpotlightPlacement, SpotlightBridge, SpotlightIndexOptions, SpotlightIndex, CraftMobileCapabilities, CraftMobileBridge, CraftReadyEvent, MobileApi, DeviceInfo, DeviceCapabilities, CameraOptions, PhotoResult, Location, LocationOptions, LocationRecordingState, LocationRecordingResult, ShareOptions, NotificationOptions, DeviceApi, HapticsApi, PermissionsApi, CameraApi, BiometricsApi, SecureStorageApi, LocationApi, ShareApi, LifecycleApi, NotificationsApi, KeepAwakeApi, SpeechOptions, SpeechApi, DeepLinksApi, NetworkStatus, NetworkApi, AppReviewApi, PushNotificationsApi, HealthDataOptions, HealthDataResult, HealthWorkoutLocation, HealthWorkout, HealthWorkoutResult, HealthWorkoutQuery, HealthWorkoutSample, HealthDailyValue, HealthAuthorizationOptions, HealthApi, LiveActivityState, LiveActivityOptions, LiveActivitiesApi, WatchConnectivityApi, HapticStyle, HapticNotificationType, PermissionType, PermissionStatus, BiometricType, AppState, HealthDataType, HealthDailyType, HealthWorkoutType, HealthWorkoutActivity };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{appReview as mt,biometrics as gt,camera as ht,deepLinks as U,device as yt,haptics as St,health as vt,keepAwake as bt,lifecycle as xt,liveActivities as At,location as wt,network as Rt,notifications as Tt,permissions as Et,pushNotifications as kt,secureStorage as Lt,share as Pt,speech as Mt,watchConnectivity as It}from"craft-native/mobile";import{haptics as z}from"craft-native/mobile";function M(){if(typeof window>"u")return;return window}function k(t=M()){if(!t)return 0;if(typeof t.scrollY==="number")return t.scrollY;return t.document?.scrollingElement?.scrollTop??0}function te(t,n=M()){if(!n)return()=>{};let r=!1,e=typeof requestAnimationFrame==="function"?requestAnimationFrame:(i)=>setTimeout(i,16),o=()=>{if(r)return;r=!0,e(()=>{r=!1,t(k(n))})};return t(k(n)),n.addEventListener("scroll",o,{passive:!0}),()=>n.removeEventListener("scroll",o)}function J(t,n){let r=Math.max(0,-t),e=t<=0?Math.max(0,n)*0.5:0;return Math.round(Math.max(r,e))}function ee(t){let n=t.host??M();if(!n)return()=>{};let r=t.threshold??72,e=null,o=!1,i=!1,s=typeof requestAnimationFrame==="function"?requestAnimationFrame:(g)=>setTimeout(g,16),l=null,a=(g)=>{l=null,t.onPull?.(g,o)},u=(g)=>{let b=l!==null;if(l=g,b)return;s(()=>{if(l!==null)a(l)})},h=(g)=>{let b=g.touches?.[0];return b?b.clientY:null},d=(g)=>{if(i||k(n)>0)return;e=h(g),o=!1},p=(g)=>{if(e===null)return;let b=h(g);if(b===null)return;let A=J(k(n),b-e);if(!o&&A>=r)o=!0,Promise.resolve(z.impact("medium")).catch(()=>{});else if(o&&A<r*0.8)o=!1;u(A)},v=async()=>{if(e===null)return;if(e=null,!o){a(0);return}o=!1,i=!0,a(r);try{await t.onRefresh()}finally{i=!1,a(0)}},m=()=>{if(e===null)return;e=null,o=!1,a(0)};return n.addEventListener("touchstart",d,{passive:!0}),n.addEventListener("touchmove",p,{passive:!0}),n.addEventListener("touchend",v),n.addEventListener("touchcancel",m),()=>{l=null,n.removeEventListener("touchstart",d),n.removeEventListener("touchmove",p),n.removeEventListener("touchend",v),n.removeEventListener("touchcancel",m)}}function N(){if(typeof window>"u")return;return window}function V(t=N()){let n=t?.history?.state;return n!==null&&n!==void 0}function re(t=N()){if(!V(t))return!1;return t.history.back(),!0}function oe(t,n,r=50){let e=t[t.length-1];if(t.length>=2&&t[t.length-2].path===n)t.pop();else if(!e||e.path!==n)t.push({path:n,title:""});if(t.length>r)t.splice(0,t.length-r);return{current:t[t.length-1],previous:t[t.length-2]??null}}function ie(t,n,r=12){let e=t?.title.trim()??"";return e&&e.length<=r?e:n}function se(){if(typeof window>"u")return[];let t=window;return t.__stacksNavTrail??=[]}function Q(t,n=Z()){let r;try{r=new URL(t)}catch{return null}let e=`${r.search}${r.hash}`;if(r.protocol==="http:"||r.protocol==="https:"){if(!n||r.origin!==n)return null;return`${r.pathname||"/"}${e}`}return`${`/${[r.host,r.pathname.replace(/^\/+/,"")].filter(Boolean).join("/")}`}${e}`}function Z(){if(typeof window>"u")return;return window.location?.origin}var _="stacks-mobile-deep-link";function ae(t,n){let r=(e)=>{let o=Q(e);if(o)t(o)};return n.getInitialURL().then((e)=>{if(!e)return;try{if(sessionStorage.getItem(_)===e)return;sessionStorage.setItem(_,e)}catch{}r(e)}).catch(()=>{}),n.onLink((e,o)=>{if(o?.initial)return;r(e)})}var ce=30;function tt(t,n){let r=Math.PI/180,e=(n.latitude-t.latitude)*r,o=(n.longitude-t.longitude)*r,i=Math.sin(e/2)**2+Math.cos(t.latitude*r)*Math.cos(n.latitude*r)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function et(t,n=25){let r=new Set;return t.filter((e)=>Number.isFinite(e.latitude)&&Number.isFinite(e.longitude)&&Number.isFinite(e.timestamp)&&e.accuracy>=0&&e.accuracy<=n).sort((e,o)=>e.timestamp-o.timestamp).filter((e)=>{if(r.has(e.timestamp))return!1;return r.add(e.timestamp),!0})}function O(t,n={}){let r=et(t,n.maxAccuracyM??25),e=n.paceWindowS??30,o=[],i=0,s=0,l=null;for(let d of r){let p=o[o.length-1],v=l?(d.timestamp-l.timestamp)/1000:0;if(l=d,!p){o.push({fix:d,cumM:0});continue}if(v>30){o.push({fix:d,cumM:i});continue}let m=(d.timestamp-p.fix.timestamp)/1000,g=tt(p.fix,d),b=Math.min(10,Math.max(3,p.fix.accuracy,d.accuracy));if(g<b)continue;if(i+=g,m>0&&g/m>=0.5)s+=m;o.push({fix:d,cumM:i})}let a=o[o.length-1],u=null,h=null;if(a){let d=a.fix.timestamp-e*1000,p=o.find((g)=>g.fix.timestamp>=d)??a,v=a.cumM-p.cumM,m=(a.fix.timestamp-p.fix.timestamp)/1000;if(v>=20&&m>0)h=v/m,u=m/(v/1000)}return{distanceM:i,movingS:s,paceSPerKm:u,averagePaceSPerKm:i>=50&&s>0?s/(i/1000):null,speedMps:h,accuracyM:r.length?r[r.length-1].accuracy:t.length?t[t.length-1].accuracy??null:null,fixes:r.length}}function ue(t){if(!t||!Number.isFinite(t)||t>3600)return"–";let n=Math.round(t);return`${Math.floor(n/60)}:${String(n%60).padStart(2,"0")}`}function de(t){return t&&Number.isFinite(t)?(t*3.6).toFixed(1):"–"}var H={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function fe(t){let n=t.location,r=t.intervalMs??3000,e=H,o=null,i=()=>typeof document<"u"&&document.visibilityState==="hidden";async function s(){let u=await n.readRecording();return e=O(u,t),t.onUpdate?.(e),e}function l(){a(),o=setInterval(()=>{if(!i())s().catch(()=>{})},r)}function a(){if(o)clearInterval(o);o=null}return{get stats(){return e},async start(){return await n.startRecording({enableHighAccuracy:!0,...t.locationOptions}),e=H,t.onUpdate?.(e),l(),e},async attach(){let u=await n.getRecordingState().catch(()=>null);if(!u?.active)return null;if(await s().catch(()=>{}),!u.paused)l();return u},async pause(){a(),await n.pauseRecording(),await s().catch(()=>{})},async resume(){await n.resumeRecording(),l()},async stop(){a();let h=(await n.stopRecording())?.locations??[];return e=O(h,t),t.onUpdate?.(e),h},refresh:s}}var me=64;var nt=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,rt=/^(?:0|[1-9]\d*)$/;function F(t){let n=[],r=[],e=t&&typeof t==="object"&&!Array.isArray(t)?t:{};for(let[o,i]of Object.entries(e)){let s=i&&typeof i==="object"?i:null;if(!s){r.push(`spotlight kind "${o}" is not an object`);continue}let{slots:l,route:a}=s,u=typeof s.noun==="string"&&s.noun.trim()?s.noun.trim():"Item";if(!nt.test(o)||o.includes("-slot-")){r.push(`spotlight kind "${o}" is not a usable name: lowercase letters, digits and single dashes, and never "-slot-"`);continue}if(typeof l!=="number"||!Number.isInteger(l)||l<=0||l>64){r.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(l)}`);continue}if(typeof a!=="string"||!a.startsWith("/")||!a.includes(":id")){r.push(`spotlight kind "${o}" needs a route starting with "/" and carrying ":id", not ${String(a)}`);continue}n.push({name:o,slots:l,route:a,noun:u})}return{kinds:n,problems:r}}function T(t,n){return t.find((r)=>r.name===n)??null}function R(t,n,r){let e=T(t,n);if(!e||!Number.isInteger(r)||r<0||r>=e.slots)return null;return`${n}-slot-${r}`}function ot(t,n){if(typeof n!=="string")return null;let r=n.lastIndexOf("-slot-");if(r<=0)return null;let e=n.slice(0,r),o=n.slice(r+6);if(!rt.test(o))return null;let i=Number(o);return R(t,e,i)===n?{kind:e,slot:i}:null}function C(t){return t.flatMap((n)=>Array.from({length:n.slots},(r,e)=>`${n.name}-slot-${e}`))}function ge(t,n){let r=t&&typeof t==="object"?t:{};if(r.enabled===!1)return[];let o=[...(Array.isArray(r.activityTypes)?r.activityTypes.filter((i)=>typeof i==="string"&&i.trim().length>0):[]).map((i)=>i.trim()),...C(F(r.kinds).kinds)];return[...new Set(o)].map((i)=>`${n}.${i}`)}function D(t,n,r){let e=typeof r.name==="string"?r.name.replace(/\s+/g," ").trim():"";if(!e)return`${T(t,n)?.noun??"Item"} #${r.id}`;return e.length>120?`${e.slice(0,119).trimEnd()}…`:e}function it(t,n,r,e,o=Date.now()){let i=T(t,r);if(!i||!Number.isInteger(e.id)||e.id<=0)return null;let s=n.filter((m)=>m.kind===r),l=D(t,r,e),a=s.find((m)=>m.itemId===e.id)??null,u=a?null:ct(s,i.slots),h=a||u!==null?null:ut(s),d=a?.slot??u??h?.slot;if(d===void 0||d===null)return null;let p={kind:r,slot:d,itemId:e.id,title:l,donatedAt:o},v=n.filter((m)=>m.kind!==r||m.slot!==d&&m.itemId!==e.id);return{entries:B(t,[...v,p]),entry:p,evicted:h,changed:!a||a.title!==l}}function st(t,n,r){let e=t.find((o)=>o.kind===n&&o.itemId===r)??null;return{entries:e?t.filter((o)=>o!==e):[...t],removed:e}}function at(t,n,r){let e=ot(t,r);if(!e)return null;let o=n.find((s)=>s.kind===e.kind&&s.slot===e.slot),i=T(t,e.kind)?.route;return o&&i?i.replace(":id",String(o.itemId)):null}function lt(t,n){if(!Array.isArray(n))return[];let r=new Map,e=new Set;for(let o of n){if(!o||typeof o!=="object")continue;let i=o,{kind:s,slot:l,itemId:a,title:u,donatedAt:h}=i;if(typeof s!=="string"||typeof l!=="number"||R(t,s,l)===null)continue;if(typeof a!=="number"||!Number.isInteger(a)||a<=0)continue;let d=`${s}-slot-${l}`,p=`${s}#${a}`;if(r.has(d)||e.has(p))continue;r.set(d,{kind:s,slot:l,itemId:a,title:typeof u==="string"&&u.trim()?u:D(t,s,{id:a}),donatedAt:typeof h==="number"&&Number.isFinite(h)&&h>0?h:0}),e.add(p)}return B(t,[...r.values()])}function B(t,n){let r=new Map(t.map((e,o)=>[e.name,o]));return[...n].sort((e,o)=>(r.get(e.kind)??0)-(r.get(o.kind)??0)||e.slot-o.slot)}function ct(t,n){let r=new Set(t.map((e)=>e.slot));for(let e=0;e<n;e++)if(!r.has(e))return e;return null}function ut(t){return t.reduce((n,r)=>!n||r.donatedAt<n.donatedAt?r:n,null)}function dt(){let t=globalThis.craft;return t&&typeof t==="object"?t.siri:void 0}var ft="stacks_spotlight_index",pt=3000;function he(t){let n=t.onProblem??((c)=>console.warn(`[spotlight] ${c}`)),r=Array.isArray(t.kinds)?{kinds:[...t.kinds],problems:[]}:F(t.kinds);for(let c of r.problems)n(c);let e=t.enabled===!1?[]:r.kinds,o=t.storageKey??ft,i=t.legacyStorageKeys??[],s=t.timeoutMs??pt,l=t.now??(()=>Date.now()),a=t.bridge??dt,u=null;function h(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function d(){if(u)return u;u=[];let c=h();if(!c)return u;try{let f=[o,...i].map((y)=>c.getItem(y)).find((y)=>y);u=f?lt(e,JSON.parse(f)):[]}catch{u=[]}return u}function p(c){u=c;let f=h();if(!f)return;try{f.setItem(o,JSON.stringify(c));for(let y of i)f.removeItem(y)}catch{}}async function v(c){if(!c)return null;let f;try{return await Promise.race([c,new Promise((y)=>{f=setTimeout(()=>y(null),s)})])}catch{return null}finally{if(f!==void 0)clearTimeout(f)}}let m=Promise.resolve();function g(c){let f=m.then(c,c);return m=f.catch(()=>{return}),f}async function b(c,f){let y=a()?.register;if(!y||e.length===0)return!1;return g(async()=>{let S=it(e,d(),c,f,l()),x=S&&R(e,c,S.entry.slot);if(!S||!x)return!1;if(!S.changed)return p(S.entries),!0;let w=await v(y(S.entry.title,x))!==null;if(w)p(S.entries);return w})}async function A(c,f){let y=a()?.remove;if(!y)return!1;return g(async()=>{let{entries:S,removed:x}=st(d(),c,f);if(!x)return!1;let w=R(e,c,x.slot),X=w?await v(y(w))!==null:!1;return p(S),X})}async function Y(c,f){let y=T(e,c)?.slots;if(!y||!a()?.register)return 0;let S=0;for(let x of[...f].slice(0,y).reverse())if(await b(c,x))S++;return S}async function W(){let c=a()?.remove;if(!c)return p([]),0;return g(async()=>{let f=0;for(let y of d()){let S=R(e,y.kind,y.slot);if(S&&await v(c(S))!==null)f++}return p([]),f})}return{kinds:e,index:b,sync:Y,remove:A,clear:W,routeFor:(c)=>at(e,d(),c),entries:()=>d(),activityTypes:(c)=>C(e).map((f)=>`${c}.${f}`),reset:()=>{u=null}}}var K=["craftShortcut","craftSiriShortcut"];function ye(t,n){let r=(e)=>{let o=e.detail,i=typeof o==="string"?o:o&&typeof o==="object"?o.action??o.type:null,s=typeof i==="string"?t.routeFor(i):null;if(s)n(s)};if(typeof globalThis.addEventListener!=="function")return()=>{};for(let e of K)globalThis.addEventListener(e,r);return()=>{for(let e of K)globalThis.removeEventListener(e,r)}}var _t=gt,Nt=ht,Ot=yt,L=St,Ht=xt,Kt=wt,$t=Tt,Ft=Et,Ct=Lt,Dt=Pt,Bt=mt;function j(t){if(typeof t==="string")return t.trim()||null;if(!t||typeof t!=="object")return null;let n=t.url;return typeof n==="string"&&n.trim()?n:null}var Ut={async getInitialURL(){if(!await G())return null;return j(await U.getInitialURL?.())},onLink(t){let n=null,r=!1,e=()=>{if(r)return;n=U.onLink?.((o,i)=>{let s=j(o);if(s)t(s,{initial:i?.initial===!0})})??null};if(E()?.craft)e();else G().then(e);return()=>{r=!0,n?.()}}},jt=bt,Gt=Mt,qt=Rt,Yt=kt,Wt=vt,Xt=At,zt=It;function E(){if(typeof window>"u")return;return window}function P(){let t=E()?.craft;if(!t||typeof t!=="object")return null;if(!("platform"in t)||t.platform!=="ios"&&t.platform!=="android")return null;let n="capabilities"in t?t.capabilities:void 0,r=n&&typeof n==="object"&&!Array.isArray(n)?Object.fromEntries(Object.entries(n).filter(([,e])=>typeof e==="boolean")):{};return{platform:t.platform,capabilities:r}}function I(){return P()!==null}function q(){if(typeof window>"u")return!1;let t=window;if(t.CraftAndroid)return!0;let n=typeof navigator>"u"?"":navigator.userAgent;return Boolean(t.webkit?.messageHandlers?.craft)&&/iPhone|iPad|iPod/.test(n)}function Jt(t=2000){if(I()||q())return Promise.resolve(!0);let n=E(),r=n;if(!n||!(r?.craft||r?.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((e)=>{let o=()=>{clearTimeout(i),n.removeEventListener("craftReady",o),e(I())},i=setTimeout(o,t);n.addEventListener("craftReady",o,{once:!0})})}function G(t=15000){let n=E();if(n?.craft)return Promise.resolve(!0);let r=n;if(!n||!(q()||r?.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((e)=>{let o=()=>{clearTimeout(i),n.removeEventListener("craftReady",o),e(Boolean(n.craft))},i=setTimeout(o,t);n.addEventListener("craftReady",o)})}function Vt(t){let n=E();if(!n)return()=>{};if(P()){let e=!1;return queueMicrotask(()=>{if(!e)t(new Event("craftReady"))}),()=>{e=!0}}let r=(e)=>{if(!P())return;n.removeEventListener("craftReady",r),t(e)};return n.addEventListener("craftReady",r),()=>n.removeEventListener("craftReady",r)}async function Qt(t){await L.impact("light");try{let n=await t();return await L.notification("success"),n}catch(n){throw await L.notification("error"),n}}var be={get nativeBridge(){return P()},biometrics:_t,camera:Nt,device:Ot,haptics:L,lifecycle:Ht,location:Kt,notifications:$t,permissions:Ft,secureStorage:Ct,share:Dt,appReview:Bt,deepLinks:Ut,keepAwake:jt,speech:Gt,network:qt,pushNotifications:Yt,health:Wt,liveActivities:Xt,watchConnectivity:zt,isNativeMobile:I,whenNative:Jt,onReady:Vt,withFeedback:Qt};export{me as MAX_SPOTLIGHT_SLOTS_PER_KIND,ce as ROUTE_GAP_S,Bt as appReview,ie as backLabelFor,_t as biometrics,Nt as camera,V as canGoBack,fe as createRouteRecorder,he as createSpotlightIndex,Q as deepLinkPath,Ut as deepLinks,Ot as device,oe as enterNavTrail,tt as fixDistance,ae as followDeepLinks,P as getNativeMobileBridge,re as goBack,L as haptics,q as hasNativeMobileHost,Wt as health,I as isNativeMobile,jt as keepAwake,Ht as lifecycle,Xt as liveActivities,Kt as location,be as mobile,se as navTrail,qt as network,j as normalizeDeepLinkURL,$t as notifications,te as observePageScroll,ee as observePullToRefresh,Vt as onMobileReady,ye as onSpotlightTap,ue as paceLabel,k as pageScrollTop,Ft as permissions,it as placeSpotlightItem,J as pullDistance,Yt as pushNotifications,lt as readSpotlightEntries,F as readSpotlightKinds,st as removeSpotlightItem,O as routeStats,Ct as secureStorage,Dt as share,Gt as speech,de as speedLabel,R as spotlightAction,C as spotlightActions,ge as spotlightActivityTypes,dt as spotlightBridge,T as spotlightKind,at as spotlightRoute,ot as spotlightSlot,D as spotlightTitle,et as usableFixes,zt as watchConnectivity,G as whenBridgeReady,Jt as whenNativeMobile,Qt as withNativeFeedback};
|
|
1
|
+
import{appReview as ht,biometrics as yt,camera as St,deepLinks as G,device as vt,haptics as bt,health as At,keepAwake as xt,lifecycle as wt,liveActivities as Rt,location as Et,network as Tt,notifications as kt,permissions as Lt,pushNotifications as Mt,secureStorage as Pt,share as _t,speech as It,watchConnectivity as Nt}from"craft-native/mobile";import{haptics as z}from"craft-native/mobile";function _(){if(typeof window>"u")return;return window}function k(t=_()){if(!t)return 0;if(typeof t.scrollY==="number")return t.scrollY;return t.document?.scrollingElement?.scrollTop??0}function ne(t,n=_()){if(!n)return()=>{};let r=!1,e=typeof requestAnimationFrame==="function"?requestAnimationFrame:(i)=>setTimeout(i,16),o=()=>{if(r)return;r=!0,e(()=>{r=!1,t(k(n))})};return t(k(n)),n.addEventListener("scroll",o,{passive:!0}),()=>n.removeEventListener("scroll",o)}function J(t,n){let r=Math.max(0,-t),e=t<=0?Math.max(0,n)*0.5:0;return Math.round(Math.max(r,e))}function re(t){let n=t.host??_();if(!n)return()=>{};let r=t.threshold??72,e=null,o=!1,i=!1,s=typeof requestAnimationFrame==="function"?requestAnimationFrame:(g)=>setTimeout(g,16),l=null,a=(g)=>{l=null,t.onPull?.(g,o)},c=(g)=>{let b=l!==null;if(l=g,b)return;s(()=>{if(l!==null)a(l)})},h=(g)=>{let b=g.touches?.[0];return b?b.clientY:null},d=(g)=>{if(i||k(n)>0)return;e=h(g),o=!1},f=(g)=>{if(e===null)return;let b=h(g);if(b===null)return;let x=J(k(n),b-e);if(!o&&x>=r)o=!0,Promise.resolve(z.impact("medium")).catch(()=>{});else if(o&&x<r*0.8)o=!1;c(x)},v=async()=>{if(e===null)return;if(e=null,!o){a(0);return}o=!1,i=!0,a(r);try{await t.onRefresh()}finally{i=!1,a(0)}},m=()=>{if(e===null)return;e=null,o=!1,a(0)};return n.addEventListener("touchstart",d,{passive:!0}),n.addEventListener("touchmove",f,{passive:!0}),n.addEventListener("touchend",v),n.addEventListener("touchcancel",m),()=>{l=null,n.removeEventListener("touchstart",d),n.removeEventListener("touchmove",f),n.removeEventListener("touchend",v),n.removeEventListener("touchcancel",m)}}function O(){if(typeof window>"u")return;return window}function Q(t=O()){let n=t?.history?.state;return n!==null&&n!==void 0}function ie(t=O()){if(!Q(t))return!1;return t.history.back(),!0}function se(t,n,r=50){let e=t[t.length-1];if(t.length>=2&&t[t.length-2].path===n)t.pop();else if(!e||e.path!==n)t.push({path:n,title:""});if(t.length>r)t.splice(0,t.length-r);return{current:t[t.length-1],previous:t[t.length-2]??null}}function ae(t,n,r=12){let e=t?.title.trim()??"";return e&&e.length<=r?e:n}function le(){if(typeof window>"u")return[];let t=window;return t.__stacksNavTrail??=[]}function Z(t,n=tt()){let r;try{r=new URL(t)}catch{return null}let e=`${r.search}${r.hash}`;if(r.protocol==="http:"||r.protocol==="https:"){if(!n||r.origin!==n)return null;return`${r.pathname||"/"}${e}`}return`${`/${[r.host,r.pathname.replace(/^\/+/,"")].filter(Boolean).join("/")}`}${e}`}function tt(){if(typeof window>"u")return;return window.location?.origin}var N="stacks-mobile-deep-link";function ue(t,n){let r=(e)=>{let o=Z(e);if(o)t(o)};return n.getInitialURL().then((e)=>{if(!e)return;try{if(sessionStorage.getItem(N)===e)return;sessionStorage.setItem(N,e)}catch{}r(e)}).catch(()=>{}),n.onLink((e,o)=>{if(o?.initial)return;r(e)})}var de=30;function et(t,n){let r=Math.PI/180,e=(n.latitude-t.latitude)*r,o=(n.longitude-t.longitude)*r,i=Math.sin(e/2)**2+Math.cos(t.latitude*r)*Math.cos(n.latitude*r)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function nt(t,n=25){let r=new Set;return t.filter((e)=>Number.isFinite(e.latitude)&&Number.isFinite(e.longitude)&&Number.isFinite(e.timestamp)&&e.accuracy>=0&&e.accuracy<=n).sort((e,o)=>e.timestamp-o.timestamp).filter((e)=>{if(r.has(e.timestamp))return!1;return r.add(e.timestamp),!0})}function H(t,n={}){let r=nt(t,n.maxAccuracyM??25),e=n.paceWindowS??30,o=[],i=0,s=0,l=null;for(let d of r){let f=o[o.length-1],v=l?(d.timestamp-l.timestamp)/1000:0;if(l=d,!f){o.push({fix:d,cumM:0});continue}if(v>30){o.push({fix:d,cumM:i});continue}let m=(d.timestamp-f.fix.timestamp)/1000,g=et(f.fix,d),b=Math.min(10,Math.max(3,f.fix.accuracy,d.accuracy));if(g<b)continue;if(i+=g,m>0&&g/m>=0.5)s+=m;o.push({fix:d,cumM:i})}let a=o[o.length-1],c=null,h=null;if(a){let d=a.fix.timestamp-e*1000,f=o.find((g)=>g.fix.timestamp>=d)??a,v=a.cumM-f.cumM,m=(a.fix.timestamp-f.fix.timestamp)/1000;if(v>=20&&m>0)h=v/m,c=m/(v/1000)}return{distanceM:i,movingS:s,paceSPerKm:c,averagePaceSPerKm:i>=50&&s>0?s/(i/1000):null,speedMps:h,accuracyM:r.length?r[r.length-1].accuracy:t.length?t[t.length-1].accuracy??null:null,fixes:r.length}}function pe(t){if(!t||!Number.isFinite(t)||t>3600)return"–";let n=Math.round(t);return`${Math.floor(n/60)}:${String(n%60).padStart(2,"0")}`}function fe(t){return t&&Number.isFinite(t)?(t*3.6).toFixed(1):"–"}var K={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function me(t){let n=t.location,r=t.intervalMs??3000,e=K,o=null,i=()=>typeof document<"u"&&document.visibilityState==="hidden";async function s(){let c=await n.readRecording();return e=H(c,t),t.onUpdate?.(e),e}function l(){a(),o=setInterval(()=>{if(!i())s().catch(()=>{})},r)}function a(){if(o)clearInterval(o);o=null}return{get stats(){return e},async start(){return await n.startRecording({enableHighAccuracy:!0,...t.locationOptions}),e=K,t.onUpdate?.(e),l(),e},async attach(){let c=await n.getRecordingState().catch(()=>null);if(!c?.active)return null;if(await s().catch(()=>{}),!c.paused)l();return c},async pause(){a(),await n.pauseRecording(),await s().catch(()=>{})},async resume(){await n.resumeRecording(),l()},async stop(){a();let h=(await n.stopRecording())?.locations??[];return e=H(h,t),t.onUpdate?.(e),h},refresh:s}}var he=150;function rt(t,n){let r=Math.PI/180,e=(n.latitude-t.latitude)*r,o=(n.longitude-t.longitude)*r,i=Math.sin(e/2)**2+Math.cos(t.latitude*r)*Math.cos(n.latitude*r)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function L(t,n){let r=[...t].sort((e,o)=>e-o);return r[Math.min(r.length-1,Math.floor(n*r.length))]}function ye(t,n){let r=(t||[]).filter((s)=>Number.isFinite(s?.latitude)&&Number.isFinite(s?.longitude)),e=r.map((s)=>Number(s.accuracy)).filter((s)=>Number.isFinite(s)&&s>=0),o=e.length?L(e,0.5):Number.POSITIVE_INFINITY,i=0;if(r.length){let s={latitude:L(r.map((l)=>l.latitude),0.5),longitude:L(r.map((l)=>l.longitude),0.5)};i=L(r.map((l)=>rt(s,l)),0.8)}if(r.length>=10&&i>150&&o<=15)return"outside";if(n<150)return"unsure";if(r.length<3||o>30||i<25)return"indoors";if(i<50&&o>10)return"indoors";return"unsure"}function Se(t){let r=String(t||"").trim().toLowerCase().replace(",",".").match(/^(\d+(?:\.\d+)?)\s*(km|k|m|mi)?$/);if(!r)return null;let e=Number(r[1]),o=r[2]||(e>100?"m":"km"),i=o==="m"?e/1000:o==="mi"?e*1.609344:e;return i>0&&i<1000?Math.round(i*1000)/1000:null}var be=64;var ot=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,it=/^(?:0|[1-9]\d*)$/;function F(t){let n=[],r=[],e=t&&typeof t==="object"&&!Array.isArray(t)?t:{};for(let[o,i]of Object.entries(e)){let s=i&&typeof i==="object"?i:null;if(!s){r.push(`spotlight kind "${o}" is not an object`);continue}let{slots:l,route:a}=s,c=typeof s.noun==="string"&&s.noun.trim()?s.noun.trim():"Item";if(!ot.test(o)||o.includes("-slot-")){r.push(`spotlight kind "${o}" is not a usable name: lowercase letters, digits and single dashes, and never "-slot-"`);continue}if(typeof l!=="number"||!Number.isInteger(l)||l<=0||l>64){r.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(l)}`);continue}if(typeof a!=="string"||!a.startsWith("/")||!a.includes(":id")){r.push(`spotlight kind "${o}" needs a route starting with "/" and carrying ":id", not ${String(a)}`);continue}n.push({name:o,slots:l,route:a,noun:c})}return{kinds:n,problems:r}}function E(t,n){return t.find((r)=>r.name===n)??null}function R(t,n,r){let e=E(t,n);if(!e||!Number.isInteger(r)||r<0||r>=e.slots)return null;return`${n}-slot-${r}`}function st(t,n){if(typeof n!=="string")return null;let r=n.lastIndexOf("-slot-");if(r<=0)return null;let e=n.slice(0,r),o=n.slice(r+6);if(!it.test(o))return null;let i=Number(o);return R(t,e,i)===n?{kind:e,slot:i}:null}function D(t){return t.flatMap((n)=>Array.from({length:n.slots},(r,e)=>`${n.name}-slot-${e}`))}function Ae(t,n){let r=t&&typeof t==="object"?t:{};if(r.enabled===!1)return[];let o=[...(Array.isArray(r.activityTypes)?r.activityTypes.filter((i)=>typeof i==="string"&&i.trim().length>0):[]).map((i)=>i.trim()),...D(F(r.kinds).kinds)];return[...new Set(o)].map((i)=>`${n}.${i}`)}function U(t,n,r){let e=typeof r.name==="string"?r.name.replace(/\s+/g," ").trim():"";if(!e)return`${E(t,n)?.noun??"Item"} #${r.id}`;return e.length>120?`${e.slice(0,119).trimEnd()}…`:e}function at(t,n,r,e,o=Date.now()){let i=E(t,r);if(!i||!Number.isInteger(e.id)||e.id<=0)return null;let s=n.filter((m)=>m.kind===r),l=U(t,r,e),a=s.find((m)=>m.itemId===e.id)??null,c=a?null:dt(s,i.slots),h=a||c!==null?null:pt(s),d=a?.slot??c??h?.slot;if(d===void 0||d===null)return null;let f={kind:r,slot:d,itemId:e.id,title:l,donatedAt:o},v=n.filter((m)=>m.kind!==r||m.slot!==d&&m.itemId!==e.id);return{entries:B(t,[...v,f]),entry:f,evicted:h,changed:!a||a.title!==l}}function lt(t,n,r){let e=t.find((o)=>o.kind===n&&o.itemId===r)??null;return{entries:e?t.filter((o)=>o!==e):[...t],removed:e}}function ut(t,n,r){let e=st(t,r);if(!e)return null;let o=n.find((s)=>s.kind===e.kind&&s.slot===e.slot),i=E(t,e.kind)?.route;return o&&i?i.replace(":id",String(o.itemId)):null}function ct(t,n){if(!Array.isArray(n))return[];let r=new Map,e=new Set;for(let o of n){if(!o||typeof o!=="object")continue;let i=o,{kind:s,slot:l,itemId:a,title:c,donatedAt:h}=i;if(typeof s!=="string"||typeof l!=="number"||R(t,s,l)===null)continue;if(typeof a!=="number"||!Number.isInteger(a)||a<=0)continue;let d=`${s}-slot-${l}`,f=`${s}#${a}`;if(r.has(d)||e.has(f))continue;r.set(d,{kind:s,slot:l,itemId:a,title:typeof c==="string"&&c.trim()?c:U(t,s,{id:a}),donatedAt:typeof h==="number"&&Number.isFinite(h)&&h>0?h:0}),e.add(f)}return B(t,[...r.values()])}function B(t,n){let r=new Map(t.map((e,o)=>[e.name,o]));return[...n].sort((e,o)=>(r.get(e.kind)??0)-(r.get(o.kind)??0)||e.slot-o.slot)}function dt(t,n){let r=new Set(t.map((e)=>e.slot));for(let e=0;e<n;e++)if(!r.has(e))return e;return null}function pt(t){return t.reduce((n,r)=>!n||r.donatedAt<n.donatedAt?r:n,null)}function ft(){let t=globalThis.craft;return t&&typeof t==="object"?t.siri:void 0}var mt="stacks_spotlight_index",gt=3000;function xe(t){let n=t.onProblem??((u)=>console.warn(`[spotlight] ${u}`)),r=Array.isArray(t.kinds)?{kinds:[...t.kinds],problems:[]}:F(t.kinds);for(let u of r.problems)n(u);let e=t.enabled===!1?[]:r.kinds,o=t.storageKey??mt,i=t.legacyStorageKeys??[],s=t.timeoutMs??gt,l=t.now??(()=>Date.now()),a=t.bridge??ft,c=null;function h(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function d(){if(c)return c;c=[];let u=h();if(!u)return c;try{let p=[o,...i].map((y)=>u.getItem(y)).find((y)=>y);c=p?ct(e,JSON.parse(p)):[]}catch{c=[]}return c}function f(u){c=u;let p=h();if(!p)return;try{p.setItem(o,JSON.stringify(u));for(let y of i)p.removeItem(y)}catch{}}async function v(u){if(!u)return null;let p;try{return await Promise.race([u,new Promise((y)=>{p=setTimeout(()=>y(null),s)})])}catch{return null}finally{if(p!==void 0)clearTimeout(p)}}let m=Promise.resolve();function g(u){let p=m.then(u,u);return m=p.catch(()=>{return}),p}async function b(u,p){let y=a()?.register;if(!y||e.length===0)return!1;return g(async()=>{let S=at(e,d(),u,p,l()),A=S&&R(e,u,S.entry.slot);if(!S||!A)return!1;if(!S.changed)return f(S.entries),!0;let w=await v(y(S.entry.title,A))!==null;if(w)f(S.entries);return w})}async function x(u,p){let y=a()?.remove;if(!y)return!1;return g(async()=>{let{entries:S,removed:A}=lt(d(),u,p);if(!A)return!1;let w=R(e,u,A.slot),X=w?await v(y(w))!==null:!1;return f(S),X})}async function W(u,p){let y=E(e,u)?.slots;if(!y||!a()?.register)return 0;let S=0;for(let A of[...p].slice(0,y).reverse())if(await b(u,A))S++;return S}async function V(){let u=a()?.remove;if(!u)return f([]),0;return g(async()=>{let p=0;for(let y of d()){let S=R(e,y.kind,y.slot);if(S&&await v(u(S))!==null)p++}return f([]),p})}return{kinds:e,index:b,sync:W,remove:x,clear:V,routeFor:(u)=>ut(e,d(),u),entries:()=>d(),activityTypes:(u)=>D(e).map((p)=>`${u}.${p}`),reset:()=>{c=null}}}var C=["craftShortcut","craftSiriShortcut"];function we(t,n){let r=(e)=>{let o=e.detail,i=typeof o==="string"?o:o&&typeof o==="object"?o.action??o.type:null,s=typeof i==="string"?t.routeFor(i):null;if(s)n(s)};if(typeof globalThis.addEventListener!=="function")return()=>{};for(let e of C)globalThis.addEventListener(e,r);return()=>{for(let e of C)globalThis.removeEventListener(e,r)}}var Ot=yt,Ht=St,Kt=vt,M=bt,Ct=wt,$t=Et,Ft=kt,Dt=Lt,Ut=Pt,Bt=_t,Gt=ht;function j(t){if(typeof t==="string")return t.trim()||null;if(!t||typeof t!=="object")return null;let n=t.url;return typeof n==="string"&&n.trim()?n:null}var jt={async getInitialURL(){if(!await Y())return null;return j(await G.getInitialURL?.())},onLink(t){let n=null,r=!1,e=()=>{if(r)return;n=G.onLink?.((o,i)=>{let s=j(o);if(s)t(s,{initial:i?.initial===!0})})??null};if(T()?.craft)e();else Y().then(e);return()=>{r=!0,n?.()}}},Yt=xt,qt=It,Wt=Tt,Vt=Mt,Xt=At,zt=Rt,Jt=Nt;function T(){if(typeof window>"u")return;return window}function P(){let t=T()?.craft;if(!t||typeof t!=="object")return null;if(!("platform"in t)||t.platform!=="ios"&&t.platform!=="android")return null;let n="capabilities"in t?t.capabilities:void 0,r=n&&typeof n==="object"&&!Array.isArray(n)?Object.fromEntries(Object.entries(n).filter(([,e])=>typeof e==="boolean")):{};return{platform:t.platform,capabilities:r}}function I(){return P()!==null}function q(){if(typeof window>"u")return!1;let t=window;if(t.CraftAndroid)return!0;let n=typeof navigator>"u"?"":navigator.userAgent;return Boolean(t.webkit?.messageHandlers?.craft)&&/iPhone|iPad|iPod/.test(n)}function Qt(t=2000){if(I()||q())return Promise.resolve(!0);let n=T(),r=n;if(!n||!(r?.craft||r?.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((e)=>{let o=()=>{clearTimeout(i),n.removeEventListener("craftReady",o),e(I())},i=setTimeout(o,t);n.addEventListener("craftReady",o,{once:!0})})}function Y(t=15000){let n=T();if(n?.craft)return Promise.resolve(!0);let r=n;if(!n||!(q()||r?.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((e)=>{let o=()=>{clearTimeout(i),n.removeEventListener("craftReady",o),e(Boolean(n.craft))},i=setTimeout(o,t);n.addEventListener("craftReady",o)})}function Zt(t){let n=T();if(!n)return()=>{};if(P()){let e=!1;return queueMicrotask(()=>{if(!e)t(new Event("craftReady"))}),()=>{e=!0}}let r=(e)=>{if(!P())return;n.removeEventListener("craftReady",r),t(e)};return n.addEventListener("craftReady",r),()=>n.removeEventListener("craftReady",r)}async function te(t){await M.impact("light");try{let n=await t();return await M.notification("success"),n}catch(n){throw await M.notification("error"),n}}var Te={get nativeBridge(){return P()},biometrics:Ot,camera:Ht,device:Kt,haptics:M,lifecycle:Ct,location:$t,notifications:Ft,permissions:Dt,secureStorage:Ut,share:Bt,appReview:Gt,deepLinks:jt,keepAwake:Yt,speech:qt,network:Wt,pushNotifications:Vt,health:Xt,liveActivities:zt,watchConnectivity:Jt,isNativeMobile:I,whenNative:Qt,onReady:Zt,withFeedback:te};export{he as INDOOR_CHECK_AFTER_S,be as MAX_SPOTLIGHT_SLOTS_PER_KIND,de as ROUTE_GAP_S,Gt as appReview,ae as backLabelFor,Ot as biometrics,Ht as camera,Q as canGoBack,me as createRouteRecorder,xe as createSpotlightIndex,Z as deepLinkPath,jt as deepLinks,Kt as device,se as enterNavTrail,et as fixDistance,ue as followDeepLinks,P as getNativeMobileBridge,ie as goBack,M as haptics,q as hasNativeMobileHost,Xt as health,ye as indoorVerdict,I as isNativeMobile,Yt as keepAwake,Ct as lifecycle,zt as liveActivities,$t as location,Te as mobile,le as navTrail,Wt as network,j as normalizeDeepLinkURL,Ft as notifications,ne as observePageScroll,re as observePullToRefresh,Zt as onMobileReady,we as onSpotlightTap,pe as paceLabel,k as pageScrollTop,Dt as permissions,at as placeSpotlightItem,J as pullDistance,Vt as pushNotifications,ct as readSpotlightEntries,F as readSpotlightKinds,lt as removeSpotlightItem,H as routeStats,Ut as secureStorage,Bt as share,qt as speech,fe as speedLabel,R as spotlightAction,D as spotlightActions,Ae as spotlightActivityTypes,ft as spotlightBridge,E as spotlightKind,ut as spotlightRoute,st as spotlightSlot,U as spotlightTitle,Se as typedDistanceKm,nt as usableFixes,Jt as watchConnectivity,Y as whenBridgeReady,Qt as whenNativeMobile,te as withNativeFeedback};
|
package/dist/indoor.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `elapsedS` is the session's own time, pauses left out. 'unsure' until it
|
|
3
|
+
* has run INDOOR_CHECK_AFTER_S; 'outside' as soon as the route has clearly
|
|
4
|
+
* gone somewhere.
|
|
5
|
+
*
|
|
6
|
+
* Measured robustly, because indoor GPS jumps: the middle is the median
|
|
7
|
+
* position and the spread is how far the nearest 80% of fixes lie from it,
|
|
8
|
+
* so one fix thrown 150 m across town neither hides a treadmill nor proves a
|
|
9
|
+
* run outside. A 400 m track (fixes within ~60 m of its middle, but sharp)
|
|
10
|
+
* is not mistaken for a treadmill: wandering only counts with a vague signal.
|
|
11
|
+
*/
|
|
12
|
+
export declare function indoorVerdict(fixes: IndoorFix[], elapsedS: number): IndoorVerdict;
|
|
13
|
+
/** A distance typed off a treadmill's display, as kilometres: "8.4", "8,4", "8400 m". */
|
|
14
|
+
export declare function typedDistanceKm(input: string): number | null;
|
|
15
|
+
/** Seconds a session runs before the verdict is trusted. */
|
|
16
|
+
export declare const INDOOR_CHECK_AFTER_S: 150;
|
|
17
|
+
/**
|
|
18
|
+
* Whether a run or ride being recorded is happening indoors: on a treadmill,
|
|
19
|
+
* or a bike on a trainer. Read the recording (`location.readRecording()`)
|
|
20
|
+
* every half minute or so while it runs and switch to a timed, GPS-free
|
|
21
|
+
* session when this says 'indoors'.
|
|
22
|
+
*
|
|
23
|
+
* Indoors the phone still reports positions, wandering around the room
|
|
24
|
+
* by tens of metres, and those wanderings added up to kilometres and a pace
|
|
25
|
+
* from nowhere ("2.82 km" and a 5:31 average over fifty minutes on a
|
|
26
|
+
* treadmill). Outside, even a walk leaves a 60-metre circle within a couple
|
|
27
|
+
* of minutes. So once a session has run long enough to tell, a route that
|
|
28
|
+
* never left that circle, a signal that never got good, or no positions at
|
|
29
|
+
* all, means the session is indoors and GPS is the wrong source for it.
|
|
30
|
+
*/
|
|
31
|
+
export declare interface IndoorFix {
|
|
32
|
+
latitude: number
|
|
33
|
+
longitude: number
|
|
34
|
+
accuracy?: number | null
|
|
35
|
+
timestamp: number
|
|
36
|
+
}
|
|
37
|
+
export type IndoorVerdict = 'indoors' | 'outside' | 'unsure';
|
package/dist/types.d.ts
CHANGED
|
@@ -352,7 +352,11 @@ export type PermissionType = | 'camera'
|
|
|
352
352
|
| 'motion'
|
|
353
353
|
| 'health';
|
|
354
354
|
export type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'restricted';
|
|
355
|
-
|
|
355
|
+
/**
|
|
356
|
+
* The kind of biometric the device offers. Craft reports `'none'` as well
|
|
357
|
+
* since craft-native 0.0.119, so the type admits it.
|
|
358
|
+
*/
|
|
359
|
+
export type BiometricType = 'faceId' | 'touchId' | 'fingerprint' | 'face' | 'iris' | 'none';
|
|
356
360
|
export type AppState = 'active' | 'inactive' | 'background';
|
|
357
361
|
export type HealthDataType = | 'steps'
|
|
358
362
|
| 'heartRate'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/mobile",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.88",
|
|
6
6
|
"description": "Craft-powered native mobile runtime for Stacks and STX applications",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"license": "MIT",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"test": "bun test"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"craft-native": ">=0.0.
|
|
35
|
+
"craft-native": ">=0.0.119"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@stacksjs/build": "0.75.
|
|
38
|
+
"@stacksjs/build": "0.75.88",
|
|
39
39
|
"better-dx": "^0.2.24"
|
|
40
40
|
}
|
|
41
41
|
}
|