@stacksjs/mobile 0.75.87 → 0.75.89
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 St,biometrics as vt,camera as bt,deepLinks as j,device as At,haptics as xt,health as wt,keepAwake as Rt,lifecycle as Et,liveActivities as Tt,location as Lt,network as kt,notifications as Mt,permissions as Pt,pushNotifications as _t,secureStorage as It,share as Nt,speech as Ot,watchConnectivity as Ht}from"craft-native/mobile";import{haptics as J}from"craft-native/mobile";function _(){if(typeof window>"u")return;return window}function L(t=_()){if(!t)return 0;if(typeof t.scrollY==="number")return t.scrollY;return t.document?.scrollingElement?.scrollTop??0}function oe(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(L(n))})};return t(L(n)),n.addEventListener("scroll",o,{passive:!0}),()=>n.removeEventListener("scroll",o)}function Q(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 ie(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),u=null,a=(g)=>{u=null,t.onPull?.(g,o)},c=(g)=>{let b=u!==null;if(u=g,b)return;s(()=>{if(u!==null)a(u)})},h=(g)=>{let b=g.touches?.[0];return b?b.clientY:null},d=(g)=>{if(i||L(n)>0)return;e=h(g),o=!1},p=(g)=>{if(e===null)return;let b=h(g);if(b===null)return;let x=Q(L(n),b-e);if(!o&&x>=r)o=!0,Promise.resolve(J.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",p,{passive:!0}),n.addEventListener("touchend",v),n.addEventListener("touchcancel",m),()=>{u=null,n.removeEventListener("touchstart",d),n.removeEventListener("touchmove",p),n.removeEventListener("touchend",v),n.removeEventListener("touchcancel",m)}}function H(){if(typeof window>"u")return;return window}var N="__stxPushed",Z="__stxScroll";function tt(t=H()){let n=t?.history?.state;if(n===null||n===void 0)return!1;if(typeof n!=="object")return!0;let r=n;if(N in r)return r[N]===!0;return!(Z in r)}function ae(t=H()){if(!tt(t))return!1;return t.history.back(),!0}function ue(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 le(t,n,r=12){let e=t?.title.trim()??"";return e&&e.length<=r?e:n}function ce(){if(typeof window>"u")return[];let t=window;return t.__stacksNavTrail??=[]}function et(t,n=nt()){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 nt(){if(typeof window>"u")return;return window.location?.origin}var O="stacks-mobile-deep-link";function de(t,n){let r=(e)=>{let o=et(e);if(o)t(o)};return n.getInitialURL().then((e)=>{if(!e)return;try{if(sessionStorage.getItem(O)===e)return;sessionStorage.setItem(O,e)}catch{}r(e)}).catch(()=>{}),n.onLink((e,o)=>{if(o?.initial)return;r(e)})}var pe=30;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 ot(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 K(t,n={}){let r=ot(t,n.maxAccuracyM??25),e=n.paceWindowS??30,o=[],i=0,s=0,u=null;for(let d of r){let p=o[o.length-1],v=u?(d.timestamp-u.timestamp)/1000:0;if(u=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=rt(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],c=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,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 me(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 ge(t){return t&&Number.isFinite(t)?(t*3.6).toFixed(1):"–"}var C={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function he(t){let n=t.location,r=t.intervalMs??3000,e=C,o=null,i=()=>typeof document<"u"&&document.visibilityState==="hidden";async function s(){let c=await n.readRecording();return e=K(c,t),t.onUpdate?.(e),e}function u(){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=C,t.onUpdate?.(e),u(),e},async attach(){let c=await n.getRecordingState().catch(()=>null);if(!c?.active)return null;if(await s().catch(()=>{}),!c.paused)u();return c},async pause(){a(),await n.pauseRecording(),await s().catch(()=>{})},async resume(){await n.resumeRecording(),u()},async stop(){a();let h=(await n.stopRecording())?.locations??[];return e=K(h,t),t.onUpdate?.(e),h},refresh:s}}var Se=150;function it(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 k(t,n){let r=[...t].sort((e,o)=>e-o);return r[Math.min(r.length-1,Math.floor(n*r.length))]}function ve(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?k(e,0.5):Number.POSITIVE_INFINITY,i=0;if(r.length){let s={latitude:k(r.map((u)=>u.latitude),0.5),longitude:k(r.map((u)=>u.longitude),0.5)};i=k(r.map((u)=>it(s,u)),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 be(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 xe=64;var st=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,at=/^(?:0|[1-9]\d*)$/;function D(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:u,route:a}=s,c=typeof s.noun==="string"&&s.noun.trim()?s.noun.trim():"Item";if(!st.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 u!=="number"||!Number.isInteger(u)||u<=0||u>64){r.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(u)}`);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:u,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 ut(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(!at.test(o))return null;let i=Number(o);return R(t,e,i)===n?{kind:e,slot:i}:null}function U(t){return t.flatMap((n)=>Array.from({length:n.slots},(r,e)=>`${n.name}-slot-${e}`))}function we(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()),...U(D(r.kinds).kinds)];return[...new Set(o)].map((i)=>`${n}.${i}`)}function B(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 lt(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),u=B(t,r,e),a=s.find((m)=>m.itemId===e.id)??null,c=a?null:pt(s,i.slots),h=a||c!==null?null:mt(s),d=a?.slot??c??h?.slot;if(d===void 0||d===null)return null;let p={kind:r,slot:d,itemId:e.id,title:u,donatedAt:o},v=n.filter((m)=>m.kind!==r||m.slot!==d&&m.itemId!==e.id);return{entries:G(t,[...v,p]),entry:p,evicted:h,changed:!a||a.title!==u}}function ct(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 dt(t,n,r){let e=ut(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 ft(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:u,itemId:a,title:c,donatedAt:h}=i;if(typeof s!=="string"||typeof u!=="number"||R(t,s,u)===null)continue;if(typeof a!=="number"||!Number.isInteger(a)||a<=0)continue;let d=`${s}-slot-${u}`,p=`${s}#${a}`;if(r.has(d)||e.has(p))continue;r.set(d,{kind:s,slot:u,itemId:a,title:typeof c==="string"&&c.trim()?c:B(t,s,{id:a}),donatedAt:typeof h==="number"&&Number.isFinite(h)&&h>0?h:0}),e.add(p)}return G(t,[...r.values()])}function G(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 pt(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 mt(t){return t.reduce((n,r)=>!n||r.donatedAt<n.donatedAt?r:n,null)}function gt(){let t=globalThis.craft;return t&&typeof t==="object"?t.siri:void 0}var ht="stacks_spotlight_index",yt=3000;function Re(t){let n=t.onProblem??((l)=>console.warn(`[spotlight] ${l}`)),r=Array.isArray(t.kinds)?{kinds:[...t.kinds],problems:[]}:D(t.kinds);for(let l of r.problems)n(l);let e=t.enabled===!1?[]:r.kinds,o=t.storageKey??ht,i=t.legacyStorageKeys??[],s=t.timeoutMs??yt,u=t.now??(()=>Date.now()),a=t.bridge??gt,c=null;function h(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function d(){if(c)return c;c=[];let l=h();if(!l)return c;try{let f=[o,...i].map((y)=>l.getItem(y)).find((y)=>y);c=f?ft(e,JSON.parse(f)):[]}catch{c=[]}return c}function p(l){c=l;let f=h();if(!f)return;try{f.setItem(o,JSON.stringify(l));for(let y of i)f.removeItem(y)}catch{}}async function v(l){if(!l)return null;let f;try{return await Promise.race([l,new Promise((y)=>{f=setTimeout(()=>y(null),s)})])}catch{return null}finally{if(f!==void 0)clearTimeout(f)}}let m=Promise.resolve();function g(l){let f=m.then(l,l);return m=f.catch(()=>{return}),f}async function b(l,f){let y=a()?.register;if(!y||e.length===0)return!1;return g(async()=>{let S=lt(e,d(),l,f,u()),A=S&&R(e,l,S.entry.slot);if(!S||!A)return!1;if(!S.changed)return p(S.entries),!0;let w=await v(y(S.entry.title,A))!==null;if(w)p(S.entries);return w})}async function x(l,f){let y=a()?.remove;if(!y)return!1;return g(async()=>{let{entries:S,removed:A}=ct(d(),l,f);if(!A)return!1;let w=R(e,l,A.slot),z=w?await v(y(w))!==null:!1;return p(S),z})}async function V(l,f){let y=E(e,l)?.slots;if(!y||!a()?.register)return 0;let S=0;for(let A of[...f].slice(0,y).reverse())if(await b(l,A))S++;return S}async function X(){let l=a()?.remove;if(!l)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(l(S))!==null)f++}return p([]),f})}return{kinds:e,index:b,sync:V,remove:x,clear:X,routeFor:(l)=>dt(e,d(),l),entries:()=>d(),activityTypes:(l)=>U(e).map((f)=>`${l}.${f}`),reset:()=>{c=null}}}var F=["craftShortcut","craftSiriShortcut"];function Ee(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 F)globalThis.addEventListener(e,r);return()=>{for(let e of F)globalThis.removeEventListener(e,r)}}var Kt=vt,Ct=bt,$t=At,M=xt,Ft=Et,Dt=Lt,Ut=Mt,Bt=Pt,Gt=It,jt=Nt,Yt=St;function Y(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 qt={async getInitialURL(){if(!await q())return null;return Y(await j.getInitialURL?.())},onLink(t){let n=null,r=!1,e=()=>{if(r)return;n=j.onLink?.((o,i)=>{let s=Y(o);if(s)t(s,{initial:i?.initial===!0})})??null};if(T()?.craft)e();else q().then(e);return()=>{r=!0,n?.()}}},Wt=Rt,Vt=Ot,Xt=kt,zt=_t,Jt=wt,Qt=Tt,Zt=Ht;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 W(){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 te(t=2000){if(I()||W())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 q(t=15000){let n=T();if(n?.craft)return Promise.resolve(!0);let r=n;if(!n||!(W()||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 ee(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 ne(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 ke={get nativeBridge(){return P()},biometrics:Kt,camera:Ct,device:$t,haptics:M,lifecycle:Ft,location:Dt,notifications:Ut,permissions:Bt,secureStorage:Gt,share:jt,appReview:Yt,deepLinks:qt,keepAwake:Wt,speech:Vt,network:Xt,pushNotifications:zt,health:Jt,liveActivities:Qt,watchConnectivity:Zt,isNativeMobile:I,whenNative:te,onReady:ee,withFeedback:ne};export{Se as INDOOR_CHECK_AFTER_S,xe as MAX_SPOTLIGHT_SLOTS_PER_KIND,pe as ROUTE_GAP_S,Yt as appReview,le as backLabelFor,Kt as biometrics,Ct as camera,tt as canGoBack,he as createRouteRecorder,Re as createSpotlightIndex,et as deepLinkPath,qt as deepLinks,$t as device,ue as enterNavTrail,rt as fixDistance,de as followDeepLinks,P as getNativeMobileBridge,ae as goBack,M as haptics,W as hasNativeMobileHost,Jt as health,ve as indoorVerdict,I as isNativeMobile,Wt as keepAwake,Ft as lifecycle,Qt as liveActivities,Dt as location,ke as mobile,ce as navTrail,Xt as network,Y as normalizeDeepLinkURL,Ut as notifications,oe as observePageScroll,ie as observePullToRefresh,ee as onMobileReady,Ee as onSpotlightTap,me as paceLabel,L as pageScrollTop,Bt as permissions,lt as placeSpotlightItem,Q as pullDistance,zt as pushNotifications,ft as readSpotlightEntries,D as readSpotlightKinds,ct as removeSpotlightItem,K as routeStats,Gt as secureStorage,jt as share,Vt as speech,ge as speedLabel,R as spotlightAction,U as spotlightActions,we as spotlightActivityTypes,gt as spotlightBridge,E as spotlightKind,dt as spotlightRoute,ut as spotlightSlot,B as spotlightTitle,be as typedDistanceKm,ot as usableFixes,Zt as watchConnectivity,q as whenBridgeReady,te as whenNativeMobile,ne 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.89",
|
|
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.89",
|
|
39
39
|
"better-dx": "^0.2.24"
|
|
40
40
|
}
|
|
41
41
|
}
|