@buoy-gg/location 7.0.44

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.
Files changed (68) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +29 -0
  3. package/lib/commonjs/components/LocationBody.js +1 -0
  4. package/lib/commonjs/components/LocationChip.js +1 -0
  5. package/lib/commonjs/components/LocationToolView.js +1 -0
  6. package/lib/commonjs/components/SchematicMap.js +1 -0
  7. package/lib/commonjs/components/format.js +1 -0
  8. package/lib/commonjs/engine/adapters/community.js +1 -0
  9. package/lib/commonjs/engine/adapters/expo.js +3 -0
  10. package/lib/commonjs/engine/adapters/expoModulesCore.js +1 -0
  11. package/lib/commonjs/engine/adapters/expoModulesCore.web.js +1 -0
  12. package/lib/commonjs/engine/adapters/index.js +1 -0
  13. package/lib/commonjs/engine/adapters/wrap.js +1 -0
  14. package/lib/commonjs/engine/fixtures.js +1 -0
  15. package/lib/commonjs/engine/geo.js +1 -0
  16. package/lib/commonjs/engine/model.js +1 -0
  17. package/lib/commonjs/engine/persistence.js +1 -0
  18. package/lib/commonjs/engine/readSavedSync.js +1 -0
  19. package/lib/commonjs/engine/readSavedSync.web.js +1 -0
  20. package/lib/commonjs/engine/store.js +1 -0
  21. package/lib/commonjs/index.js +1 -0
  22. package/lib/commonjs/package.json +1 -0
  23. package/lib/commonjs/preset.js +1 -0
  24. package/lib/commonjs/sync/locationSyncAdapter.js +1 -0
  25. package/lib/module/components/LocationBody.js +1 -0
  26. package/lib/module/components/LocationChip.js +1 -0
  27. package/lib/module/components/LocationToolView.js +1 -0
  28. package/lib/module/components/SchematicMap.js +1 -0
  29. package/lib/module/components/format.js +1 -0
  30. package/lib/module/engine/adapters/community.js +1 -0
  31. package/lib/module/engine/adapters/expo.js +3 -0
  32. package/lib/module/engine/adapters/expoModulesCore.js +1 -0
  33. package/lib/module/engine/adapters/expoModulesCore.web.js +1 -0
  34. package/lib/module/engine/adapters/index.js +1 -0
  35. package/lib/module/engine/adapters/wrap.js +1 -0
  36. package/lib/module/engine/fixtures.js +1 -0
  37. package/lib/module/engine/geo.js +1 -0
  38. package/lib/module/engine/model.js +1 -0
  39. package/lib/module/engine/persistence.js +1 -0
  40. package/lib/module/engine/readSavedSync.js +1 -0
  41. package/lib/module/engine/readSavedSync.web.js +1 -0
  42. package/lib/module/engine/store.js +1 -0
  43. package/lib/module/index.js +1 -0
  44. package/lib/module/preset.js +1 -0
  45. package/lib/module/sync/locationSyncAdapter.js +1 -0
  46. package/lib/typescript/components/LocationBody.d.ts +2 -0
  47. package/lib/typescript/components/LocationChip.d.ts +8 -0
  48. package/lib/typescript/components/LocationToolView.d.ts +8 -0
  49. package/lib/typescript/components/SchematicMap.d.ts +10 -0
  50. package/lib/typescript/components/format.d.ts +24 -0
  51. package/lib/typescript/engine/adapters/community.d.ts +11 -0
  52. package/lib/typescript/engine/adapters/expo.d.ts +9 -0
  53. package/lib/typescript/engine/adapters/expoModulesCore.d.ts +8 -0
  54. package/lib/typescript/engine/adapters/expoModulesCore.web.d.ts +4 -0
  55. package/lib/typescript/engine/adapters/index.d.ts +6 -0
  56. package/lib/typescript/engine/adapters/wrap.d.ts +25 -0
  57. package/lib/typescript/engine/fixtures.d.ts +24 -0
  58. package/lib/typescript/engine/geo.d.ts +116 -0
  59. package/lib/typescript/engine/model.d.ts +70 -0
  60. package/lib/typescript/engine/persistence.d.ts +22 -0
  61. package/lib/typescript/engine/readSavedSync.d.ts +9 -0
  62. package/lib/typescript/engine/readSavedSync.web.d.ts +4 -0
  63. package/lib/typescript/engine/store.d.ts +187 -0
  64. package/lib/typescript/index.d.ts +15 -0
  65. package/lib/typescript/preset.d.ts +45 -0
  66. package/lib/typescript/sync/locationSyncAdapter.d.ts +29 -0
  67. package/lib/web/index.mjs +3 -0
  68. package/package.json +110 -0
package/LICENSE ADDED
@@ -0,0 +1,58 @@
1
+ PROPRIETARY SOFTWARE LICENSE
2
+
3
+ Copyright (c) 2024-present Buoy. All rights reserved.
4
+
5
+ This software and its source code are proprietary and confidential.
6
+
7
+ NOTICE: This is NOT open source software. This software is licensed,
8
+ not sold, and is protected by copyright laws and international treaties.
9
+
10
+ TERMS AND CONDITIONS:
11
+
12
+ 1. LICENSE GRANT
13
+ Subject to the terms of this Agreement and payment of applicable fees,
14
+ Buoy grants you a limited, non-exclusive, non-transferable license
15
+ to use the compiled software packages in your applications.
16
+
17
+ 2. RESTRICTIONS
18
+ You may NOT:
19
+ - Copy, modify, or distribute the source code
20
+ - Reverse engineer, decompile, or disassemble the software
21
+ - Remove or alter any proprietary notices or labels
22
+ - Sublicense, rent, lease, or lend the software
23
+ - Use the software to create competing products
24
+ - Share access credentials with unauthorized parties
25
+
26
+ 3. OWNERSHIP
27
+ React Buoy retains all right, title, and interest in the software,
28
+ including all intellectual property rights. This license does not
29
+ grant you any rights to trademarks or service marks.
30
+
31
+ 4. TERMINATION
32
+ This license is effective until terminated. Your rights under this
33
+ license will terminate automatically without notice if you fail to
34
+ comply with any of its terms. Upon termination, you must cease all
35
+ use and destroy all copies of the software.
36
+
37
+ 5. DISCLAIMER OF WARRANTIES
38
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
39
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
41
+
42
+ 6. LIMITATION OF LIABILITY
43
+ IN NO EVENT SHALL BUOY BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
44
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
45
+ CONNECTION WITH THIS LICENSE OR THE USE OF THE SOFTWARE.
46
+
47
+ 7. GOVERNING LAW
48
+ This Agreement shall be governed by and construed in accordance with
49
+ the laws of the United States, without regard to its conflict of
50
+ law provisions.
51
+
52
+ For licensing inquiries and subscription information:
53
+ - Website: https://buoy.gg
54
+ - Email: AustinLovesWorking@gmail.com
55
+
56
+ Unauthorized reproduction or distribution of this software, or any
57
+ portion of it, may result in severe civil and criminal penalties,
58
+ and will be prosecuted to the maximum extent possible under the law.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ <div align="center">
2
+
3
+ # @buoy-gg/location
4
+
5
+ Tell your React Native app it is somewhere else. Pin it to any place, move it along a route with real heading and speed, cross geofences, and test no GPS signal or location services off, without changing the device's location. Works with expo-location (including geofencing and background updates), @react-native-community/geolocation and react-native-geolocation-service.
6
+
7
+ <a href="https://buoy.gg/buoy/latest/docs/tools/location"><b>Location guide</b></a> &nbsp;·&nbsp; <a href="https://buoy.gg">buoy.gg</a> &nbsp;·&nbsp; <a href="https://github.com/Buoy-gg/buoy">All tools</a>
8
+
9
+ [![npm version](https://img.shields.io/npm/v/@buoy-gg/location?style=flat-square&labelColor=10302a&color=2a9d78)](https://www.npmjs.com/package/@buoy-gg/location) [![npm downloads](https://img.shields.io/npm/dm/@buoy-gg/location?style=flat-square&labelColor=10302a&color=2a9d78&label=downloads%2Fmonth)](https://www.npmjs.com/package/@buoy-gg/location)
10
+
11
+ </div>
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @buoy-gg/core @buoy-gg/location
17
+ ```
18
+
19
+ The tool appears in `FloatingDevTools` on its own. If your app asks for the location or starts geofencing while its modules load, import the package first in your entry file so a saved location applies before they run:
20
+
21
+ ```js
22
+ import "@buoy-gg/location";
23
+ ```
24
+
25
+ Location is part of Buoy Pro. The [Location guide](https://buoy.gg/buoy/latest/docs/tools/location) covers your own places and routes, geofences, and what keeps the real location. New to Buoy? Start with the [Quick start](https://buoy.gg/buoy/latest/docs/quick-start).
26
+
27
+ ---
28
+
29
+ <sub>Part of <a href="https://buoy.gg">Buoy</a>, developer tools that live inside your app. Proprietary software. © Buoy LLC. <a href="https://buoy.gg/terms">Terms</a></sub>
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LocationBody=LocationBody;var _react=require("react");var _sharedUi=require("@buoy-gg/shared-ui");var _store=require("../engine/store");var _adapters=require("../engine/adapters");var _locationSyncAdapter=require("../sync/locationSyncAdapter");var _LocationChip=require("./LocationChip");var _LocationToolView=require("./LocationToolView");var _jsxRuntime=require("react/jsx-runtime");const actions=_locationSyncAdapter.locationSyncAdapter.actions;async function runAction(e,o){const t=actions[e];if(!t)throw new Error(`Unknown location action: ${e}`);return t(o)}const read=()=>_locationSyncAdapter.locationSyncAdapter.getSnapshot();const PERMISSION_POLL_MS=2e3;function LocationBody(){const[e,o]=(0,_react.useState)(read);(0,_react.useEffect)(()=>{(0,_adapters.installLocationAdapters)();(0,_store.bootLocation)();o(read());(0,_LocationChip.setLocationToolOpen)(true);(0,_store.refreshLocationPermission)();const t=setInterval(_store.refreshLocationPermission,PERMISSION_POLL_MS);const r=(0,_store.subscribeLocation)(()=>o(read()));return()=>{clearInterval(t);r();(0,_LocationChip.setLocationToolOpen)(false)}},[]);return(0,_jsxRuntime.jsx)(_sharedUi.FeatureGate,{featureName:"Location",children:(0,_jsxRuntime.jsx)(_LocationToolView.LocationToolView,{snapshot:e,onAction:runAction})})}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LOCATION_CHIP_ID=void 0;exports.LocationChip=LocationChip;exports.setLocationToolOpen=setLocationToolOpen;exports.watchLocationChip=watchLocationChip;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _store=require("../engine/store");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const LOCATION_CHIP_ID=exports.LOCATION_CHIP_ID="location-chip";const registration={id:LOCATION_CHIP_ID,render:t=>(0,_jsxRuntime.jsx)(LocationChip,{...t})};const isChipOpen=()=>(0,_sharedUi.getFloatingTools)().some(t=>t.id===LOCATION_CHIP_ID);let watching=false;let toolOpen=false;let resync=null;function setLocationToolOpen(t){if(toolOpen===t)return;toolOpen=t;resync?.()}function watchLocationChip(){if(watching)return;watching=true;let t=false;const o=()=>{const e=(0,_store.getLocationSnapshot)().active&&(0,_store.getLocationSettings)().showChip&&!toolOpen;if(e&&!t)(0,_sharedUi.openFloatingTool)(registration);else if(!e&&isChipOpen())(0,_sharedUi.dismissFloatingTool)(LOCATION_CHIP_ID);t=e};resync=o;(0,_store.subscribeLocation)(o);o()}function LocationChip({id:t,revealToken:o}){const e=(0,_react.useSyncExternalStore)(_store.subscribeLocation,_store.getLocationSnapshot,_store.getLocationSnapshot);const r=(0,_format.titleLine)(e);const i=e.override.mode==="route"&&e.progress;const n=e.override.playing;const s=!!i&&i.finished;return(0,_jsxRuntime.jsx)(_sharedUi.FloatingTool,{id:t,revealToken:o,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the location chip. ${r}`,handleAdornment:(0,_jsxRuntime.jsx)(_sharedUi.LocationToolIcon,{size:12}),children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(_sharedUi.LocationToolIcon,{size:18}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.text,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.title,numberOfLines:1,testID:"location-chip-title",children:r}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detail,numberOfLines:1,testID:"location-chip-detail",children:(0,_format.chipLine)(e)})]}),i?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"location-chip-playpause",accessibilityRole:"button",accessibilityLabel:n?"Pause the route":s?"Play the route again":"Resume the route",onPress:()=>n?(0,_store.pauseRoute)():(0,_store.resumeRoute)(),style:styles.pill,hitSlop:{top:8,bottom:8,left:4,right:4},children:n?(0,_jsxRuntime.jsx)(_sharedUi.Pause,{size:14,color:_sharedUi.night.color.accent}):s?(0,_jsxRuntime.jsx)(_sharedUi.RefreshCw,{size:14,color:_sharedUi.night.color.accent}):(0,_jsxRuntime.jsx)(_sharedUi.Play,{size:14,color:_sharedUi.night.color.accent})}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.separator}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"location-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to the real location",onPress:()=>(0,_store.resetLocation)(),style:styles.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:(0,_jsxRuntime.jsx)(_sharedUi.X,{size:16,color:_sharedUi.night.color.textSecondary})})]})})}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:230,maxWidth:340},text:{flexShrink:1,minWidth:120},title:{color:_sharedUi.night.color.text,fontSize:14,fontWeight:"600"},detail:{color:_sharedUi.night.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},pill:{width:30,height:30,borderRadius:15,alignItems:"center",justifyContent:"center",backgroundColor:_sharedUi.night.color.accentFill},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:_reactNative.StyleSheet.hairlineWidth,height:20,backgroundColor:_sharedUi.night.color.separator}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LocationToolView=LocationToolView;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _geo=require("../engine/geo");var _model=require("../engine/model");var _format=require("./format");var _SchematicMap=require("./SchematicMap");var _jsxRuntime=require("react/jsx-runtime");const PAGE_TITLES={places:"Other Location",routes:"Route",speed:"Speed",accuracy:"Accuracy & Drift",activity:"Activity",options:"Options"};const PIN="#F87171";const SPEEDS=[{key:"1.4",label:"Walking"},{key:"3.3",label:"Running"},{key:"5.5",label:"Cycling"},{key:"13.4",label:"City Traffic"},{key:"30",label:"Highway"},{key:"250",label:"Airplane"}];const CONDITION_TABS=[{key:"good",label:"Good"},{key:"weak",label:"Weak"},{key:"no-signal",label:"No Signal"},{key:"off",label:"Off"}];const CONDITION_NOTES={good:"Precise fixes, like outdoors with a clear sky.",weak:"Fixes are \xB165 m and wander by up to 50 m, like indoors or between tall buildings.","no-signal":"Watches get no updates and location requests fail.",off:"The app is told location services are turned off.",custom:"Custom accuracy and drift."};const ACCURACY=[{key:"5",label:"5 m"},{key:"20",label:"20 m"},{key:"65",label:"65 m"},{key:"1000",label:"1 km"}];const DRIFT=[{key:"0",label:"Off"},{key:"10",label:"10 m"},{key:"50",label:"50 m"},{key:"200",label:"200 m"}];const INLINE_BUILT_INS=4;function useTicker(e){const[i,t]=(0,_react.useState)(()=>(0,_sharedUi.realNow)());(0,_react.useEffect)(()=>{if(!e)return void 0;const n=setInterval(()=>t((0,_sharedUi.realNow)()),1e3);return()=>clearInterval(n)},[e]);return i}function LocationToolView({snapshot:e,onAction:i}){const t=(0,_sharedUi.useSafeAreaInsets)({minBottom:16});const[n,o]=(0,_react.useState)(null);const[s,a]=(0,_react.useState)("main");const l=()=>a("main");const r=(0,_sharedUi.useToolScreenHeader)(s==="main"?null:{title:PAGE_TITLES[s],subtitle:"",onBack:l,searchable:false},[s]);const c=(g,x)=>{o(null);i(g,x).catch(f=>{o(f instanceof Error?f.message:String(f))})};if(!e){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.waiting,testID:"location-waiting",children:(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{centered:true,children:"Waiting for the app\u2026"})})}const u=n?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{tone:"danger",centered:true,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{testID:"location-error",children:n})}):null;const h=(g,x)=>{c(g,x);l()};let d;switch(s){case"places":d=(0,_jsxRuntime.jsx)(PlacesPage,{snapshot:e,pick:h});break;case"routes":d=(0,_jsxRuntime.jsx)(RoutesPage,{snapshot:e,pick:h});break;case"speed":d=(0,_jsxRuntime.jsx)(SpeedPage,{snapshot:e,pick:h});break;case"accuracy":d=(0,_jsxRuntime.jsx)(AccuracyPage,{snapshot:e,run:c});break;case"activity":d=(0,_jsxRuntime.jsx)(ActivityPage,{snapshot:e,run:c});break;case"options":d=(0,_jsxRuntime.jsx)(OptionsPage,{snapshot:e,run:c});break;default:d=(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(StatusCard,{snapshot:e,run:c}),u,(0,_jsxRuntime.jsx)(MapSection,{snapshot:e,run:c}),(0,_jsxRuntime.jsx)(LocationSection,{snapshot:e,run:c,open:a}),(0,_jsxRuntime.jsx)(MovementSection,{snapshot:e,open:a}),(0,_jsxRuntime.jsx)(GeofenceSection,{snapshot:e,run:c}),(0,_jsxRuntime.jsx)(ConditionsSection,{snapshot:e,run:c,open:a}),(0,_jsxRuntime.jsx)(MoreSection,{snapshot:e,open:a})]})}return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:[styles.content,{paddingBottom:t.bottom}],testID:"location-scroll",keyboardShouldPersistTaps:"handled",children:[s!=="main"&&!r?(0,_jsxRuntime.jsx)(BackRow,{title:PAGE_TITLES[s],onBack:l}):null,s!=="main"?u:null,d]},s)}function StatusCard({snapshot:e,run:i}){const t=e.override;const n=t.mode==="route"?t.route:null;const o=e.progress;useTicker(!!n&&t.playing);const s=(0,_format.titleTone)(e);const a=e.current.fix;const l=o&&o.length>0?Math.min(1,o.along/o.length):0;const[r,c]=(0,_react.useState)(false);return(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.status,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.statusTitle,s==="simulated"?styles.titleSimulated:s==="broken"?styles.titleBroken:null],testID:"location-hero-title",numberOfLines:1,adjustsFontSizeToFit:true,children:(0,_format.titleLine)(e)}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.statusLine,testID:"location-hero-status",children:(0,_format.stateLine)(e)}),a&&e.simulating?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"location-copy-coordinates",accessibilityRole:"button",accessibilityLabel:"Copy coordinates",activeOpacity:.6,onPress:()=>{void(0,_sharedUi.copyToClipboard)(`${a.latitude}, ${a.longitude}`).then(u=>{if(!u)return;c(true);setTimeout(()=>c(false),1500)})},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.coordinates,children:r?"Copied":(0,_format.formatCoordinate)(a,5)})}):null,n&&o?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.progressTrack,testID:"location-route-progress",children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.progressFill,{width:`${l*100}%`}]}),(n.gaps??[]).map(([u,h],d)=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.progressGap,{left:`${u/o.length*100}%`,width:`${(h-u)/o.length*100}%`}]},d))]}):null,e.active?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.statusButtons,children:[n&&o?(0,_jsxRuntime.jsx)(RoundButton,{testID:t.playing?"location-route-pause":"location-route-resume",label:t.playing?"Pause":o.finished?"Play again":"Resume",onPress:()=>i(t.playing?"pauseRoute":"resumeRoute"),children:t.playing?(0,_jsxRuntime.jsx)(_sharedUi.Pause,{size:18,color:_sharedUi.night.color.onAccent}):o.finished?(0,_jsxRuntime.jsx)(_sharedUi.RefreshCw,{size:18,color:_sharedUi.night.color.onAccent}):(0,_jsxRuntime.jsx)(_sharedUi.Play,{size:18,color:_sharedUi.night.color.onAccent})}):null,(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.flex,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Use Real Location",size:"md",testID:"location-reset",onPress:()=>i("reset")})})]}):null]}),e.permission?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.permission,testID:"location-permission",children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowBetween,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:"Permission"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.rowValue,e.permission.status!=="granted"?styles.valueWarning:null],testID:"location-permission-value",children:(0,_format.permissionLine)(e.permission)})]}),e.permission.status!=="granted"?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detail,children:"The app's location requests fail until it's allowed. Change it in Settings or the Permissions tool."}):null]}):null]})}function RoundButton({children:e,label:i,onPress:t,testID:n}){return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:n,accessibilityRole:"button",accessibilityLabel:i,activeOpacity:.7,onPress:t,style:styles.round,children:e})}function MapSection({snapshot:e,run:i}){const t=!!e.position||e.places.length>0||e.tasks.some(n=>n.regions.length>0);if(!t)return null;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_SchematicMap.SchematicMap,{snapshot:e,onPinPlace:n=>i("setLocation",{latitude:n.latitude,longitude:n.longitude,label:n.label}),onCrossRegion:(n,o)=>i(o.state==="inside"?"exitRegion":"enterRegion",{identifier:o.identifier,task:n.name})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Map views in the app still show the device's own blue dot. Move the simulator's location for those."})]})}function LocationSection({snapshot:e,run:i,open:t}){const n=e.places.length>0;const o=n?e.places:e.builtInPlaces.slice(0,INLINE_BUILT_INS);const s=e.override.mode==="fixed"?e.override.place:null;const a=e.position;const l=!!s&&!o.some(r=>samePlace(r,s));return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Location"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[o.map((r,c)=>(0,_jsxRuntime.jsx)(ListRow,{title:r.label??(0,_format.formatCoordinate)(r,4),value:a&&!(s&&samePlace(r,s))?distanceFrom(a,r):void 0,checked:!!s&&samePlace(r,s),testID:`location-place-${slug(r.label??String(c))}`,onPress:()=>i("setLocation",{latitude:r.latitude,longitude:r.longitude,label:r.label})},`${r.label??c}`)),(0,_jsxRuntime.jsx)(ListRow,{title:"Other Location\u2026",value:l?s.label||(0,_format.formatCoordinate)(s,3):void 0,chevron:true,testID:"location-other",onPress:()=>t("places")},"other")]})})]})}function distanceFrom(e,i){const t=(0,_geo.distanceMeters)(e,i);return t<30?"Here":(0,_format.formatDistance)(t)}function samePlace(e,i){if(e.label&&i.label)return e.label===i.label;return(0,_geo.distanceMeters)(e,i)<1}function PlacesPage({snapshot:e,pick:i}){const[t,n]=(0,_react.useState)("");const o=(0,_geo.parseCoordinate)(t);const s=e.override.mode==="fixed"?e.override.place:null;const a=()=>{if(!o)return;i("setLocation",{query:t});n("")};return(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Coordinates"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.editor,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.inputRow,children:[(0,_jsxRuntime.jsx)(_reactNative.TextInput,{value:t,onChangeText:n,placeholder:"Coordinates or a Maps link",placeholderTextColor:_sharedUi.night.color.placeholder,autoCapitalize:"none",autoCorrect:false,style:styles.input,testID:"location-coordinate-input",accessibilityLabel:"Coordinates or a Maps link",returnKeyType:"done",onSubmitEditing:a}),(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Pin",size:"md",variant:"primary",disabled:!o,testID:"location-coordinate-set",onPress:a})]}),t.length>0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:o?styles.detail:styles.warning,testID:"location-coordinate-preview",children:o?readableCoordinate(o):"Type a latitude and longitude, like 40.7580, -73.9855, or paste a Google or Apple Maps link."}):null]})})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Places"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:e.builtInPlaces.map((l,r)=>(0,_jsxRuntime.jsx)(ListRow,{title:l.label??(0,_format.formatCoordinate)(l,4),detail:l.label==="Null Island"?"0, 0: catches code that treats 0 as no location":void 0,checked:!!s&&samePlace(l,s),testID:`location-place-${slug(l.label??String(r))}`,onPress:()=>i("setLocation",{latitude:l.latitude,longitude:l.longitude,label:l.label})},`${l.label??r}`))})}),e.places.length===0?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Add your own places, such as your stores, with registerLocationPlaces()."}):null]})]})}function readableCoordinate(e){const i=`${Math.abs(e.latitude).toFixed(4)}\xB0 ${e.latitude>=0?"N":"S"}`;const t=`${Math.abs(e.longitude).toFixed(4)}\xB0 ${e.longitude>=0?"E":"W"}`;return`${i}, ${t}`}function MovementSection({snapshot:e,open:i}){const t=e.override.mode==="route"?e.override.route:null;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Movement"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(ListRow,{title:"Route",value:t?.name??"None",chevron:true,testID:"location-route",onPress:()=>i("routes")},"route"),t?(0,_jsxRuntime.jsx)(ListRow,{title:"Speed",value:speedName(t.speed),chevron:true,testID:"location-speed",onPress:()=>i("speed")},"speed"):null]})})]})}function speedName(e){const i=SPEEDS.find(t=>Math.abs(Number(t.key)-e)<.05);return i?i.label:(0,_format.formatSpeed)(e)}function RoutesPage({snapshot:e,pick:i}){const t=e.override.mode==="route"?e.override.route:null;const n=t?.id;return(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[t?(0,_jsxRuntime.jsx)(_reactNative.View,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:(0,_jsxRuntime.jsx)(ListRow,{title:"Stop Here",detail:"End the route and stay where it got to",testID:"location-route-stop",onPress:()=>i("stopRoute")},"stop")})})}):null,e.routes.length>0?(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"This App"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:e.routes.map((o,s)=>(0,_jsxRuntime.jsx)(ListRow,{title:o.name??o.id??`Route ${s+1}`,detail:`${(0,_format.formatDistance)((0,_geo.routeLength)(o.points))} at ${(0,_format.formatSpeed)(o.speed)}${o.loop?", on repeat":""}`,checked:!!n&&n===o.id,testID:`location-route-${slug(o.id??o.name??String(s))}`,onPress:()=>i("startRoute",{route:o.id??o.name})},o.id??`${o.name}-${s}`))})})]}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"From Here"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:e.presets.map(o=>(0,_jsxRuntime.jsx)(ListRow,{title:o.name,detail:presetDetail(o.id)??o.description,checked:n===`preset:${o.id}`,testID:`location-preset-${o.id}`,onPress:()=>i("startRoute",{route:o.id})},o.id))})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"These start where the app is now."})]})]})}function presetDetail(e){const i=_format.formatDistance;switch(e){case"walk":return`${i(1e3)} north at walking pace`;case"run":return`${i(3e3)} north, then east, at running pace`;case"drive":return`${i(4e3)} of city streets with turns`;case"highway":return`${i(3e4)} north at highway speed`;case"tunnel":return`${i(3e3)} drive with no signal for ${i(600)} in the middle`;case"loop":return`A ${i(400)} block, walked on repeat`;default:return null}}function SpeedPage({snapshot:e,pick:i}){const t=e.override.route?.speed??0;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:SPEEDS.map(n=>(0,_jsxRuntime.jsx)(ListRow,{title:n.label,value:(0,_format.formatSpeed)(Number(n.key)),checked:Math.abs(Number(n.key)-t)<.05,testID:`location-speed-${n.key}`,onPress:()=>i("setSpeed",{speed:Number(n.key)})},n.key))})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Heading and speed follow the route."})]})}const RESULT_MS=1e4;function GeofenceSection({snapshot:e,run:i}){const t=e.tasks.filter(r=>r.kind==="geofencing"&&r.regions.length>0);const[n,o]=(0,_react.useState)(null);const s=useTicker(!!n);if(t.length===0)return null;const a=t.length>1;const l=t.map(r=>r.name).join(", ");return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Geofences"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightRows,{children:t.flatMap(r=>r.regions.map(c=>{const u=`${r.name}:${c.identifier}`;const h=c.state==="inside";const d=n?.key===u&&s-n.at<RESULT_MS?n:null;const g=[where(c)];if(a)g.push(r.name);return(0,_jsxRuntime.jsx)(ListRow,{title:c.label??c.identifier,detail:g.join(" \xB7 "),note:d?taskResult(e,r,d.at):void 0,action:h?"Leave":"Enter",testID:`location-region-${slug(c.identifier)}`,onPress:()=>{o({key:u,at:(0,_sharedUi.realNow)()});i(h?"exitRegion":"enterRegion",{identifier:c.identifier,task:r.name})}},u)}))})}),(0,_jsxRuntime.jsxs)(_sharedUi.NightFootnote,{children:["Tap a region to cross its edge. ",a?"The app's tasks":`The app's ${l} task`," runs as it would from the OS."]})]})}function where(e){if(e.state==="inside")return"Inside";if(e.distance==null)return`${(0,_format.formatDistance)(e.radius)} radius`;return`${(0,_format.formatDistance)(Math.max(0,e.distance-e.radius))} away`}function taskResult(e,i,t){const n=e.log.filter(l=>l.at>=t-50&&(l.detail??"").startsWith(i.name));const o=n.find(l=>l.kind==="error");if(o)return{text:`Task failed: ${o.detail?.slice(i.name.length+3)??""}`,tone:"bad"};const s=n.find(l=>l.kind==="task");if(s)return{text:"Task ran",tone:"ok"};const a=n.find(l=>l.kind==="enter"||l.kind==="exit");if(!a)return{text:"Already on this side",tone:"wait"};return{text:"Running the app's task\u2026",tone:"wait"}}function ConditionsSection({snapshot:e,run:i,open:t}){const n=e.override;const o=(0,_model.currentConditions)(n);const s=e.simulating?CONDITION_TABS:CONDITION_TABS.filter(a=>a.key!=="weak");return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Conditions"}),(0,_jsxRuntime.jsxs)(_sharedUi.NightCard,{children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.segmentWrap,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:s,activeKey:o??"",size:"sm",testIDPrefix:"location-conditions",onChange:a=>i("setConditions",{conditions:a})})}),e.simulating&&n.services&&n.signal?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.separatorTop,children:(0,_jsxRuntime.jsx)(ListRow,{title:"Accuracy & Drift",value:`${(0,_format.formatAccuracy)(n.accuracy)}${n.jitter>0?` \xB7 drifts ${(0,_format.formatDistance)(n.jitter)}`:""}`,chevron:true,testID:"location-accuracy",onPress:()=>t("accuracy")})}):null]}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:CONDITION_NOTES[o??"custom"]})]})}function AccuracyPage({snapshot:e,run:i}){const t=e.override;return(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Accuracy"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.segmentWrap,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:ACCURACY,activeKey:nearestKey(ACCURACY,t.accuracy)??"",size:"sm",testIDPrefix:"location-accuracy",onChange:n=>i("tune",{accuracy:Number(n)})})})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"The accuracy radius the app is given with each fix."})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Drift"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.segmentWrap,children:(0,_jsxRuntime.jsx)(_sharedUi.NightSegmented,{tabs:DRIFT,activeKey:nearestKey(DRIFT,t.jitter)??"0",size:"sm",testIDPrefix:"location-drift",onChange:n=>i("tune",{jitter:Number(n)})})})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"Moves each fix by up to this much at random, the way a real fix wanders."})]})]})}function MoreSection({snapshot:e,open:i}){const t=e.log.length;return(0,_jsxRuntime.jsx)(_reactNative.View,{children:(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(ListRow,{title:"Activity",value:t===0?"None":`${t} ${t===1?"event":"events"}`,chevron:true,testID:"location-activity",onPress:()=>i("activity")},"activity"),(0,_jsxRuntime.jsx)(ListRow,{title:"Options",chevron:true,testID:"location-options",onPress:()=>i("options")},"options")]})})})}function ActivityPage({snapshot:e,run:i}){const t=useTicker(true);const n=e.log.slice().reverse();const o=e.watches.filter(r=>r.kind==="position").length;const s=e.tasks.filter(r=>r.kind==="locationUpdates").length;const a=e.tasks.filter(r=>r.kind==="geofencing").reduce((r,c)=>r+c.regions.length,0);const l=[o?`${o} location ${o===1?"watch":"watches"}`:null,a?`${a} ${a===1?"geofence":"geofences"}`:null,s?"background updates":null].filter(Boolean);return(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"The App Is Using"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.editor,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,testID:"location-activity-summary",children:l.length?l.join(", "):"Nothing right now"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detail,children:e.libraries.length?`Through ${e.libraries.join(" and ")}.`:"No supported location library was found in this app."})]})})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:"Recent"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[n.length===0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.editor,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detail,children:"Location requests, watches and geofence crossings show up here."})},"empty"):n.map(r=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.logRow,testID:"location-log-entry",children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.logDot,dotStyle(r.kind)]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.flex,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.logText,children:r.text}),r.detail?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.logDetail,numberOfLines:2,children:r.detail}):null]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.logWhen,children:(0,_format.formatWhen)(r.at,t)})]},r.id)),n.length>0?(0,_jsxRuntime.jsx)(ListRow,{title:"Clear",tint:true,testID:"location-clear-log",onPress:()=>i("clearLog")},"clear"):null]})})]})]})}function dotStyle(e){if(e==="enter")return styles.dotEnter;if(e==="exit")return styles.dotExit;if(e==="error")return styles.dotError;if(e==="task")return styles.dotTask;return null}function OptionsPage({snapshot:e,run:i}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[(0,_jsxRuntime.jsx)(SwitchRow,{title:"Keep Across Reloads",value:e.settings.persist,testID:"location-setting-persist",onValueChange:t=>i("updateSettings",{persist:t})},"persist"),(0,_jsxRuntime.jsx)(SwitchRow,{title:"Show Floating Status",value:e.settings.showChip,testID:"location-setting-showChip",onValueChange:t=>i("updateSettings",{showChip:t})},"chip")]})}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:"The floating status stays on screen while the app is somewhere else, so a simulated location is never left on by accident."})]})}function BackRow({title:e,onBack:i}){return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:"location-back",accessibilityRole:"button",accessibilityLabel:"Back",activeOpacity:.6,onPress:i,style:styles.backRow,children:[(0,_jsxRuntime.jsx)(_sharedUi.ChevronLeft,{size:18,color:_sharedUi.night.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.backLabel,children:"Location"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.backTitle,numberOfLines:1,children:e})]})}function ListRow({title:e,detail:i,note:t,value:n,action:o,checked:s,chevron:a,tint:l,onPress:r,testID:c}){return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:c,accessibilityRole:"button",accessibilityLabel:o?`${o} ${e}`:e,accessibilityState:s?{selected:true}:void 0,activeOpacity:.6,onPress:r,style:styles.row,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.rowTitle,l?styles.titleTint:null],numberOfLines:1,children:e}),i?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detail,children:i}):null,t?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.note,t.tone==="ok"?styles.noteOk:t.tone==="bad"?styles.noteBad:null],testID:`${c}-result`,children:t.text}):null]}),n?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowValue,numberOfLines:1,children:n}):null,o?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowAction,children:o}):null,s?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:18,color:_sharedUi.night.color.accent}):null,a?(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary}):null]})}function SwitchRow({title:e,value:i,onValueChange:t,testID:n}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.rowText,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,children:e})}),(0,_jsxRuntime.jsx)(_sharedUi.NightSwitch,{value:i,testID:n,accessibilityLabel:e,onValueChange:t})]})}function nearestKey(e,i){let t=null;let n=Infinity;for(const o of e){const s=Math.abs(Number(o.key)-i);if(s<n){t=o.key;n=s}}return t!==null&&n<=Math.max(.05,Number(t)*.05)?t:null}function slug(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}const styles=_reactNative.StyleSheet.create({fill:{flex:1},flex:{flex:1},content:{paddingHorizontal:_sharedUi.night.gutter,paddingTop:8,gap:_sharedUi.night.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},status:{padding:_sharedUi.night.cardPad+2,gap:6},statusTitle:{color:_sharedUi.night.color.text,fontSize:28,fontWeight:"600"},titleSimulated:{color:_sharedUi.night.color.accent},titleBroken:{color:PIN},statusLine:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row,fontVariant:["tabular-nums"]},coordinates:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,fontFamily:_sharedUi.monoFont},statusButtons:{flexDirection:"row",alignItems:"center",gap:10,marginTop:10},round:{width:44,height:44,borderRadius:22,alignItems:"center",justifyContent:"center",backgroundColor:_sharedUi.night.color.accent},progressTrack:{height:6,borderRadius:3,marginTop:8,backgroundColor:_sharedUi.night.color.fillSecondary,overflow:"hidden"},progressFill:{position:"absolute",left:0,top:0,bottom:0,backgroundColor:_sharedUi.night.color.accent},progressGap:{position:"absolute",top:0,bottom:0,backgroundColor:"rgba(255, 255, 255, 0.28)"},permission:{borderTopWidth:_reactNative.StyleSheet.hairlineWidth,borderTopColor:_sharedUi.night.color.separator,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:12,gap:4},rowBetween:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12},valueWarning:{color:_sharedUi.night.color.warning},row:{flexDirection:"row",alignItems:"center",gap:10,minHeight:48,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowText:{flex:1,gap:2},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},titleTint:{color:_sharedUi.night.color.accent},rowValue:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row,maxWidth:"50%"},rowAction:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.row,fontWeight:"500"},detail:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption},note:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,marginTop:2},noteOk:{color:_sharedUi.night.color.accent},noteBad:{color:_sharedUi.night.color.danger},warning:{color:_sharedUi.night.color.warning,fontSize:_sharedUi.night.font.caption},separatorTop:{borderTopWidth:_reactNative.StyleSheet.hairlineWidth,borderTopColor:_sharedUi.night.color.separator},segmentWrap:{flexDirection:"row",padding:10},editor:{paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:14,gap:8},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.body,backgroundColor:_sharedUi.night.color.bg,borderRadius:_sharedUi.night.radius.input,borderWidth:1,borderColor:_sharedUi.night.color.border,paddingHorizontal:12,paddingVertical:9},backRow:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4},backLabel:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.row},backTitle:{flex:1,color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row,fontWeight:"600",textAlign:"center",marginRight:70},logRow:{flexDirection:"row",alignItems:"flex-start",gap:10,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},logDot:{width:8,height:8,borderRadius:4,marginTop:6,backgroundColor:_sharedUi.night.color.textTertiary},dotEnter:{backgroundColor:_sharedUi.night.color.accent},dotExit:{backgroundColor:_sharedUi.night.color.warning},dotError:{backgroundColor:_sharedUi.night.color.danger},dotTask:{backgroundColor:_sharedUi.night.color.info},logText:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.body},logDetail:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:2},logWhen:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,fontVariant:["tabular-nums"],marginTop:1}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SchematicMap=SchematicMap;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _geo=require("../engine/geo");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const PIN="#F87171";const ASPECT=1.8;const NEARBY_METERS=6e4;const MIN_SPAN_METERS=400;function SchematicMap({snapshot:t,onPinPlace:a,onCrossRegion:l}){const i=t.position;const r=t.override.mode==="route"?t.override.route:null;const n=i??t.places[0]??firstRegion(t.tasks)??null;if(!n)return null;const s=e=>!i||(0,_geo.distanceMeters)(i,e)<=NEARBY_METERS;const y=t.places.filter(s);const M=t.tasks.filter(e=>e.kind==="geofencing").flatMap(e=>e.regions.filter(s).map(o=>({task:e,region:o})));const x=t.places.length-y.length;const _=Math.cos(n.latitude*Math.PI/180);const c=e=>({x:(e.longitude-n.longitude)*111320*_,y:(e.latitude-n.latitude)*110540});const d=[];if(i)d.push({...c(i),r:60});for(const e of r?.points??[])d.push({...c(e),r:0});for(const e of y)d.push({...c(e),r:60});for(const e of M)d.push({...c(e.region),r:e.region.radius});let p=Infinity;let f=-Infinity;let b=Infinity;let m=-Infinity;for(const e of d){p=Math.min(p,e.x-e.r);f=Math.max(f,e.x+e.r);b=Math.min(b,e.y-e.r);m=Math.max(m,e.y+e.r)}const $=(p+f)/2;const I=(b+m)/2;const S=Math.max(MIN_SPAN_METERS,(m-b)*1.35,(f-p)*1.2/ASPECT);const w=S*ASPECT;const u=e=>{const o=c(e);return{x:.5+(o.x-$)/w,y:.5-(o.y-I)/S}};const j=scaleBar(w);const v=t.override.mode==="fixed"?t.override.place.label:void 0;return(0,_jsxRuntime.jsx)(_reactNative.View,{children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.map,testID:"location-map",accessibilityLabel:"Map of places, geofences and the simulated position",children:[GRID.map(e=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.gridV,{left:pct(e)}]},`v${e}`)),GRID.map(e=>(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.gridH,{top:pct(e)}]},`h${e}`)),M.map(({task:e,region:o})=>{const h=u(o);const g=2*o.radius/w;const C=g*ASPECT;const R=o.state==="inside";return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:`location-map-region-${slug(o.identifier)}`,accessibilityRole:"button",accessibilityLabel:`${R?"Leave":"Enter"} ${o.label??o.identifier}`,activeOpacity:.6,onPress:()=>l(e,o),style:[styles.fence,R?styles.fenceInside:null,{left:pct(h.x-g/2),top:pct(h.y-C/2),width:pct(g),height:pct(C)}]},`${e.name}:${o.identifier}`)}),r?segments(r.points.map(u)).map((e,o)=>(0,_jsxRuntime.jsx)(_reactNative.View,{pointerEvents:"none",style:[styles.segment,{left:pct(e.midX-e.length/2),top:pct(e.midY),width:pct(e.length),transform:[{rotate:`${e.angle}rad`}]}]},`seg${o}`)):null,y.map((e,o)=>{const h=u(e);const g=!!v&&v===e.label;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`location-map-place-${slug(e.label??String(o))}`,accessibilityRole:"button",accessibilityLabel:`Pin ${e.label??"this place"}`,activeOpacity:.6,onPress:()=>a(e),style:[styles.placeHit,{left:pct(h.x),top:pct(h.y)}],children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.placeDot,g?styles.placeDotSelected:null]}),e.label?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.placeLabel,numberOfLines:1,children:e.label}):null]},`${e.label??o}`)}),i?(0,_jsxRuntime.jsxs)(_reactNative.View,{pointerEvents:"none",style:[styles.pinWrap,{left:pct(u(i).x),top:pct(u(i).y)}],children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.pinHalo}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.pin,t.current.reason==="gap"?styles.pinHollow:null]})]}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.scale,pointerEvents:"none",children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.scaleBar,{width:pct(j.fraction)}]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.scaleLabel,children:j.label})]}),x>0?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.offMap,pointerEvents:"none",children:`${x} more ${x===1?"place":"places"} off the map`}):null]})})}const GRID=[.2,.4,.6,.8];function pct(t){return`${t*100}%`}function firstRegion(t){for(const a of t)if(a.regions[0])return a.regions[0];return null}function segments(t){const a=[];for(let l=1;l<t.length;l++){const i=t[l-1];const r=t[l];const n=r.x-i.x;const s=(r.y-i.y)/ASPECT;a.push({midX:(i.x+r.x)/2,midY:(i.y+r.y)/2,length:Math.sqrt(n*n+s*s),angle:Math.atan2(s,n)})}return a}function scaleBar(t){const a=t/4;const l=(0,_format.usesMiles)()?1609.344:1e3;const i=(0,_format.usesMiles)()?[.01,.02,.05,.1,.2,.5,1,2,5,10,20,50,100].map(n=>n*l):[10,20,50,100,200,500,1e3,2e3,5e3,1e4,2e4,5e4,1e5];let r=i[0];for(const n of i)if(n<=a)r=n;return{fraction:r/t,label:(0,_format.formatDistance)(r)}}function slug(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}const styles=_reactNative.StyleSheet.create({map:{width:"100%",aspectRatio:ASPECT,borderRadius:_sharedUi.night.radius.card,borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface,overflow:"hidden"},gridV:{position:"absolute",top:0,bottom:0,width:_reactNative.StyleSheet.hairlineWidth,backgroundColor:"rgba(255, 255, 255, 0.04)"},gridH:{position:"absolute",left:0,right:0,height:_reactNative.StyleSheet.hairlineWidth,backgroundColor:"rgba(255, 255, 255, 0.04)"},fence:{position:"absolute",borderRadius:9999,borderWidth:1,borderColor:"rgba(255, 255, 255, 0.22)",backgroundColor:"rgba(255, 255, 255, 0.04)",minWidth:10,minHeight:10},fenceInside:{borderColor:_sharedUi.night.color.accentBorderStrong,backgroundColor:_sharedUi.night.color.accentSoft},segment:{position:"absolute",height:3,marginTop:-1.5,borderRadius:1.5,backgroundColor:"rgba(248, 113, 113, 0.45)"},placeHit:{position:"absolute",flexDirection:"row",alignItems:"center",gap:4,height:24,marginTop:-12,marginLeft:-12,paddingLeft:8,paddingRight:4},placeDot:{width:8,height:8,borderRadius:4,backgroundColor:_sharedUi.night.color.textSecondary},placeDotSelected:{backgroundColor:_sharedUi.night.color.text},placeLabel:{color:_sharedUi.night.color.textSecondary,fontSize:10,fontWeight:"500",maxWidth:110},pinWrap:{position:"absolute",width:28,height:28,marginLeft:-14,marginTop:-14,alignItems:"center",justifyContent:"center"},pinHalo:{position:"absolute",width:28,height:28,borderRadius:14,backgroundColor:"rgba(248, 113, 113, 0.22)"},pin:{width:14,height:14,borderRadius:7,backgroundColor:PIN,borderWidth:2,borderColor:"#FFFFFF"},pinHollow:{backgroundColor:"transparent",borderColor:PIN},scale:{position:"absolute",left:10,right:10,bottom:8,gap:3},scaleBar:{height:2,borderRadius:1,backgroundColor:_sharedUi.night.color.textTertiary},scaleLabel:{color:_sharedUi.night.color.textTertiary,fontSize:10,fontVariant:["tabular-nums"]},offMap:{position:"absolute",right:10,bottom:8,color:_sharedUi.night.color.textTertiary,fontSize:10}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.chipLine=chipLine;exports.formatAccuracy=formatAccuracy;Object.defineProperty(exports,"formatCoordinate",{enumerable:true,get:function(){return _geo.formatCoordinate}});exports.formatDistance=formatDistance;exports.formatDuration=formatDuration;exports.formatSpeed=formatSpeed;exports.formatWhen=formatWhen;exports.permissionLine=permissionLine;exports.setImperialUnits=setImperialUnits;exports.stateLine=stateLine;exports.titleLine=titleLine;exports.titleTone=titleTone;exports.usesMiles=usesMiles;var _geo=require("../engine/geo");const MILES_REGIONS=new Set(["US","GB","LR","MM"]);let imperialOverride=null;function setImperialUnits(e){imperialOverride=e}function localeRegion(){try{const e=Intl.DateTimeFormat().resolvedOptions().locale;const r=/[-_]([A-Z]{2})\b/.exec(e);return r?r[1]:null}catch{return null}}let cachedImperial=null;function usesMiles(){if(imperialOverride!==null)return imperialOverride;if(cachedImperial===null)cachedImperial=MILES_REGIONS.has(localeRegion()??"");return cachedImperial}const FEET_PER_METER=3.28084;const METERS_PER_MILE=1609.344;function formatDistance(e){if(!Number.isFinite(e))return"\u2013";const r=Math.abs(e);if(usesMiles()){const t=r/METERS_PER_MILE;if(t<.1)return`${Math.round(r*FEET_PER_METER/10)*10} ft`;return`${oneDecimalBelowTen(t)} mi`}if(r<1e3)return`${Math.round(r)} m`;return`${oneDecimalBelowTen(r/1e3)} km`}function oneDecimalBelowTen(e){const r=Math.round(e*10)/10;return r<10?r.toFixed(1):Math.round(e).toLocaleString("en-US")}function formatAccuracy(e){if(!Number.isFinite(e))return"\u2013";if(e>=1e3)return`\xB1${formatDistance(e)}`;return usesMiles()?`\xB1${Math.round(e*FEET_PER_METER)} ft`:`\xB1${Math.round(e)} m`}function formatSpeed(e){if(e==null||e<0)return"\u2013";const r=usesMiles()?e*3600/METERS_PER_MILE:e*3.6;const t=usesMiles()?"mph":"km/h";return`${r<10?r.toFixed(1):Math.round(r)} ${t}`}function formatDuration(e){if(!Number.isFinite(e)||e<0)return"\u2013";const r=Math.round(e/6e4);if(r<1)return`${Math.max(1,Math.round(e/1e3))} sec`;if(r<60)return`${r} min`;const t=Math.floor(r/60);const n=r%60;return n?`${t} hr ${n} min`:`${t} hr`}function formatWhen(e,r){const t=Math.max(0,Math.round((r-e)/1e3));if(t<5)return"now";if(t<60)return`${t}s ago`;try{return new Date(e).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}catch{const n=new Date(e);return`${n.getHours()}:${String(n.getMinutes()).padStart(2,"0")}`}}function titleLine(e){if(!e.override.services)return"Location Services Off";if(!e.override.signal)return"No GPS Signal";if(e.override.mode==="real")return"Real Location";if(e.override.mode==="route")return e.override.route?.name??"Route";return e.override.place.label||"Dropped Pin"}function titleTone(e){if(!e.override.services||!e.override.signal)return"broken";return e.override.mode==="real"?"real":"simulated"}function stateLine(e){if(!e.override.services)return"The app is told location services are off";if(!e.override.signal)return"Updates stop and location requests fail";if(e.override.mode==="real")return"The app gets the device's location";const r=[];if(e.override.mode==="route"&&e.progress){const n=e.progress;if(n.finished)r.push("Arrived");else if(!e.override.playing)r.push("Paused");if(e.current.reason==="gap")r.push("no signal here");if(!n.finished){r.push(`${formatDistance(n.along)} of ${formatDistance(n.length)}`);if(n.etaMs!=null)r.push(`${formatDuration(n.etaMs)} left`);else if(e.override.route?.loop)r.push("on repeat")}}else{r.push("Pinned")}const t=e.current.fix;if(t&&e.override.mode==="fixed")r.push(formatAccuracy(t.accuracy));if(e.current.precision==="reduced")r.push("approximate");return r.join(" \xB7 ")}function permissionLine(e){if(e.status==="denied")return"Not Allowed";if(e.status==="undetermined")return"Not Asked Yet";const r=e.background?"Always":"While Using";return`${r} \xB7 ${e.precision==="reduced"?"Approximate":"Precise"}`}function chipLine(e){if(!e.override.services)return"The app is told location is off";if(!e.override.signal)return"Updates stop, requests fail";if(e.override.mode==="route"&&e.progress){if(e.progress.finished)return"Arrived";const t=`${formatDistance(e.progress.along)} of ${formatDistance(e.progress.length)}`;return e.override.playing?t:`Paused \xB7 ${t}`}const r=e.current.fix;return r?`Pinned \xB7 ${(0,_geo.formatCoordinate)(r,3)}`:"Pinned"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.COMMUNITY_MODULES=void 0;exports.exportPosition=exportPosition;exports.installCommunityAdapters=installCommunityAdapters;var _store=require("../store");var _wrap=require("./wrap");var ReactNative=_interopRequireWildcard(require("react-native"));function _interopRequireWildcard(t,r){if("function"==typeof WeakMap)var i=new WeakMap,u=new WeakMap;return(_interopRequireWildcard=function(o,n){if(!n&&o&&o.__esModule)return o;var l,c,s={__proto__:null,default:o};if(null===o||"object"!=typeof o&&"function"!=typeof o)return s;if(l=n?u:i){if(l.has(o))return l.get(o);l.set(o,s)}for(const e in o)"default"!==e&&{}.hasOwnProperty.call(o,e)&&((c=(l=Object.defineProperty)&&Object.getOwnPropertyDescriptor(o,e))&&(c.get||c.set)?l(s,e,c):s[e]=o[e]);return s})(t,r)}const COMMUNITY_MODULES=exports.COMMUNITY_MODULES=[{module:"RNCGeolocation",library:"@react-native-community/geolocation"},{module:"RNFusedLocation",library:"react-native-geolocation-service"}];const CODES={PERMISSION_DENIED:1,POSITION_UNAVAILABLE:2,TIMEOUT:3};function positionError(t,r){return{code:t,message:r,...CODES}}function reactNative(){return ReactNative}function findModule(t){const r=reactNative();if(!r)return null;let i=null;try{const u=globalThis.__turboModuleProxy!=null;if(u||typeof r.TurboModuleRegistry?.get==="function")i=r.TurboModuleRegistry?.get?.(t)}catch{i=null}if(!i){try{i=r.NativeModules?.[t]}catch{i=null}}return i&&typeof i==="object"?i:null}function exportPosition(t,r,i){const u={coords:{latitude:t.latitude,longitude:t.longitude,altitude:t.altitude,accuracy:t.accuracy,altitudeAccuracy:t.altitudeAccuracy,heading:t.heading??(r==="ios"?-1:0),speed:t.speed??(r==="ios"?-1:0)},timestamp:i};if(r==="android")u.mocked=false;return u}const held=[];function install(t){const r=findModule(t.module);if(!r||typeof r.getCurrentPosition!=="function")return false;held.push(r);const i=reactNative();const u=i?.Platform?.OS??"ios";const o=(e,a)=>i?.DeviceEventEmitter?.emit(e,a);const n={options:null,native:false,on:false};const l=()=>(0,_store.trackWatch)({library:t.library,id:"observer",kind:"position",options:n.options??{},deliver:e=>o("geolocationDidChange",exportPosition(e,u,Date.now())),fail:e=>o("geolocationError",positionError(2,e))});(0,_wrap.wrapMethod)(r,"getCurrentPosition",e=>(...a)=>{if(!(0,_store.isLocationActive)())return e(...a);const p=a[1];const f=a[2];if(!(0,_store.servicesEnabled)()){(0,_store.addLog)("request",t.library,"getCurrentPosition \u2192 services off");f?.(positionError(2,"No location provider available."));return void 0}const{fix:d}=(0,_store.currentFix)();if(!d){(0,_store.addLog)("request",t.library,"getCurrentPosition \u2192 no signal");(0,_store.realSetTimeout)(()=>f?.(positionError(3,"Unable to fetch location within 1.0s.")),1e3);return void 0}(0,_store.addLog)("request",t.library,`getCurrentPosition \u2192 ${d.latitude.toFixed(5)}, ${d.longitude.toFixed(5)}`);(0,_store.realSetTimeout)(()=>p?.(exportPosition(d,u,Date.now())),0);return void 0});const c=(0,_wrap.wrapMethod)(r,"startObserving",e=>(...a)=>{n.options=a[0]&&typeof a[0]==="object"?a[0]:{};n.on=true;if(!(0,_store.isLocationActive)()){n.native=true;return e(...a)}n.native=false;l();return void 0});const s=(0,_wrap.wrapMethod)(r,"stopObserving",e=>(...a)=>{n.on=false;(0,_store.untrackWatch)(t.library,"position","observer");if(n.native){n.native=false;return e(...a)}return void 0});(0,_store.registerAdapter)({library:t.library,onActiveChange(e){if(!n.on)return;if(e&&n.native){n.native=false;s?.();l()}else if(!e&&!n.native){(0,_store.untrackWatch)(t.library,"position","observer");n.native=true;c?.(n.options??{})}}});return true}function installCommunityAdapters(){return COMMUNITY_MODULES.filter(install).map(t=>t.library)}
@@ -0,0 +1,3 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.EXPO_LIBRARY=void 0;exports.exportLocation=exportLocation;exports.installExpoLocationAdapter=installExpoLocationAdapter;var _store=require("../store");var _wrap=require("./wrap");var _expoModulesCore=require("./expoModulesCore");var ReactNative=_interopRequireWildcard(require("react-native"));function _interopRequireWildcard(d,r){if("function"==typeof WeakMap)var s=new WeakMap,c=new WeakMap;return(_interopRequireWildcard=function(a,u){if(!u&&a&&a.__esModule)return a;var p,A,y={__proto__:null,default:a};if(null===a||"object"!=typeof a&&"function"!=typeof a)return y;if(p=u?c:s){if(p.has(a))return p.get(a);p.set(a,y)}for(const g in a)"default"!==g&&{}.hasOwnProperty.call(a,g)&&((A=(p=Object.defineProperty)&&Object.getOwnPropertyDescriptor(a,g))&&(A.get||A.set)?p(y,g,A):y[g]=a[g]);return y})(d,r)}const EXPO_LIBRARY=exports.EXPO_LIBRARY="expo-location";function platformOS(){return ReactNative.Platform?.OS??"ios"}function expoModule(d){try{const s=globalThis.expo?.modules;const c=s?.[d];if(c&&typeof c==="object")return c}catch{}const r=(0,_expoModulesCore.requireOptionalExpoModule)(d);return r&&typeof r==="object"?r:null}function exportLocation(d,r,s){const c=r==="ios";const a={coords:{latitude:d.latitude,longitude:d.longitude,altitude:d.altitude??(c?0:null),accuracy:d.accuracy,altitudeAccuracy:d.altitudeAccuracy??(c?-1:null),heading:d.heading??(c?-1:null),speed:d.speed??(c?-1:null)},timestamp:s};if(r==="android")a.mocked=false;return a}function failMessage(d,r,s){return s==="ios"?`Calling the '${d}' function has failed
2
+ \u2192 Caused by: ${r}`:`Call to function 'ExpoLocation.${d}' has been rejected.
3
+ \u2192 Caused by: ${r}`}const ERRORS={denied:{ios:{code:"ERR_DENIED_FOREGROUND_LOCATION_PERMISSION",reason:"Location permission is required to do this operation"},android:{code:"ERR_LOCATION_UNAUTHORIZED",reason:"Not authorized to use location services"}},deniedBackground:{ios:{code:"ERR_DENIED_BACKGROUND_LOCATION_PERMISSION",reason:"Background location permission is required to do this operation"},android:{code:"ERR_LOCATION_BACKGROUND_UNAUTHORIZED",reason:"Not authorized to use background location services"}},services:{ios:{code:"ERR_LOCATION_SERVICES_DISABLED",reason:"Location services are disabled"},android:{code:"ERR_LOCATION_SETTINGS_UNSATISFIED",reason:"Location request failed due to unsatisfied device settings"}},unavailable:{ios:{code:"ERR_LOCATION_UNAVAILABLE",reason:"Cannot obtain current location"},android:{code:"ERR_CURRENT_LOCATION_IS_UNAVAILABLE",reason:"Current location is unavailable. Make sure that location services are enabled"}}};function reject(d,r,s){const c=s==="android"?ERRORS[d].android:ERRORS[d].ios;return Promise.reject((0,_wrap.codedError)(c.code,failMessage(r,c.reason,s)))}let installed=false;function installExpoLocationAdapter(){const d=expoModule("ExpoLocation");if(!d||typeof d.getCurrentPositionAsync!=="function")return false;const r=d;const s=expoModule("ExpoTaskManager");const c=platformOS();const a=new Map;const u={};const p=()=>Date.now();const A=n=>e=>r.emit?.("Expo.locationChanged",{watchId:n,location:exportLocation(e,c,p())});const y=n=>e=>{const t=e.heading??0;r.emit?.("Expo.headingChanged",{watchId:n,heading:{trueHeading:t,magHeading:t,accuracy:3}})};const g=n=>e=>r.emit?.("Expo.locationError",{watchId:n,reason:e});async function v(){const n=r.getForegroundPermissionsAsync;const e={granted:true,status:"granted",precision:"full",reported:false};if(typeof n!=="function")return e;try{const t=await n.call(r);const o=t?.ios?.accuracy==="reduced"||t?.android?.accuracy==="coarse";const i=o?"reduced":"full";(0,_store.notePrecision)(i);const l=t?.granted===true;const f=l?"granted":t?.status==="undetermined"?"undetermined":"denied";return{granted:l,status:f,precision:i,reported:true}}catch{return e}}async function P(){const n=r.getBackgroundPermissionsAsync;if(typeof n!=="function")return null;try{return(await n.call(r))?.granted===true}catch{return null}}async function R(){const n=r.getBackgroundPermissionsAsync;if(typeof n!=="function")return true;try{return(await n.call(r))?.granted===true}catch{return true}}function h(n,e){(0,_store.trackWatch)({library:EXPO_LIBRARY,id:n,kind:e.kind,options:e.options,deliver:e.kind==="position"?A(n):y(n),fail:g(n)})}u.getCurrentPositionAsync=(0,_wrap.wrapMethod)(r,"getCurrentPositionAsync",n=>async(...e)=>{if(!(0,_store.isLocationActive)())return n(...e);const t="getCurrentPositionAsync";if(!(0,_store.servicesEnabled)()){(0,_store.addLog)("request",EXPO_LIBRARY,"getCurrentPositionAsync \u2192 services off");return reject("services",t,c)}const o=await v();if(!o.granted){(0,_store.addLog)("request",EXPO_LIBRARY,"getCurrentPositionAsync \u2192 permission denied");return reject("denied",t,c)}const{fix:i}=(0,_store.currentFix)();if(!i){(0,_store.addLog)("request",EXPO_LIBRARY,"getCurrentPositionAsync \u2192 no signal");await new Promise(l=>(0,_store.realSetTimeout)(()=>l(null),1e3));return reject("unavailable",t,c)}(0,_store.addLog)("request",EXPO_LIBRARY,`getCurrentPositionAsync \u2192 ${i.latitude.toFixed(5)}, ${i.longitude.toFixed(5)}`);return exportLocation(i,c,p())});u.getLastKnownPositionAsync=(0,_wrap.wrapMethod)(r,"getLastKnownPositionAsync",n=>async(...e)=>{if(!(0,_store.isLocationActive)())return n(...e);const t=await v();if(!t.granted)return reject("denied","getLastKnownPositionAsync",c);const{fix:o}=(0,_store.currentFix)();(0,_store.addLog)("request",EXPO_LIBRARY,`getLastKnownPositionAsync \u2192 ${o?"simulated":"null"}`);return o?exportLocation(o,c,p()):null});u.watchPositionImplAsync=(0,_wrap.wrapMethod)(r,"watchPositionImplAsync",n=>async(...e)=>{const t=Number(e[0]);const o=e[1]&&typeof e[1]==="object"?e[1]:{};if(!(0,_store.isLocationActive)()){const f=await n(...e);const k={kind:"position",options:o,native:true};a.set(t,k);if((0,_store.isLocationActive)())w(t,k);return f}const i=await v();if(!i.granted)return reject("denied","watchPositionImplAsync",c);if(!(0,_store.isLocationActive)()){a.set(t,{kind:"position",options:o,native:true});return n(...e)}const l={kind:"position",options:o,native:false};a.set(t,l);h(t,l);return void 0});u.watchDeviceHeading=(0,_wrap.wrapMethod)(r,"watchDeviceHeading",n=>async(...e)=>{const t=Number(e[0]);if(!(0,_store.isLocationActive)()){const l=await n(...e);const f={kind:"heading",options:{},native:true};a.set(t,f);if((0,_store.isLocationActive)())w(t,f);return l}const o=await v();if(!o.granted)return reject("denied","watchDeviceHeading",c);if(!(0,_store.isLocationActive)()){a.set(t,{kind:"heading",options:{},native:true});return n(...e)}const i={kind:"heading",options:{},native:false};a.set(t,i);h(t,i);return void 0});u.removeWatchAsync=(0,_wrap.wrapMethod)(r,"removeWatchAsync",n=>async(...e)=>{const t=Number(e[0]);const o=a.get(t);a.delete(t);(0,_store.untrackWatch)(EXPO_LIBRARY,"position",t);(0,_store.untrackWatch)(EXPO_LIBRARY,"heading",t);if(!o||o.native)return n(...e);return void 0});(0,_wrap.wrapMethod)(r,"hasServicesEnabledAsync",n=>async(...e)=>{if((0,_store.isLocationActive)()&&!(0,_store.servicesEnabled)())return false;return n(...e)});(0,_wrap.wrapMethod)(r,"getProviderStatusAsync",n=>async(...e)=>{const t=await n(...e);if(!(0,_store.isLocationActive)()||(0,_store.servicesEnabled)())return t;const o={...t,locationServicesEnabled:false};for(const i of["gpsAvailable","networkAvailable","passiveAvailable"])if(i in o)o[i]=false;return o});const L=(n,e)=>(0,_wrap.wrapMethod)(r,e,t=>async(...o)=>{const i=String(o[0]);const l=o[1]&&typeof o[1]==="object"?o[1]:{};const f={name:i,kind:n,library:EXPO_LIBRARY,options:l};if(!(0,_store.isLocationActive)()){const S=await t(...o);(0,_store.trackTask)(f,false);if((0,_store.isLocationActive)())E(true);return S}if(n==="locationUpdates"&&!(0,_store.servicesEnabled)())return reject("services",e,c);const k=await v();if(!k.granted)return reject("denied",e,c);if(n==="geofencing"&&!await R()){return reject("deniedBackground",e,c)}(0,_store.trackTask)(f,true);return void 0});u.startLocationUpdatesAsync=L("locationUpdates","startLocationUpdatesAsync");u.startGeofencingAsync=L("geofencing","startGeofencingAsync");const T=(n,e)=>(0,_wrap.wrapMethod)(r,e,t=>async(...o)=>{const i=(0,_store.getTask)(String(o[0]));if(i&&i.kind===n){(0,_store.untrackTask)(i.name);if(i.intercepted)return void 0}return t(...o)});u.stopLocationUpdatesAsync=T("locationUpdates","stopLocationUpdatesAsync");u.stopGeofencingAsync=T("geofencing","stopGeofencingAsync");const _=(n,e)=>(0,_wrap.wrapMethod)(r,e,t=>async(...o)=>{const i=(0,_store.getTask)(String(o[0]));if(i&&i.kind===n)return true;return t(...o)});_("locationUpdates","hasStartedLocationUpdatesAsync");_("geofencing","hasStartedGeofencingAsync");const m=new Map;let b=0;const I={geofencing:"geofencing",locationUpdates:"location"};if(s){(0,_wrap.wrapMethod)(s,"notifyTaskFinishedAsync",n=>async(...e)=>{const t=e[1]??{};const o=t.eventId?m.get(t.eventId):void 0;if(o&&t.eventId){m.delete(t.eventId);o(t.result);return void 0}return n(...e)});(0,_wrap.wrapMethod)(s,"isTaskRegisteredAsync",n=>async(...e)=>{if((0,_store.getTask)(String(e[0]))?.intercepted)return true;return n(...e)});(0,_wrap.wrapMethod)(s,"getTaskOptionsAsync",n=>async(...e)=>{const t=(0,_store.getTask)(String(e[0]));if(t?.intercepted)return t.options;return n(...e)});(0,_wrap.wrapMethod)(s,"getRegisteredTasksAsync",n=>async(...e)=>{const t=await n(...e)??[];const o=(0,_store.getTasks)().filter(i=>i.intercepted).map(i=>({taskName:i.name,taskType:I[i.kind],options:i.options}));return[...t,...o]});(0,_wrap.wrapMethod)(s,"unregisterTaskAsync",n=>async(...e)=>{const t=(0,_store.getTask)(String(e[0]));if(t){(0,_store.untrackTask)(t.name);if(t.intercepted)return void 0}return n(...e)});(0,_wrap.wrapMethod)(s,"unregisterAllTasksAsync",n=>async(...e)=>{for(const t of(0,_store.getTasks)())(0,_store.untrackTask)(t.name);return n(...e)})}function N(){if(!s)return null;if(s.__expo_module_name__&&typeof s.emit==="function")return(e,t)=>s.emit(e,t);const n=ReactNative.DeviceEventEmitter;return n?(e,t)=>n.emit(e,t):null}async function O(n){for(let e=0;e<5e3&&(0,_expoModulesCore.isTaskDefined)(n)===false;e+=100){await new Promise(t=>(0,_store.realSetTimeout)(()=>t(null),100))}}async function M(n,e){await O(n.name);const t=N();if(!t)return Promise.reject(new Error("expo-task-manager is not installed"));const o=`buoy-location-${++b}`;const i=typeof s?.EVENT_NAME==="string"?s.EVENT_NAME:"TaskManager.executeTask";return new Promise((l,f)=>{m.set(o,l);(0,_store.realSetTimeout)(()=>{if(m.delete(o))f(new Error("did not finish within 30 s"))},3e4);try{t(i,{data:e,error:null,executionInfo:{eventId:o,taskName:n.name,appState:"active"}})}catch(k){m.delete(o);f(k)}})}function w(n,e){if(!e.native)return;e.native=false;void Promise.resolve(u.removeWatchAsync?.(n)).catch(()=>{});h(n,e)}function E(n){for(const[e,t]of Array.from(a.entries())){if(n&&t.native){w(e,t)}else if(!n&&!t.native){(0,_store.untrackWatch)(EXPO_LIBRARY,t.kind,e);const o=t.kind==="position"?u.watchPositionImplAsync:u.watchDeviceHeading;t.native=true;void Promise.resolve(t.kind==="position"?o?.(e,t.options):o?.(e)).catch(i=>{t.native=false;g(e)(String(i?.message??i))})}else if(n&&!t.native&&!(0,_store.hasWatch)(EXPO_LIBRARY,t.kind,e)){h(e,t)}}for(const e of(0,_store.getTasks)()){if(e.library!==EXPO_LIBRARY)continue;const t=e.kind==="geofencing";if(n&&!e.intercepted){const o=t?u.stopGeofencingAsync:u.stopLocationUpdatesAsync;void Promise.resolve(o?.(e.name)).catch(()=>{});(0,_store.setTaskIntercepted)(e.name,true)}else if(!n&&e.intercepted){const o=t?u.startGeofencingAsync:u.startLocationUpdatesAsync;(0,_store.setTaskIntercepted)(e.name,false);void Promise.resolve(o?.(e.name,e.options)).catch(i=>{(0,_store.addLog)("error",EXPO_LIBRARY,`Could not restart ${e.name} natively: ${String(i?.message??i)}`)})}}}(0,_store.registerAdapter)({library:EXPO_LIBRARY,fireTask:M,onActiveChange:E,readPermission:async()=>{const n=await v();if(!n.reported)return null;const e=n.status==="granted"?await P():false;return{status:n.status,background:e,precision:n.precision}}});if(!installed){installed=true;if(s&&typeof s.getRegisteredTasksAsync==="function"){void Promise.resolve(s.getRegisteredTasksAsync.call(s)).then(n=>{for(const e of n??[]){if(!e?.taskName||(0,_store.getTask)(e.taskName))continue;const t=e.taskType==="geofencing"?"geofencing":e.taskType==="location"?"locationUpdates":null;if(!t)continue;(0,_store.trackTask)({name:e.taskName,kind:t,library:EXPO_LIBRARY,options:e.options??{}},false);if((0,_store.isLocationActive)())E(true)}}).catch(()=>{})}}return true}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.isTaskDefined=isTaskDefined;exports.requireOptionalExpoModule=requireOptionalExpoModule;function requireOptionalExpoModule(r){try{const e=require("expo-modules-core");return e.requireOptionalNativeModule?.(r)??null}catch{return null}}function isTaskDefined(r){try{const e=require("expo-task-manager");return typeof e.isTaskDefined==="function"?e.isTaskDefined(r):null}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.isTaskDefined=isTaskDefined;exports.requireOptionalExpoModule=requireOptionalExpoModule;function requireOptionalExpoModule(e){return null}function isTaskDefined(e){return null}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.installLocationAdapters=installLocationAdapters;var _community=require("./community");var _expo=require("./expo");let found=null;function installLocationAdapters(){if(found)return found;found=[];if((0,_expo.installExpoLocationAdapter)())found.push("expo-location");found.push(...(0,_community.installCommunityAdapters)());return found}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.codedError=codedError;exports.wrapMethod=wrapMethod;const MARK="__buoyLocationNext";function wrapMethod(r,o,e){const n=r[o];if(typeof n!=="function")return null;const c=n[MARK]??n;const u=(...s)=>c.apply(r,s);const t=e(u);t[MARK]=c;try{r[o]=t}catch{return null}return r[o]===t?u:null}function codedError(r,o){const e=new Error(o);e.code=r;return e}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ROUTE_PRESETS=exports.BUILT_IN_PLACES=void 0;exports.buildPresetRoute=buildPresetRoute;exports.lineRoute=lineRoute;var _geo=require("./geo");const BUILT_IN_PLACES=exports.BUILT_IN_PLACES=[{latitude:37.3349,longitude:-122.009,label:"Apple Park"},{latitude:37.422,longitude:-122.0841,label:"Googleplex"},{latitude:40.758,longitude:-73.9855,label:"Times Square"},{latitude:51.508,longitude:-.1281,label:"Trafalgar Square"},{latitude:48.8584,longitude:2.2945,label:"Eiffel Tower"},{latitude:35.6595,longitude:139.7005,label:"Shibuya Crossing"},{latitude:-33.8568,longitude:151.2153,label:"Sydney Opera House"},{latitude:-23.5614,longitude:-46.6559,label:"S\xE3o Paulo"},{latitude:0,longitude:0,label:"Null Island"}];const ROUTE_PRESETS=exports.ROUTE_PRESETS=[{id:"walk",name:"Walk",description:"1 km north from here at walking pace",speed:1.4},{id:"run",name:"Run",description:"3 km north, then east, at running pace",speed:3.3},{id:"drive",name:"City Drive",description:"4 km of city streets with turns",speed:13.4},{id:"highway",name:"Highway",description:"30 km north at highway speed",speed:30},{id:"tunnel",name:"Tunnel",description:"3 km drive with no signal for 600 m in the middle",speed:13.4},{id:"loop",name:"Block Loop",description:"A 400 m block, walked on repeat",speed:1.4}];function buildPresetRoute(n,l,s=0){const r=ROUTE_PRESETS.find(i=>i.id===n);if(!r)throw new Error(`Unknown route preset "${n}". Use one of: ${ROUTE_PRESETS.map(i=>i.id).join(", ")}.`);const e={latitude:l.latitude,longitude:l.longitude};const t=(i,o,d)=>(0,_geo.destination)(i,s+o,d);let a;let u;let p=false;switch(n){case"walk":a=[e,t(e,0,1e3)];break;case"run":a=[e,t(e,0,1500),t(t(e,0,1500),90,1500)];break;case"drive":{const i=t(e,0,1200);const o=t(i,90,800);const d=t(o,0,1e3);const c=t(d,-90,1e3);a=[e,i,o,d,c];break}case"highway":a=[e,t(e,0,3e4)];break;case"tunnel":a=[e,t(e,0,3e3)];u=[[1200,1800]];break;case"loop":{const i=t(e,0,100);const o=t(i,90,100);const d=t(o,180,100);a=[e,i,o,d,e];p=true;break}}return{id:`preset:${n}`,name:r.name,points:a,speed:r.speed,loop:p,gaps:u}}function lineRoute(n,l,s){return{id:"line",name:l.label?`To ${l.label}`:"Straight line",points:[{latitude:n.latitude,longitude:n.longitude},{latitude:l.latitude,longitude:l.longitude}],speed:s}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.REDUCED_ACCURACY_M=exports.EARTH_RADIUS_M=void 0;exports.bearingDegrees=bearingDegrees;exports.destination=destination;exports.distanceMeters=distanceMeters;exports.evaluateRegions=evaluateRegions;exports.formatCoordinate=formatCoordinate;exports.formatDistance=formatDistance;exports.interpolate=interpolate;exports.isCoordinate=isCoordinate;exports.isInside=isInside;exports.jitter=jitter;exports.legLengths=legLengths;exports.normalizeLongitude=normalizeLongitude;exports.parseCoordinate=parseCoordinate;exports.pointForRegion=pointForRegion;exports.positionAlong=positionAlong;exports.reduceAccuracy=reduceAccuracy;exports.routeDurationMs=routeDurationMs;exports.routeLength=routeLength;exports.toRegion=toRegion;const EARTH_RADIUS_M=exports.EARTH_RADIUS_M=63710088e-1;const rad=t=>t*Math.PI/180;const deg=t=>t*180/Math.PI;function isCoordinate(t){if(!t||typeof t!=="object")return false;const{latitude:e,longitude:n}=t;return typeof e==="number"&&typeof n==="number"&&Number.isFinite(e)&&Number.isFinite(n)&&Math.abs(e)<=90&&Math.abs(n)<=180}function normalizeLongitude(t){const e=((t+180)%360+360)%360-180;return e===-180&&t>0?180:e}function distanceMeters(t,e){const n=rad(e.latitude-t.latitude);const i=rad(e.longitude-t.longitude);const o=Math.sin(n/2)**2+Math.cos(rad(t.latitude))*Math.cos(rad(e.latitude))*Math.sin(i/2)**2;return 2*EARTH_RADIUS_M*Math.asin(Math.min(1,Math.sqrt(o)))}function bearingDegrees(t,e){const n=rad(t.latitude);const i=rad(e.latitude);const o=rad(e.longitude-t.longitude);const r=Math.sin(o)*Math.cos(i);const s=Math.cos(n)*Math.sin(i)-Math.sin(n)*Math.cos(i)*Math.cos(o);return(deg(Math.atan2(r,s))+360)%360}function destination(t,e,n){const i=n/EARTH_RADIUS_M;const o=rad(e);const r=rad(t.latitude);const s=rad(t.longitude);const u=Math.asin(Math.sin(r)*Math.cos(i)+Math.cos(r)*Math.sin(i)*Math.cos(o));const c=s+Math.atan2(Math.sin(o)*Math.sin(i)*Math.cos(r),Math.cos(i)-Math.sin(r)*Math.sin(u));return{latitude:deg(u),longitude:normalizeLongitude(deg(c))}}function interpolate(t,e,n){if(n<=0)return{latitude:t.latitude,longitude:t.longitude};if(n>=1)return{latitude:e.latitude,longitude:e.longitude};const i=distanceMeters(t,e);if(i<1e-6)return{latitude:t.latitude,longitude:t.longitude};return destination(t,bearingDegrees(t,e),i*n)}function legLengths(t){const e=[];for(let n=1;n<t.length;n++)e.push(distanceMeters(t[n-1],t[n]));return e}function routeLength(t){return legLengths(t).reduce((e,n)=>e+n,0)}function positionAlong(t,e){const{points:n}=t;if(n.length===0)throw new Error("A route needs at least one point.");const i=n[0];if(n.length===1){return{...i,along:0,heading:0,leg:0,finished:true,inGap:false}}const o=legLengths(n);const r=o.reduce((a,d)=>a+d,0);let s=Math.max(0,e);let u=false;if(r<=0){s=0;u=!t.loop}else if(t.loop){s=s%r}else if(s>=r){s=r;u=true}const c=(t.gaps??[]).some(([a,d])=>s>=a&&s<d);let l=s;for(let a=0;a<o.length;a++){const d=o[a];const f=n[a];const h=n[a+1];const M=a===o.length-1;if(l<d||M){const p=d>0?Math.min(1,l/d):1;const x=interpolate(f,h,p);return{...x,along:s,heading:bearingDegrees(f,h),leg:a,finished:u,inGap:c}}l-=d}const g=n[n.length-1];return{...g,along:s,heading:0,leg:o.length-1,finished:u,inGap:c}}function routeDurationMs(t){if(t.speed<=0)return Infinity;return routeLength(t.points)/t.speed*1e3}function jitter(t,e,n){if(e<=0)return{latitude:t.latitude,longitude:t.longitude};const i=fract(Math.sin(n*12.9898)*43758.5453);const o=fract(Math.sin(n*78.233)*12543.1234);return destination(t,i*360,Math.sqrt(o)*e)}function fract(t){return t-Math.floor(t)}const REDUCED_ACCURACY_M=exports.REDUCED_ACCURACY_M=3e3;function reduceAccuracy(t){const e=.03;const n=Math.round(t.latitude/e)*e;const i=e/Math.max(.2,Math.cos(rad(n)));const o=Math.round(t.longitude/i)*i;return{...t,latitude:round6(n),longitude:round6(normalizeLongitude(o)),accuracy:Math.max(t.accuracy,REDUCED_ACCURACY_M),heading:null,speed:null}}function round6(t){return Math.round(t*1e6)/1e6}function isInside(t,e){return distanceMeters(t,e)<=t.radius}function evaluateRegions(t,e,n){const i={};const o=[];for(const r of t){const s=e[r.identifier]??"unknown";const u=isInside(r,n)?"inside":"outside";i[r.identifier]=u;if(s===u)continue;const c=u==="inside"?"enter":"exit";const l=s==="unknown";if(l||(c==="enter"?r.notifyOnEnter:r.notifyOnExit)){o.push({identifier:r.identifier,kind:c,initial:l})}}return{states:i,transitions:o}}function pointForRegion(t,e,n){if(e==="inside")return{latitude:t.latitude,longitude:t.longitude};const i=n&&distanceMeters(t,n)>1?bearingDegrees(t,n):0;return destination(t,i,t.radius+Math.max(50,t.radius*.25))}function toRegion(t,e){if(!isCoordinate(t))return null;const n=t;const i=Number(n.radius);if(!Number.isFinite(i)||i<=0)return null;return{identifier:typeof n.identifier==="string"&&n.identifier?n.identifier:`region-${e+1}`,latitude:n.latitude,longitude:n.longitude,radius:i,notifyOnEnter:n.notifyOnEnter!==false,notifyOnExit:n.notifyOnExit!==false}}function parseCoordinate(t){const e=t.trim();const n=[/@(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)/,/[?&](?:q|ll|query|center)=(-?\d+(?:\.\d+)?)(?:,|%2C)\s*(-?\d+(?:\.\d+)?)/i,/^(-?\d+(?:\.\d+)?)\s*[,\s]\s*(-?\d+(?:\.\d+)?)$/];for(const i of n){const o=e.match(i);if(o){const r={latitude:Number(o[1]),longitude:Number(o[2])};if(isCoordinate(r))return r}}return null}function formatCoordinate(t,e=5){return`${t.latitude.toFixed(e)}, ${t.longitude.toFixed(e)}`}function formatDistance(t){if(!Number.isFinite(t))return"\u2013";if(t<1e3)return`${Math.round(t)} m`;if(t<1e4)return`${(t/1e3).toFixed(1)} km`;return`${Math.round(t/1e3)} km`}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DEFAULT_SETTINGS=exports.DEFAULT_PLACE=exports.CONDITIONS=void 0;exports.currentConditions=currentConditions;exports.defaultOverride=defaultOverride;exports.isOverrideActive=isOverrideActive;exports.isSimulatingPosition=isSimulatingPosition;exports.parseOverride=parseOverride;exports.parseRoute=parseRoute;var _geo=require("./geo");const DEFAULT_SETTINGS=exports.DEFAULT_SETTINGS={persist:true,showChip:true};const DEFAULT_PLACE=exports.DEFAULT_PLACE={latitude:37.3349,longitude:-122.009,label:"Apple Park"};function defaultOverride(){return{mode:"real",place:{...DEFAULT_PLACE},altitude:30,accuracy:5,jitter:0,heading:null,route:null,playing:false,anchorReal:0,anchorMeters:0,signal:true,services:true,interval:1e3}}function isOverrideActive(t){return!!t&&(t.mode!=="real"||!t.signal||!t.services)}function isSimulatingPosition(t){return!!t&&t.mode!=="real"}function num(t,e,r=-Infinity,i=Infinity){const n=typeof t==="number"?t:Number(t);return Number.isFinite(n)?Math.min(i,Math.max(r,n)):e}function nullableNum(t,e){if(t===null)return null;const r=typeof t==="number"?t:Number(t);return t!==void 0&&Number.isFinite(r)?r:e}function parseRoute(t){if(!t||typeof t!=="object")return null;const e=t;const r=Array.isArray(e.points)?e.points.filter(_geo.isCoordinate):[];if(r.length<2)return null;const i=Array.isArray(e.gaps)?e.gaps.filter(n=>Array.isArray(n)&&n.length===2&&n.every(a=>typeof a==="number"&&Number.isFinite(a))):void 0;return{id:typeof e.id==="string"?e.id:void 0,name:typeof e.name==="string"?e.name:void 0,points:r.map(n=>({latitude:n.latitude,longitude:n.longitude})),speed:num(e.speed,1.4,.1,400),loop:e.loop===true,gaps:i&&i.length?i:void 0}}function parseOverride(t){if(!t||typeof t!=="object")return null;const e=t;const r=defaultOverride();const i=e.mode==="fixed"||e.mode==="route"?e.mode:"real";const n=e.place;const a=(0,_geo.isCoordinate)(n)?{latitude:n.latitude,longitude:n.longitude,label:typeof n.label==="string"?n.label:void 0}:r.place;const s=parseRoute(e.route);return{mode:i==="route"&&!s?"fixed":i,place:a,altitude:nullableNum(e.altitude,r.altitude),accuracy:num(e.accuracy,r.accuracy,0,1e5),jitter:num(e.jitter,0,0,1e4),heading:e.heading===null||e.heading===void 0?null:num(e.heading,0,0,360)%360,route:s,playing:e.playing===true&&!!s,anchorReal:num(e.anchorReal,0),anchorMeters:num(e.anchorMeters,0,0),signal:e.signal!==false,services:e.services!==false,interval:num(e.interval,r.interval,100,6e4)}}const CONDITIONS=exports.CONDITIONS={good:{accuracy:5,jitter:0,signal:true,services:true},weak:{accuracy:65,jitter:50,signal:true,services:true},"no-signal":{accuracy:5,jitter:0,signal:false,services:true},off:{accuracy:5,jitter:0,signal:true,services:false}};function currentConditions(t){if(!t.services)return"off";if(!t.signal)return"no-signal";for(const e of["good","weak"]){const r=CONDITIONS[e];if(t.accuracy===r.accuracy&&t.jitter===r.jitter)return e}return null}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LOCATION_STORAGE_KEY=void 0;exports.parseSaved=parseSaved;exports.readSavedAsync=readSavedAsync;Object.defineProperty(exports,"readSavedSync",{enumerable:true,get:function(){return _readSavedSync.readSavedSync}});exports.writeSaved=writeSaved;var _sharedUi=require("@buoy-gg/shared-ui");var _model=require("./model");var _readSavedSync=require("./readSavedSync");const LOCATION_STORAGE_KEY=exports.LOCATION_STORAGE_KEY=_sharedUi.devToolsStorageKeys.location.state();function parseTask(t){if(!t||typeof t!=="object")return null;const e=t;if(typeof e.name!=="string"||!e.name)return null;if(e.kind!=="geofencing"&&e.kind!=="locationUpdates")return null;return{name:e.name,kind:e.kind,library:typeof e.library==="string"?e.library:"expo-location",options:e.options&&typeof e.options==="object"?e.options:{}}}function parseSaved(t){if(!t)return null;try{const e=JSON.parse(t);if(!e||e.v!==1)return null;const r=e.settings??{};return{v:1,override:(0,_model.parseOverride)(e.override),settings:{persist:typeof r.persist==="boolean"?r.persist:_model.DEFAULT_SETTINGS.persist,showChip:typeof r.showChip==="boolean"?r.showChip:_model.DEFAULT_SETTINGS.showChip},tasks:Array.isArray(e.tasks)?e.tasks.map(parseTask).filter(n=>n!==null):[]}}catch{return null}}async function readSavedAsync(){try{return parseSaved(await _sharedUi.persistentStorage.getItem(LOCATION_STORAGE_KEY))}catch{return null}}let writes=Promise.resolve();function writeSaved(t){const e=JSON.stringify(t);writes=writes.then(()=>_sharedUi.persistentStorage.setItem(LOCATION_STORAGE_KEY,e)).catch(()=>{});return writes.then(()=>{})}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.readSavedSync=readSavedSync;var _persistence=require("./persistence");function fsNames(e){const n=encodeURIComponent(e.replace(/~/g,"~0").replace(/\//g,"~1"));return n===e?[e]:[n,e]}function readSavedSync(){try{const e=require("expo-file-system");if(typeof e?.File!=="function"||!e.Paths?.document)return void 0;const n=new e.File(e.Paths.document,"react-buoy");if(typeof n.textSync!=="function")return void 0;for(const r of fsNames(_persistence.LOCATION_STORAGE_KEY)){const t=new e.File(e.Paths.document,"react-buoy",`${r}.json`);if(t.exists)return(0,_persistence.parseSaved)(t.textSync())}return null}catch{return void 0}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.readSavedSync=readSavedSync;function readSavedSync(){return void 0}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"CONDITIONS",{enumerable:true,get:function(){return _model.CONDITIONS}});exports.__resetForTests=__resetForTests;exports.__tickForTests=__tickForTests;exports.addLog=addLog;exports.bootLocation=bootLocation;exports.clearLog=clearLog;Object.defineProperty(exports,"currentConditions",{enumerable:true,get:function(){return _model.currentConditions}});exports.currentFix=currentFix;exports.currentPoint=currentPoint;exports.getAdapters=getAdapters;exports.getLocationSettings=getLocationSettings;exports.getLocationSnapshot=getLocationSnapshot;exports.getPrecision=getPrecision;exports.getTask=getTask;exports.getTasks=getTasks;exports.hasWatch=hasWatch;exports.isLocationActive=isLocationActive;exports.isSimulating=isSimulating;exports.moveToRegion=moveToRegion;exports.notePermission=notePermission;exports.notePrecision=notePrecision;exports.pauseRoute=pauseRoute;exports.realSetTimeout=realSetTimeout;exports.refreshLocationPermission=refreshLocationPermission;exports.registerAdapter=registerAdapter;exports.registerLocationPlaces=registerLocationPlaces;exports.registerLocationRoutes=registerLocationRoutes;exports.resetLocation=resetLocation;exports.resumeRoute=resumeRoute;exports.seekRoute=seekRoute;exports.servicesEnabled=servicesEnabled;exports.setConditions=setConditions;exports.setPlace=setPlace;exports.setRouteSpeed=setRouteSpeed;exports.setServices=setServices;exports.setSignal=setSignal;exports.setTaskIntercepted=setTaskIntercepted;exports.startRoute=startRoute;exports.stopRoute=stopRoute;exports.subscribeLocation=subscribeLocation;exports.trackTask=trackTask;exports.trackWatch=trackWatch;exports.tuneOverride=tuneOverride;exports.untrackTask=untrackTask;exports.untrackWatch=untrackWatch;exports.updateLocationSettings=updateLocationSettings;exports.useRealLocation=useRealLocation;var _sharedUi=require("@buoy-gg/shared-ui");var _geo=require("./geo");var _model=require("./model");var _persistence=require("./persistence");function timers(){const e=globalThis.__buoyRealTimers;return e??globalThis}function realSetTimeout(e,t){return timers().setTimeout(e,t)}function realClearTimeout(e){timers().clearTimeout(e)}let override=(0,_model.defaultOverride)();let settings={..._model.DEFAULT_SETTINGS};let precision="full";let permission=null;let booted=false;let wasActive=false;const adapters=new Map;const watches=new Map;const tasks=new Map;const log=[];let logId=0;let lastDeliveryAt=null;let seed=1;const appPlaces=[];const appRoutes=[];const listeners=new Set;let cached=null;function notify(){cached=null;for(const e of Array.from(listeners)){try{e()}catch{}}}function subscribeLocation(e){listeners.add(e);return()=>{listeners.delete(e)}}const MAX_LOG=100;function addLog(e,t,n,o){log.push({id:++logId,at:(0,_sharedUi.realNow)(),kind:e,library:t,text:n,...o?{detail:o}:{}});if(log.length>MAX_LOG)log.splice(0,log.length-MAX_LOG);notify()}function isLocationActive(){return(0,_model.isOverrideActive)(override)}function isSimulating(){return(0,_model.isSimulatingPosition)(override)}function servicesEnabled(){return override.services}function getPrecision(){return precision}function notePrecision(e){if(!e||e===precision)return;precision=e;notify()}function notePermission(e){if(!e)return;const t=permission&&permission.status===e.status&&permission.background===e.background&&permission.precision===e.precision;if(e.precision!==precision)precision=e.precision;if(t)return;permission=e;notify()}function metersAt(e){if(!override.route)return 0;if(!override.playing)return override.anchorMeters;return override.anchorMeters+Math.max(0,e-override.anchorReal)/1e3*override.route.speed}function currentFix(e=(0,_sharedUi.realNow)()){if(!override.services)return{fix:null,reason:"services"};if(!override.signal)return{fix:null,reason:"signal"};if(override.mode==="real")return{fix:null,reason:"real"};let t;let n=override.heading;let o=0;if(override.mode==="route"&&override.route){const s=(0,_geo.positionAlong)(override.route,metersAt(e));if(s.inGap)return{fix:null,reason:"gap"};t=s;const i=override.playing&&!s.finished;n=s.heading;o=i?override.route.speed:0}else{t=override.place}if(override.jitter>0){t=(0,_geo.jitter)(t,override.jitter,Math.floor(e/override.interval)+seed)}let r={latitude:t.latitude,longitude:t.longitude,altitude:override.altitude,accuracy:Math.max(override.accuracy,override.jitter),altitudeAccuracy:override.altitude===null?null:3,heading:n,speed:o};if(precision==="reduced")r=(0,_geo.reduceAccuracy)(r);return{fix:r,reason:null}}let timer=null;let precisionCheckAt=0;function needsLoop(){if(!(0,_model.isSimulatingPosition)(override))return false;if(watches.size>0||tasks.size>0)return true;return override.mode==="route"&&override.playing&&listeners.size>0}function schedule(){if(timer!==null)return;if(!needsLoop())return;timer=realSetTimeout(()=>{timer=null;tick();schedule()},override.interval)}function stopLoop(){if(timer!==null)realClearTimeout(timer);timer=null}function kick(){stopLoop();tick();schedule()}function watchOption(e,t){const n=Number(e.options[t]);return Number.isFinite(n)&&n>0?n:0}function tick(){const e=(0,_sharedUi.realNow)();const{fix:t}=currentFix(e);if(override.mode==="route"&&override.route&&override.playing){const n=(0,_geo.positionAlong)(override.route,metersAt(e));if(n.finished){override={...override,playing:false,anchorMeters:n.along,anchorReal:e};save()}}if(t){deliverToWatches(t,false);evaluateTasks(t)}if(e-precisionCheckAt>5e3){precisionCheckAt=e;refreshPrecision()}notify()}function deliverToWatches(e,t){for(const n of Array.from(watches.values())){if(n.kind==="heading"){const o=e.heading??0;if(!t&&n.lastHeading===o&&n.updates>0)continue;n.lastHeading=o}else{const o=watchOption(n,"distanceInterval");if(!t&&n.last){const r=(0,_geo.distanceMeters)(n.last,e);if(r<Math.max(o,.01))continue}n.last={latitude:e.latitude,longitude:e.longitude}}n.updates+=1;lastDeliveryAt=(0,_sharedUi.realNow)();try{n.deliver(e)}catch(o){addLog("error",n.library,`Watch ${n.id} callback threw: ${String(o?.message??o)}`)}}}function evaluateTasks(e){for(const t of Array.from(tasks.values())){if(t.kind==="geofencing"){const{states:n,transitions:o}=(0,_geo.evaluateRegions)(t.regions,t.states,e);t.states=n;for(const r of o)fireRegion(t,r)}else{const n=watchOption(t,"distanceInterval");if(t.lastBatchAt&&(0,_geo.distanceMeters)(t.lastBatchAt,e)<Math.max(n,.01))continue;t.lastBatchAt={latitude:e.latitude,longitude:e.longitude};fireTask(t,{locations:[e]},"a location update")}}}function fireRegion(e,t){const n=e.regions.find(r=>r.identifier===t.identifier);if(!n)return;addLog(t.kind,e.library,`${t.kind==="enter"?"Entered":"Left"} ${regionLabel(n)??n.identifier}`,`${e.name} \xB7 region ${n.identifier}${t.initial?" \xB7 first check after monitoring started":""}`);const o=regionLabel(n)??n.identifier;fireTask(e,{eventType:t.kind==="enter"?1:2,region:n},`${t.kind==="enter"?"entering":"leaving"} ${o}`)}function fireTask(e,t,n){const o=adapters.get(e.library);if(!o?.fireTask)return;e.runs+=1;const r=e.kind==="locationUpdates";if(r)addLog("batch",e.library,"Sent a background location update",e.name);o.fireTask(e,t).then(s=>{addLog("task",e.library,`Task ran for ${n}`,s!==void 0&&s!==null?`${e.name} \xB7 returned ${short(s)}`:e.name)},s=>{addLog("error",e.library,`Task failed for ${n}`,`${e.name} \xB7 ${String(s?.message??s)}`)})}function short(e){try{const t=typeof e==="string"?e:JSON.stringify(e);return t.length>80?`${t.slice(0,77)}\u2026`:t}catch{return String(e)}}function refreshPrecision(){refreshLocationPermission()}function refreshLocationPermission(){for(const e of adapters.values()){e.readPermission?.().then(notePermission,()=>{})}}function registerAdapter(e){adapters.set(e.library,e);notify()}function getAdapters(){return Array.from(adapters.keys())}function trackWatch(e){const t=`${e.library}:${e.kind}:${e.id}`;watches.set(t,{...e,key:t,since:(0,_sharedUi.realNow)(),updates:0,last:null,lastHeading:null});addLog("watch",e.library,e.kind==="heading"?"The app started watching the compass heading":"The app started watching location",`watch ${e.id} \xB7 ${e.library}`);realSetTimeout(()=>{const n=watches.get(t);if(!n)return;const{fix:o,reason:r}=currentFix();if(o){deliverToWatches(o,false);notify()}else if(r==="services"){n.fail?.("Location services are disabled")}},0);schedule()}function untrackWatch(e,t,n){const o=`${e}:${t}:${n}`;const r=watches.delete(o);if(r){addLog("watch",e,t==="heading"?"The app stopped watching the heading":"The app stopped watching location",`watch ${n} \xB7 ${e}`)}return r}function hasWatch(e,t,n){return watches.has(`${e}:${t}:${n}`)}function trackTask(e,t){const n=e.kind==="geofencing"?(e.options.regions??[]).map((o,r)=>(0,_geo.toRegion)(o,r)).filter(o=>o!==null):[];tasks.set(e.name,{...e,regions:n,states:{},since:(0,_sharedUi.realNow)(),runs:0,intercepted:t,lastBatchAt:null});addLog("task",e.library,e.kind==="geofencing"?`The app started monitoring ${n.length} geofence${n.length===1?"":"s"}`:"The app started background location updates",e.name);save();if((0,_model.isSimulatingPosition)(override)){realSetTimeout(()=>{const{fix:o}=currentFix();const r=tasks.get(e.name);if(o&&r){evaluateTasks(o);notify()}},0)}schedule()}function untrackTask(e){const t=tasks.get(e);if(!t)return null;tasks.delete(e);addLog("task",t.library,t.kind==="geofencing"?"The app stopped monitoring geofences":"The app stopped background updates",t.name);save();return t}function getTask(e){return tasks.get(e)??null}function getTasks(e){return Array.from(tasks.values()).filter(t=>!e||t.kind===e)}function setTaskIntercepted(e,t){const n=tasks.get(e);if(!n)return;n.intercepted=t;if(!t)n.states={};save()}function registerLocationPlaces(e){for(const t of e){const n=appPlaces.findIndex(o=>o.label&&o.label===t.label);if(n>=0)appPlaces[n]={...t};else appPlaces.push({...t})}notify()}function regionLabel(e){let t=null;let n=Infinity;for(const o of appPlaces){if(!o.label)continue;const r=(0,_geo.distanceMeters)(o,e);if(r<=Math.max(50,e.radius)&&r<n){t=o;n=r}}return t?.label??null}function registerLocationRoutes(e){for(const t of e){const n=(0,_model.parseRoute)(t);if(!n)continue;const o=appRoutes.findIndex(r=>(r.id??r.name)===(n.id??n.name));if(o>=0)appRoutes[o]=n;else appRoutes.push(n)}notify()}function commit(e){override=e;const t=(0,_model.isOverrideActive)(override);if(t!==wasActive){wasActive=t;for(const n of adapters.values()){try{n.onActiveChange?.(t)}catch(o){addLog("error",n.library,`Switching failed: ${String(o?.message??o)}`)}}}save();if((0,_model.isSimulatingPosition)(override))kick();else{stopLoop();notify()}return getLocationSnapshot()}function setPlace(e){return commit({...override,mode:"fixed",place:{latitude:e.latitude,longitude:e.longitude,label:e.label},playing:false})}function currentPoint(){if(override.mode==="route"&&override.route)return(0,_geo.positionAlong)(override.route,metersAt((0,_sharedUi.realNow)()));return override.place}function startRoute(e){const t=(0,_model.parseRoute)(e);if(!t)throw new Error("A route needs two or more valid points.");return commit({...override,mode:"route",route:t,playing:true,anchorReal:(0,_sharedUi.realNow)(),anchorMeters:0})}function pauseRoute(){if(override.mode!=="route"||!override.playing)return getLocationSnapshot();const e=(0,_sharedUi.realNow)();return commit({...override,playing:false,anchorMeters:metersAt(e),anchorReal:e})}function resumeRoute(){if(override.mode!=="route"||!override.route)return getLocationSnapshot();const e=(0,_geo.routeLength)(override.route.points);const t=!override.route.loop&&override.anchorMeters>=e?0:override.anchorMeters;return commit({...override,playing:true,anchorReal:(0,_sharedUi.realNow)(),anchorMeters:t})}function seekRoute(e){if(override.mode!=="route"||!override.route)throw new Error("No route is playing.");return commit({...override,anchorMeters:Math.max(0,e),anchorReal:(0,_sharedUi.realNow)()})}function setRouteSpeed(e){if(!override.route)throw new Error("No route is loaded.");if(!Number.isFinite(e)||e<=0)throw new Error("Speed must be a positive number of m/s.");const t=(0,_sharedUi.realNow)();return commit({...override,route:{...override.route,speed:e},anchorMeters:metersAt(t),anchorReal:t})}function tuneOverride(e){const t=(0,_model.parseOverride)({...override,...stripUndefined(e)});if(!t)return getLocationSnapshot();return commit({...t,anchorMeters:override.anchorMeters,anchorReal:override.anchorReal})}function stripUndefined(e){const t={};for(const[n,o]of Object.entries(e))if(o!==void 0)t[n]=o;return t}function setSignal(e){return commit({...override,signal:e})}function setServices(e){const t=commit({...override,services:e});if(!e){for(const n of Array.from(watches.values())){if(n.kind==="position")n.fail?.("Location services are disabled")}addLog("error","device","Location services switched off","open watches got an error")}return t}function setConditions(e){const t=_model.CONDITIONS[e];if(!t)throw new Error(`Unknown conditions "${String(e)}". Use good, weak, no-signal or off.`);const n=override.services;const o=e==="good"||e==="weak"?t:{signal:t.signal,services:t.services};const r=commit({...override,...o});if(n&&!t.services){for(const s of Array.from(watches.values())){if(s.kind==="position")s.fail?.("Location services are disabled")}addLog("error","device","Location services switched off","open watches got an error")}return r}function stopRoute(){if(override.mode!=="route"||!override.route)return getLocationSnapshot();const e=currentPoint();return setPlace({latitude:e.latitude,longitude:e.longitude})}function useRealLocation(){return commit({...override,mode:"real",playing:false})}function moveToRegion(e,t,n){for(const o of tasks.values()){if(n&&o.name!==n)continue;const r=o.regions.find(a=>a.identifier===e);if(!r)continue;const s=(0,_geo.pointForRegion)(r,t,currentPoint());const i=regionLabel(r)??r.identifier;return setPlace({...s,label:t==="inside"?`At ${i}`:`Outside ${i}`})}throw new Error(`No geofence region "${e}" is being monitored.`)}function resetLocation(){const e=(0,_model.defaultOverride)();return commit({...e,place:override.place})}function updateLocationSettings(e){settings={persist:typeof e.persist==="boolean"?e.persist:settings.persist,showChip:typeof e.showChip==="boolean"?e.showChip:settings.showChip};save();notify();return getLocationSnapshot()}function getLocationSettings(){return settings}function clearLog(){log.length=0;notify();return getLocationSnapshot()}function getLocationSnapshot(){if(cached)return cached;const e=(0,_sharedUi.realNow)();const{fix:t,reason:n}=currentFix(e);let o=null;if(override.mode==="route"&&override.route){const i=(0,_geo.positionAlong)(override.route,metersAt(e));const a=(0,_geo.routeLength)(override.route.points);o={along:i.along,length:a,finished:i.finished,leg:i.leg,etaMs:override.playing&&!override.route.loop&&!i.finished?(a-i.along)/override.route.speed*1e3:null}}const r=(0,_model.isSimulatingPosition)(override)?currentPoint():null;const s=t??r;cached={active:(0,_model.isOverrideActive)(override),simulating:(0,_model.isSimulatingPosition)(override),override,current:{fix:t,reason:n,precision},permission,position:r?{latitude:r.latitude,longitude:r.longitude}:null,progress:o,watches:Array.from(watches.values()).map(i=>({key:i.key,library:i.library,id:i.id,kind:i.kind,options:i.options,since:i.since,updates:i.updates})),tasks:Array.from(tasks.values()).map(i=>({name:i.name,kind:i.kind,library:i.library,intercepted:i.intercepted,since:i.since,runs:i.runs,options:i.options,regions:i.regions.map(a=>({...a,label:regionLabel(a),state:i.states[a.identifier]??"unknown",distance:s?(0,_geo.distanceMeters)(a,s):null}))})),log:log.slice(-50),libraries:Array.from(adapters.keys()),places:appPlaces.slice(),routes:appRoutes.slice(),settings,lastDeliveryAt};return cached}function save(){if(!booted)return;const e={v:1,override:settings.persist&&(0,_model.isOverrideActive)(override)?override:null,settings,tasks:Array.from(tasks.values()).filter(t=>t.intercepted).map(({name:t,kind:n,library:o,options:r})=>({name:t,kind:n,library:o,options:r}))};void(0,_persistence.writeSaved)(e)}function apply(e){if(!e)return;settings=e.settings;for(const t of e.tasks){if(!tasks.has(t.name))trackTaskQuiet(t)}if(e.override&&(0,_model.isOverrideActive)(e.override)){override=e.override;wasActive=true}}function trackTaskQuiet(e){const t=e.kind==="geofencing"?(e.options.regions??[]).map((n,o)=>(0,_geo.toRegion)(n,o)).filter(n=>!!n):[];tasks.set(e.name,{...e,regions:t,states:{},since:(0,_sharedUi.realNow)(),runs:0,intercepted:true,lastBatchAt:null})}function bootLocation(){if(booted)return;booted=true;seed=Math.floor(Math.random()*1e3)+1;const e=(0,_persistence.readSavedSync)();if(e!==void 0){apply(e);afterRestore();return}void(0,_persistence.readSavedAsync)().then(t=>{apply(t);afterRestore()})}function afterRestore(){for(const e of adapters.values())e.onActiveChange?.(wasActive);if((0,_model.isSimulatingPosition)(override))realSetTimeout(kick,0);else notify()}function __resetForTests(){stopLoop();override=(0,_model.defaultOverride)();settings={..._model.DEFAULT_SETTINGS};precision="full";permission=null;booted=false;wasActive=false;adapters.clear();watches.clear();tasks.clear();log.length=0;appPlaces.length=0;appRoutes.length=0;lastDeliveryAt=null;cached=null}function __tickForTests(){tick()}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"BUILT_IN_PLACES",{enumerable:true,get:function(){return _fixtures.BUILT_IN_PLACES}});Object.defineProperty(exports,"LOCATION_CHIP_ID",{enumerable:true,get:function(){return _LocationChip.LOCATION_CHIP_ID}});Object.defineProperty(exports,"LOCATION_TOOL_ICON_COLOR",{enumerable:true,get:function(){return _sharedUi.LOCATION_TOOL_ICON_COLOR}});Object.defineProperty(exports,"LocationBody",{enumerable:true,get:function(){return _LocationBody.LocationBody}});Object.defineProperty(exports,"LocationChip",{enumerable:true,get:function(){return _LocationChip.LocationChip}});Object.defineProperty(exports,"LocationToolIcon",{enumerable:true,get:function(){return _sharedUi.LocationToolIcon}});Object.defineProperty(exports,"LocationToolView",{enumerable:true,get:function(){return _LocationToolView.LocationToolView}});Object.defineProperty(exports,"ROUTE_PRESETS",{enumerable:true,get:function(){return _fixtures.ROUTE_PRESETS}});Object.defineProperty(exports,"bearingDegrees",{enumerable:true,get:function(){return _geo.bearingDegrees}});Object.defineProperty(exports,"bootLocation",{enumerable:true,get:function(){return _store.bootLocation}});Object.defineProperty(exports,"buildPresetRoute",{enumerable:true,get:function(){return _fixtures.buildPresetRoute}});Object.defineProperty(exports,"createLocationTool",{enumerable:true,get:function(){return _preset.createLocationTool}});Object.defineProperty(exports,"destination",{enumerable:true,get:function(){return _geo.destination}});Object.defineProperty(exports,"distanceMeters",{enumerable:true,get:function(){return _geo.distanceMeters}});Object.defineProperty(exports,"getLocationSnapshot",{enumerable:true,get:function(){return _store.getLocationSnapshot}});Object.defineProperty(exports,"installLocationAdapters",{enumerable:true,get:function(){return _adapters.installLocationAdapters}});Object.defineProperty(exports,"isLocationActive",{enumerable:true,get:function(){return _store.isLocationActive}});Object.defineProperty(exports,"locationSyncAdapter",{enumerable:true,get:function(){return _locationSyncAdapter.locationSyncAdapter}});Object.defineProperty(exports,"locationToolPreset",{enumerable:true,get:function(){return _preset.locationToolPreset}});Object.defineProperty(exports,"moveToRegion",{enumerable:true,get:function(){return _store.moveToRegion}});Object.defineProperty(exports,"parseCoordinate",{enumerable:true,get:function(){return _geo.parseCoordinate}});Object.defineProperty(exports,"pauseRoute",{enumerable:true,get:function(){return _store.pauseRoute}});Object.defineProperty(exports,"refreshLocationPermission",{enumerable:true,get:function(){return _store.refreshLocationPermission}});Object.defineProperty(exports,"registerLocationPlaces",{enumerable:true,get:function(){return _store.registerLocationPlaces}});Object.defineProperty(exports,"registerLocationRoutes",{enumerable:true,get:function(){return _store.registerLocationRoutes}});Object.defineProperty(exports,"resetLocation",{enumerable:true,get:function(){return _store.resetLocation}});Object.defineProperty(exports,"resumeRoute",{enumerable:true,get:function(){return _store.resumeRoute}});Object.defineProperty(exports,"seekRoute",{enumerable:true,get:function(){return _store.seekRoute}});Object.defineProperty(exports,"setConditions",{enumerable:true,get:function(){return _store.setConditions}});Object.defineProperty(exports,"setPlace",{enumerable:true,get:function(){return _store.setPlace}});Object.defineProperty(exports,"setRouteSpeed",{enumerable:true,get:function(){return _store.setRouteSpeed}});Object.defineProperty(exports,"setServices",{enumerable:true,get:function(){return _store.setServices}});Object.defineProperty(exports,"setSignal",{enumerable:true,get:function(){return _store.setSignal}});Object.defineProperty(exports,"startRoute",{enumerable:true,get:function(){return _store.startRoute}});Object.defineProperty(exports,"stopRoute",{enumerable:true,get:function(){return _store.stopRoute}});Object.defineProperty(exports,"subscribeLocation",{enumerable:true,get:function(){return _store.subscribeLocation}});Object.defineProperty(exports,"tuneOverride",{enumerable:true,get:function(){return _store.tuneOverride}});Object.defineProperty(exports,"useRealLocation",{enumerable:true,get:function(){return _store.useRealLocation}});var _store=require("./engine/store");var _adapters=require("./engine/adapters");var _LocationChip=require("./components/LocationChip");var _preset=require("./preset");var _LocationBody=require("./components/LocationBody");var _LocationToolView=require("./components/LocationToolView");var _sharedUi=require("@buoy-gg/shared-ui");var _locationSyncAdapter=require("./sync/locationSyncAdapter");var _fixtures=require("./engine/fixtures");var _geo=require("./engine/geo");const isReactNativeRuntime=typeof navigator!=="undefined"&&navigator.product==="ReactNative";if(isReactNativeRuntime){(0,_LocationChip.watchLocationChip)();if(typeof __DEV__!=="undefined"&&__DEV__){(0,_adapters.installLocationAdapters)();(0,_store.bootLocation)()}}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.locationToolPreset=exports.createLocationTool=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _LocationBody=require("./components/LocationBody");var _jsxRuntime=require("react/jsx-runtime");const locationToolPreset=exports.locationToolPreset=(0,_sharedUi.defineToolPreset)({id:"location",name:"LOCATION",description:"Pin the app anywhere, play routes, trigger geofences",slot:"both",color:_sharedUi.LOCATION_TOOL_ICON_COLOR,icon:({size:o,color:e})=>(0,_jsxRuntime.jsx)(_sharedUi.LocationToolIcon,{size:o,color:e}),component:_LocationBody.LocationBody,modal:{subtitle:"simulate where the app is"}});const createLocationTool=exports.createLocationTool=(0,_sharedUi.createToolFactory)(locationToolPreset);
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.locationSyncAdapter=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _store=require("../engine/store");var _geo=require("../engine/geo");var _fixtures=require("../engine/fixtures");function obj(t){return t&&typeof t==="object"?t:{}}function boolParam(t,...e){for(const o of e){const n=t[o];if(typeof n==="boolean")return n;if(n==="true"||n==="on")return true;if(n==="false"||n==="off")return false}return void 0}function numParam(t,...e){for(const o of e){const n=t[o];if(n===void 0||n===null||n==="")continue;const i=Number(n);if(Number.isFinite(i))return i}return void 0}function snapshot(){return{...(0,_store.getLocationSnapshot)(),builtInPlaces:_fixtures.BUILT_IN_PLACES,presets:_fixtures.ROUTE_PRESETS}}function findPlace(t){const e=t.trim().toLowerCase();const o=[...(0,_store.getLocationSnapshot)().places,..._fixtures.BUILT_IN_PLACES];return o.find(n=>n.label?.toLowerCase()===e)??o.find(n=>n.label?.toLowerCase().includes(e))??null}function placeParam(t){const e=typeof t.label==="string"?t.label:void 0;const o=numParam(t,"latitude","lat");const n=numParam(t,"longitude","lon","lng");if(o!==void 0&&n!==void 0){const i={latitude:o,longitude:n};if(!(0,_geo.isCoordinate)(i))throw new Error("latitude must be within \xB190 and longitude within \xB1180.");return{...i,label:e}}for(const i of["place","to","query","coordinate","at"]){const r=t[i];if((0,_geo.isCoordinate)(r))return{...r,label:r.label??e};if(typeof r==="string"&&r.trim()){const a=(0,_geo.parseCoordinate)(r);if(a)return{...a,label:e};const u=findPlace(r);if(u)return u;throw new Error(`No place called "${r}". Give latitude and longitude, or one of: ${placeNames()}.`)}}return null}function placeNames(){return[...(0,_store.getLocationSnapshot)().places,..._fixtures.BUILT_IN_PLACES].map(t=>t.label).filter(Boolean).join(", ")}function routeParam(t){const e=numParam(t,"speed","metersPerSecond");const o=numParam(t,"heading","bearing")??0;if(Array.isArray(t.points)){return{points:t.points,speed:e??1.4,loop:boolParam(t,"loop")??false,name:typeof t.name==="string"?t.name:"Custom route",gaps:Array.isArray(t.gaps)?t.gaps:void 0}}const n=typeof t.route==="string"?t.route:typeof t.routeId==="string"?t.routeId:typeof t.preset==="string"?t.preset:void 0;if(n){const r=(0,_store.getLocationSnapshot)().routes.find(s=>s.id===n||s.name?.toLowerCase()===n.toLowerCase());if(r)return e?{...r,speed:e}:r;const a=_fixtures.ROUTE_PRESETS.find(s=>s.id===n||s.name.toLowerCase()===n.toLowerCase());if(a){const s=(0,_fixtures.buildPresetRoute)(a.id,(0,_store.currentPoint)(),o);return e?{...s,speed:e}:s}const u=[...(0,_store.getLocationSnapshot)().routes.map(s=>s.id??s.name),..._fixtures.ROUTE_PRESETS.map(s=>s.id)];throw new Error(`No route "${n}". Use one of: ${u.join(", ")}; or pass points.`)}const i=placeParam(t);if(i)return(0,_fixtures.lineRoute)((0,_store.currentPoint)(),i,e??1.4);throw new Error("startRoute needs `points` (two or more {latitude, longitude}), `route` (a preset or app route id), or `to` (a place).")}const locationSyncAdapter=exports.locationSyncAdapter=(0,_sharedUi.createSyncAdapter)({version:1,getSnapshot(){return snapshot()},subscribe(t){return(0,_store.subscribeLocation)(t)},actions:{getState(){return snapshot()},setLocation(t){const e=placeParam(obj(t));if(!e){throw new Error('setLocation needs `latitude` and `longitude`, `query` ("lat, lon" or a map link), or `place` (a place name).')}(0,_store.setPlace)(e);return snapshot()},startRoute(t){(0,_store.startRoute)(routeParam(obj(t)));return snapshot()},stopRoute(){(0,_store.stopRoute)();return snapshot()},setConditions(t){const e=obj(t);const o=typeof e.conditions==="string"?e.conditions:typeof e.preset==="string"?e.preset:"";const n=o.trim().toLowerCase().replace(/[\s_]+/g,"-");const i={good:"good",weak:"weak","no-signal":"no-signal",nosignal:"no-signal",off:"off","services-off":"off","location-off":"off"};const r=i[n];if(!r)throw new Error("setConditions needs `conditions`: good, weak, no-signal or off.");(0,_store.setConditions)(r);return snapshot()},pauseRoute(){(0,_store.pauseRoute)();return snapshot()},resumeRoute(){(0,_store.resumeRoute)();return snapshot()},seekRoute(t){const e=obj(t);const o=numParam(e,"meters","along");const n=numParam(e,"fraction","progress");const i=(0,_store.getLocationSnapshot)().progress?.length??0;if(o===void 0&&n===void 0)throw new Error("seekRoute needs `meters` or `fraction` (0 to 1).");(0,_store.seekRoute)(o??(n??0)*i);return snapshot()},setSpeed(t){const e=numParam(obj(t),"speed","metersPerSecond");if(e===void 0)throw new Error("setSpeed needs `speed` in meters per second.");(0,_store.setRouteSpeed)(e);return snapshot()},tune(t){const e=obj(t);(0,_store.tuneOverride)({accuracy:numParam(e,"accuracy"),jitter:numParam(e,"jitter","drift"),altitude:e.altitude===null?null:numParam(e,"altitude"),heading:e.heading===null?null:numParam(e,"heading"),interval:numParam(e,"interval","intervalMs")});return snapshot()},setSignal(t){const e=boolParam(obj(t),"on","signal","enabled");if(e===void 0)throw new Error("setSignal needs `on`: true or false.");(0,_store.setSignal)(e);return snapshot()},setServices(t){const e=boolParam(obj(t),"on","services","enabled");if(e===void 0)throw new Error("setServices needs `on`: true or false.");(0,_store.setServices)(e);return snapshot()},enterRegion(t){const e=obj(t);const o=typeof e.identifier==="string"?e.identifier:typeof e.region==="string"?e.region:void 0;if(!o)throw new Error("enterRegion needs `identifier` (a monitored geofence region).");(0,_store.moveToRegion)(o,"inside",typeof e.task==="string"?e.task:void 0);return snapshot()},exitRegion(t){const e=obj(t);const o=typeof e.identifier==="string"?e.identifier:typeof e.region==="string"?e.region:void 0;if(!o)throw new Error("exitRegion needs `identifier` (a monitored geofence region).");(0,_store.moveToRegion)(o,"outside",typeof e.task==="string"?e.task:void 0);return snapshot()},useRealLocation(){(0,_store.useRealLocation)();return snapshot()},reset(){(0,_store.resetLocation)();return snapshot()},updateSettings(t){const e=obj(t);(0,_store.updateLocationSettings)({persist:boolParam(e,"persist"),showChip:boolParam(e,"showChip")});return snapshot()},clearLog(){(0,_store.clearLog)();return snapshot()}}});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as m,useState as f}from"react";import{FeatureGate as p}from"@buoy-gg/shared-ui";import{bootLocation as u,refreshLocationPermission as e,subscribeLocation as l}from"../engine/store";import{installLocationAdapters as L}from"../engine/adapters";import{locationSyncAdapter as s}from"../sync/locationSyncAdapter";import{setLocationToolOpen as i}from"./LocationChip";import{LocationToolView as h}from"./LocationToolView";import{jsx as a}from"react/jsx-runtime";const S=s.actions;async function b(o,t){const n=S[o];if(!n)throw new Error(`Unknown location action: ${o}`);return n(t)}const r=()=>s.getSnapshot();const d=2e3;export function LocationBody(){const[o,t]=f(r);m(()=>{L();u();t(r());i(true);e();const n=setInterval(e,d);const c=l(()=>t(r()));return()=>{clearInterval(n);c();i(false)}},[]);return a(p,{featureName:"Location",children:a(h,{snapshot:o,onAction:b})})}
@@ -0,0 +1 @@
1
+ "use strict";import{useSyncExternalStore as S}from"react";import{StyleSheet as u,Text as f,TouchableOpacity as g,View as c}from"react-native";import{FloatingTool as w,LocationToolIcon as m,Pause as C,Play as I,RefreshCw as T,X as R,dismissFloatingTool as z,getFloatingTools as O,night as i,openFloatingTool as P}from"@buoy-gg/shared-ui";import{getLocationSettings as j,getLocationSnapshot as a,pauseRoute as v,resetLocation as D,resumeRoute as F,subscribeLocation as y}from"../engine/store";import{chipLine as W,titleLine as k}from"./format";import{jsx as t,jsxs as b}from"react/jsx-runtime";export const LOCATION_CHIP_ID="location-chip";const _={id:LOCATION_CHIP_ID,render:e=>t(LocationChip,{...e})};const V=()=>O().some(e=>e.id===LOCATION_CHIP_ID);let x=false;let h=false;let L=null;export function setLocationToolOpen(e){if(h===e)return;h=e;L?.()}export function watchLocationChip(){if(x)return;x=true;let e=false;const r=()=>{const o=a().active&&j().showChip&&!h;if(o&&!e)P(_);else if(!o&&V())z(LOCATION_CHIP_ID);e=o};L=r;y(r);r()}export function LocationChip({id:e,revealToken:r}){const o=S(y,a,a);const d=k(o);const l=o.override.mode==="route"&&o.progress;const s=o.override.playing;const p=!!l&&l.finished;return t(w,{id:e,revealToken:r,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the location chip. ${d}`,handleAdornment:t(m,{size:12}),children:b(c,{style:n.row,children:[t(m,{size:18}),b(c,{style:n.text,children:[t(f,{style:n.title,numberOfLines:1,testID:"location-chip-title",children:d}),t(f,{style:n.detail,numberOfLines:1,testID:"location-chip-detail",children:W(o)})]}),l?t(g,{testID:"location-chip-playpause",accessibilityRole:"button",accessibilityLabel:s?"Pause the route":p?"Play the route again":"Resume the route",onPress:()=>s?v():F(),style:n.pill,hitSlop:{top:8,bottom:8,left:4,right:4},children:s?t(C,{size:14,color:i.color.accent}):p?t(T,{size:14,color:i.color.accent}):t(I,{size:14,color:i.color.accent})}):null,t(c,{style:n.separator}),t(g,{testID:"location-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to the real location",onPress:()=>D(),style:n.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:t(R,{size:16,color:i.color.textSecondary})})]})})}const n=u.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:230,maxWidth:340},text:{flexShrink:1,minWidth:120},title:{color:i.color.text,fontSize:14,fontWeight:"600"},detail:{color:i.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},pill:{width:30,height:30,borderRadius:15,alignItems:"center",justifyContent:"center",backgroundColor:i.color.accentFill},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:u.hairlineWidth,height:20,backgroundColor:i.color.separator}});
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as q,useState as I}from"react";import{ScrollView as Y,StyleSheet as A,Text as p,TextInput as J,TouchableOpacity as P,View as u}from"react-native";import{Check as Q,ChevronLeft as X,ChevronRight as Z,NightButton as B,NightCard as y,NightFootnote as T,NightRows as x,NightSectionLabel as w,NightSegmented as O,NightSwitch as ee,Pause as te,Play as ne,RefreshCw as oe,copyToClipboard as ie,monoFont as re,night as l,realNow as W,useSafeAreaInsets as le,useToolScreenHeader as ae}from"@buoy-gg/shared-ui";import{distanceMeters as H,parseCoordinate as ce,routeLength as se}from"../engine/geo";import{currentConditions as de}from"../engine/model";import{formatAccuracy as ue,formatCoordinate as $,formatDistance as C,formatSpeed as M,formatWhen as he,permissionLine as ge,stateLine as fe,titleLine as pe,titleTone as ye}from"./format";import{SchematicMap as me}from"./SchematicMap";import{jsx as e,Fragment as D,jsxs as s}from"react/jsx-runtime";const F={places:"Other Location",routes:"Route",speed:"Speed",accuracy:"Accuracy & Drift",activity:"Activity",options:"Options"};const be="#F87171";const V=[{key:"1.4",label:"Walking"},{key:"3.3",label:"Running"},{key:"5.5",label:"Cycling"},{key:"13.4",label:"City Traffic"},{key:"30",label:"Highway"},{key:"250",label:"Airplane"}];const j=[{key:"good",label:"Good"},{key:"weak",label:"Weak"},{key:"no-signal",label:"No Signal"},{key:"off",label:"Off"}];const we={good:"Precise fixes, like outdoors with a clear sky.",weak:"Fixes are \xB165 m and wander by up to 50 m, like indoors or between tall buildings.","no-signal":"Watches get no updates and location requests fail.",off:"The app is told location services are turned off.",custom:"Custom accuracy and drift."};const _=[{key:"5",label:"5 m"},{key:"20",label:"20 m"},{key:"65",label:"65 m"},{key:"1000",label:"1 km"}];const G=[{key:"0",label:"Off"},{key:"10",label:"10 m"},{key:"50",label:"50 m"},{key:"200",label:"200 m"}];const ke=4;function E(t){const[o,n]=I(()=>W());q(()=>{if(!t)return void 0;const i=setInterval(()=>n(W()),1e3);return()=>clearInterval(i)},[t]);return o}export function LocationToolView({snapshot:t,onAction:o}){const n=le({minBottom:16});const[i,r]=I(null);const[d,g]=I("main");const h=()=>g("main");const c=ae(d==="main"?null:{title:F[d],subtitle:"",onBack:h,searchable:false},[d]);const f=(S,z)=>{r(null);o(S,z).catch(N=>{r(N instanceof Error?N.message:String(N))})};if(!t){return e(u,{style:a.waiting,testID:"location-waiting",children:e(T,{centered:true,children:"Waiting for the app\u2026"})})}const k=i?e(T,{tone:"danger",centered:true,children:e(p,{testID:"location-error",children:i})}):null;const v=(S,z)=>{f(S,z);h()};let b;switch(d){case"places":b=e(Ce,{snapshot:t,pick:v});break;case"routes":b=e(Re,{snapshot:t,pick:v});break;case"speed":b=e(ze,{snapshot:t,pick:v});break;case"accuracy":b=e(Ee,{snapshot:t,run:f});break;case"activity":b=e(He,{snapshot:t,run:f});break;case"options":b=e(Ve,{snapshot:t,run:f});break;default:b=s(D,{children:[e(Te,{snapshot:t,run:f}),k,e(ve,{snapshot:t,run:f}),e(Se,{snapshot:t,run:f,open:g}),e(Pe,{snapshot:t,open:g}),e(Ae,{snapshot:t,run:f}),e(Me,{snapshot:t,run:f,open:g}),e(Be,{snapshot:t,open:g})]})}return s(Y,{style:a.fill,contentContainerStyle:[a.content,{paddingBottom:n.bottom}],testID:"location-scroll",keyboardShouldPersistTaps:"handled",children:[d!=="main"&&!c?e(je,{title:F[d],onBack:h}):null,d!=="main"?k:null,b]},d)}function Te({snapshot:t,run:o}){const n=t.override;const i=n.mode==="route"?n.route:null;const r=t.progress;E(!!i&&n.playing);const d=ye(t);const g=t.current.fix;const h=r&&r.length>0?Math.min(1,r.along/r.length):0;const[c,f]=I(false);return s(y,{children:[s(u,{style:a.status,children:[e(p,{style:[a.statusTitle,d==="simulated"?a.titleSimulated:d==="broken"?a.titleBroken:null],testID:"location-hero-title",numberOfLines:1,adjustsFontSizeToFit:true,children:pe(t)}),e(p,{style:a.statusLine,testID:"location-hero-status",children:fe(t)}),g&&t.simulating?e(P,{testID:"location-copy-coordinates",accessibilityRole:"button",accessibilityLabel:"Copy coordinates",activeOpacity:.6,onPress:()=>{void ie(`${g.latitude}, ${g.longitude}`).then(k=>{if(!k)return;f(true);setTimeout(()=>f(false),1500)})},children:e(p,{style:a.coordinates,children:c?"Copied":$(g,5)})}):null,i&&r?s(u,{style:a.progressTrack,testID:"location-route-progress",children:[e(u,{style:[a.progressFill,{width:`${h*100}%`}]}),(i.gaps??[]).map(([k,v],b)=>e(u,{style:[a.progressGap,{left:`${k/r.length*100}%`,width:`${(v-k)/r.length*100}%`}]},b))]}):null,t.active?s(u,{style:a.statusButtons,children:[i&&r?e(xe,{testID:n.playing?"location-route-pause":"location-route-resume",label:n.playing?"Pause":r.finished?"Play again":"Resume",onPress:()=>o(n.playing?"pauseRoute":"resumeRoute"),children:n.playing?e(te,{size:18,color:l.color.onAccent}):r.finished?e(oe,{size:18,color:l.color.onAccent}):e(ne,{size:18,color:l.color.onAccent})}):null,e(u,{style:a.flex,children:e(B,{label:"Use Real Location",size:"md",testID:"location-reset",onPress:()=>o("reset")})})]}):null]}),t.permission?s(u,{style:a.permission,testID:"location-permission",children:[s(u,{style:a.rowBetween,children:[e(p,{style:a.rowTitle,children:"Permission"}),e(p,{style:[a.rowValue,t.permission.status!=="granted"?a.valueWarning:null],testID:"location-permission-value",children:ge(t.permission)})]}),t.permission.status!=="granted"?e(p,{style:a.detail,children:"The app's location requests fail until it's allowed. Change it in Settings or the Permissions tool."}):null]}):null]})}function xe({children:t,label:o,onPress:n,testID:i}){return e(P,{testID:i,accessibilityRole:"button",accessibilityLabel:o,activeOpacity:.7,onPress:n,style:a.round,children:t})}function ve({snapshot:t,run:o}){const n=!!t.position||t.places.length>0||t.tasks.some(i=>i.regions.length>0);if(!n)return null;return s(u,{children:[e(me,{snapshot:t,onPinPlace:i=>o("setLocation",{latitude:i.latitude,longitude:i.longitude,label:i.label}),onCrossRegion:(i,r)=>o(r.state==="inside"?"exitRegion":"enterRegion",{identifier:r.identifier,task:i.name})}),e(T,{children:"Map views in the app still show the device's own blue dot. Move the simulator's location for those."})]})}function Se({snapshot:t,run:o,open:n}){const i=t.places.length>0;const r=i?t.places:t.builtInPlaces.slice(0,ke);const d=t.override.mode==="fixed"?t.override.place:null;const g=t.position;const h=!!d&&!r.some(c=>R(c,d));return s(u,{children:[e(w,{children:"Location"}),e(y,{children:s(x,{children:[r.map((c,f)=>e(m,{title:c.label??$(c,4),value:g&&!(d&&R(c,d))?Ie(g,c):void 0,checked:!!d&&R(c,d),testID:`location-place-${L(c.label??String(f))}`,onPress:()=>o("setLocation",{latitude:c.latitude,longitude:c.longitude,label:c.label})},`${c.label??f}`)),e(m,{title:"Other Location\u2026",value:h?d.label||$(d,3):void 0,chevron:true,testID:"location-other",onPress:()=>n("places")},"other")]})})]})}function Ie(t,o){const n=H(t,o);return n<30?"Here":C(n)}function R(t,o){if(t.label&&o.label)return t.label===o.label;return H(t,o)<1}function Ce({snapshot:t,pick:o}){const[n,i]=I("");const r=ce(n);const d=t.override.mode==="fixed"?t.override.place:null;const g=()=>{if(!r)return;o("setLocation",{query:n});i("")};return s(D,{children:[s(u,{children:[e(w,{children:"Coordinates"}),e(y,{children:s(u,{style:a.editor,children:[s(u,{style:a.inputRow,children:[e(J,{value:n,onChangeText:i,placeholder:"Coordinates or a Maps link",placeholderTextColor:l.color.placeholder,autoCapitalize:"none",autoCorrect:false,style:a.input,testID:"location-coordinate-input",accessibilityLabel:"Coordinates or a Maps link",returnKeyType:"done",onSubmitEditing:g}),e(B,{label:"Pin",size:"md",variant:"primary",disabled:!r,testID:"location-coordinate-set",onPress:g})]}),n.length>0?e(p,{style:r?a.detail:a.warning,testID:"location-coordinate-preview",children:r?De(r):"Type a latitude and longitude, like 40.7580, -73.9855, or paste a Google or Apple Maps link."}):null]})})]}),s(u,{children:[e(w,{children:"Places"}),e(y,{children:e(x,{children:t.builtInPlaces.map((h,c)=>e(m,{title:h.label??$(h,4),detail:h.label==="Null Island"?"0, 0: catches code that treats 0 as no location":void 0,checked:!!d&&R(h,d),testID:`location-place-${L(h.label??String(c))}`,onPress:()=>o("setLocation",{latitude:h.latitude,longitude:h.longitude,label:h.label})},`${h.label??c}`))})}),t.places.length===0?e(T,{children:"Add your own places, such as your stores, with registerLocationPlaces()."}):null]})]})}function De(t){const o=`${Math.abs(t.latitude).toFixed(4)}\xB0 ${t.latitude>=0?"N":"S"}`;const n=`${Math.abs(t.longitude).toFixed(4)}\xB0 ${t.longitude>=0?"E":"W"}`;return`${o}, ${n}`}function Pe({snapshot:t,open:o}){const n=t.override.mode==="route"?t.override.route:null;return s(u,{children:[e(w,{children:"Movement"}),e(y,{children:s(x,{children:[e(m,{title:"Route",value:n?.name??"None",chevron:true,testID:"location-route",onPress:()=>o("routes")},"route"),n?e(m,{title:"Speed",value:$e(n.speed),chevron:true,testID:"location-speed",onPress:()=>o("speed")},"speed"):null]})})]})}function $e(t){const o=V.find(n=>Math.abs(Number(n.key)-t)<.05);return o?o.label:M(t)}function Re({snapshot:t,pick:o}){const n=t.override.mode==="route"?t.override.route:null;const i=n?.id;return s(D,{children:[n?e(u,{children:e(y,{children:e(x,{children:e(m,{title:"Stop Here",detail:"End the route and stay where it got to",testID:"location-route-stop",onPress:()=>o("stopRoute")},"stop")})})}):null,t.routes.length>0?s(u,{children:[e(w,{children:"This App"}),e(y,{children:e(x,{children:t.routes.map((r,d)=>e(m,{title:r.name??r.id??`Route ${d+1}`,detail:`${C(se(r.points))} at ${M(r.speed)}${r.loop?", on repeat":""}`,checked:!!i&&i===r.id,testID:`location-route-${L(r.id??r.name??String(d))}`,onPress:()=>o("startRoute",{route:r.id??r.name})},r.id??`${r.name}-${d}`))})})]}):null,s(u,{children:[e(w,{children:"From Here"}),e(y,{children:e(x,{children:t.presets.map(r=>e(m,{title:r.name,detail:Le(r.id)??r.description,checked:i===`preset:${r.id}`,testID:`location-preset-${r.id}`,onPress:()=>o("startRoute",{route:r.id})},r.id))})}),e(T,{children:"These start where the app is now."})]})]})}function Le(t){const o=C;switch(t){case"walk":return`${o(1e3)} north at walking pace`;case"run":return`${o(3e3)} north, then east, at running pace`;case"drive":return`${o(4e3)} of city streets with turns`;case"highway":return`${o(3e4)} north at highway speed`;case"tunnel":return`${o(3e3)} drive with no signal for ${o(600)} in the middle`;case"loop":return`A ${o(400)} block, walked on repeat`;default:return null}}function ze({snapshot:t,pick:o}){const n=t.override.route?.speed??0;return s(u,{children:[e(y,{children:e(x,{children:V.map(i=>e(m,{title:i.label,value:M(Number(i.key)),checked:Math.abs(Number(i.key)-n)<.05,testID:`location-speed-${i.key}`,onPress:()=>o("setSpeed",{speed:Number(i.key)})},i.key))})}),e(T,{children:"Heading and speed follow the route."})]})}const Ne=1e4;function Ae({snapshot:t,run:o}){const n=t.tasks.filter(c=>c.kind==="geofencing"&&c.regions.length>0);const[i,r]=I(null);const d=E(!!i);if(n.length===0)return null;const g=n.length>1;const h=n.map(c=>c.name).join(", ");return s(u,{children:[e(w,{children:"Geofences"}),e(y,{children:e(x,{children:n.flatMap(c=>c.regions.map(f=>{const k=`${c.name}:${f.identifier}`;const v=f.state==="inside";const b=i?.key===k&&d-i.at<Ne?i:null;const S=[Oe(f)];if(g)S.push(c.name);return e(m,{title:f.label??f.identifier,detail:S.join(" \xB7 "),note:b?We(t,c,b.at):void 0,action:v?"Leave":"Enter",testID:`location-region-${L(f.identifier)}`,onPress:()=>{r({key:k,at:W()});o(v?"exitRegion":"enterRegion",{identifier:f.identifier,task:c.name})}},k)}))})}),s(T,{children:["Tap a region to cross its edge. ",g?"The app's tasks":`The app's ${h} task`," runs as it would from the OS."]})]})}function Oe(t){if(t.state==="inside")return"Inside";if(t.distance==null)return`${C(t.radius)} radius`;return`${C(Math.max(0,t.distance-t.radius))} away`}function We(t,o,n){const i=t.log.filter(h=>h.at>=n-50&&(h.detail??"").startsWith(o.name));const r=i.find(h=>h.kind==="error");if(r)return{text:`Task failed: ${r.detail?.slice(o.name.length+3)??""}`,tone:"bad"};const d=i.find(h=>h.kind==="task");if(d)return{text:"Task ran",tone:"ok"};const g=i.find(h=>h.kind==="enter"||h.kind==="exit");if(!g)return{text:"Already on this side",tone:"wait"};return{text:"Running the app's task\u2026",tone:"wait"}}function Me({snapshot:t,run:o,open:n}){const i=t.override;const r=de(i);const d=t.simulating?j:j.filter(g=>g.key!=="weak");return s(u,{children:[e(w,{children:"Conditions"}),s(y,{children:[e(u,{style:a.segmentWrap,children:e(O,{tabs:d,activeKey:r??"",size:"sm",testIDPrefix:"location-conditions",onChange:g=>o("setConditions",{conditions:g})})}),t.simulating&&i.services&&i.signal?e(u,{style:a.separatorTop,children:e(m,{title:"Accuracy & Drift",value:`${ue(i.accuracy)}${i.jitter>0?` \xB7 drifts ${C(i.jitter)}`:""}`,chevron:true,testID:"location-accuracy",onPress:()=>n("accuracy")})}):null]}),e(T,{children:we[r??"custom"]})]})}function Ee({snapshot:t,run:o}){const n=t.override;return s(D,{children:[s(u,{children:[e(w,{children:"Accuracy"}),e(y,{children:e(u,{style:a.segmentWrap,children:e(O,{tabs:_,activeKey:U(_,n.accuracy)??"",size:"sm",testIDPrefix:"location-accuracy",onChange:i=>o("tune",{accuracy:Number(i)})})})}),e(T,{children:"The accuracy radius the app is given with each fix."})]}),s(u,{children:[e(w,{children:"Drift"}),e(y,{children:e(u,{style:a.segmentWrap,children:e(O,{tabs:G,activeKey:U(G,n.jitter)??"0",size:"sm",testIDPrefix:"location-drift",onChange:i=>o("tune",{jitter:Number(i)})})})}),e(T,{children:"Moves each fix by up to this much at random, the way a real fix wanders."})]})]})}function Be({snapshot:t,open:o}){const n=t.log.length;return e(u,{children:e(y,{children:s(x,{children:[e(m,{title:"Activity",value:n===0?"None":`${n} ${n===1?"event":"events"}`,chevron:true,testID:"location-activity",onPress:()=>o("activity")},"activity"),e(m,{title:"Options",chevron:true,testID:"location-options",onPress:()=>o("options")},"options")]})})})}function He({snapshot:t,run:o}){const n=E(true);const i=t.log.slice().reverse();const r=t.watches.filter(c=>c.kind==="position").length;const d=t.tasks.filter(c=>c.kind==="locationUpdates").length;const g=t.tasks.filter(c=>c.kind==="geofencing").reduce((c,f)=>c+f.regions.length,0);const h=[r?`${r} location ${r===1?"watch":"watches"}`:null,g?`${g} ${g===1?"geofence":"geofences"}`:null,d?"background updates":null].filter(Boolean);return s(D,{children:[s(u,{children:[e(w,{children:"The App Is Using"}),e(y,{children:s(u,{style:a.editor,children:[e(p,{style:a.rowTitle,testID:"location-activity-summary",children:h.length?h.join(", "):"Nothing right now"}),e(p,{style:a.detail,children:t.libraries.length?`Through ${t.libraries.join(" and ")}.`:"No supported location library was found in this app."})]})})]}),s(u,{children:[e(w,{children:"Recent"}),e(y,{children:s(x,{children:[i.length===0?e(u,{style:a.editor,children:e(p,{style:a.detail,children:"Location requests, watches and geofence crossings show up here."})},"empty"):i.map(c=>s(u,{style:a.logRow,testID:"location-log-entry",children:[e(u,{style:[a.logDot,Fe(c.kind)]}),s(u,{style:a.flex,children:[e(p,{style:a.logText,children:c.text}),c.detail?e(p,{style:a.logDetail,numberOfLines:2,children:c.detail}):null]}),e(p,{style:a.logWhen,children:he(c.at,n)})]},c.id)),i.length>0?e(m,{title:"Clear",tint:true,testID:"location-clear-log",onPress:()=>o("clearLog")},"clear"):null]})})]})]})}function Fe(t){if(t==="enter")return a.dotEnter;if(t==="exit")return a.dotExit;if(t==="error")return a.dotError;if(t==="task")return a.dotTask;return null}function Ve({snapshot:t,run:o}){return s(u,{children:[e(y,{children:s(x,{children:[e(K,{title:"Keep Across Reloads",value:t.settings.persist,testID:"location-setting-persist",onValueChange:n=>o("updateSettings",{persist:n})},"persist"),e(K,{title:"Show Floating Status",value:t.settings.showChip,testID:"location-setting-showChip",onValueChange:n=>o("updateSettings",{showChip:n})},"chip")]})}),e(T,{children:"The floating status stays on screen while the app is somewhere else, so a simulated location is never left on by accident."})]})}function je({title:t,onBack:o}){return s(P,{testID:"location-back",accessibilityRole:"button",accessibilityLabel:"Back",activeOpacity:.6,onPress:o,style:a.backRow,children:[e(X,{size:18,color:l.color.accent}),e(p,{style:a.backLabel,children:"Location"}),e(p,{style:a.backTitle,numberOfLines:1,children:t})]})}function m({title:t,detail:o,note:n,value:i,action:r,checked:d,chevron:g,tint:h,onPress:c,testID:f}){return s(P,{testID:f,accessibilityRole:"button",accessibilityLabel:r?`${r} ${t}`:t,accessibilityState:d?{selected:true}:void 0,activeOpacity:.6,onPress:c,style:a.row,children:[s(u,{style:a.rowText,children:[e(p,{style:[a.rowTitle,h?a.titleTint:null],numberOfLines:1,children:t}),o?e(p,{style:a.detail,children:o}):null,n?e(p,{style:[a.note,n.tone==="ok"?a.noteOk:n.tone==="bad"?a.noteBad:null],testID:`${f}-result`,children:n.text}):null]}),i?e(p,{style:a.rowValue,numberOfLines:1,children:i}):null,r?e(p,{style:a.rowAction,children:r}):null,d?e(Q,{size:18,color:l.color.accent}):null,g?e(Z,{size:16,color:l.color.textTertiary}):null]})}function K({title:t,value:o,onValueChange:n,testID:i}){return s(u,{style:a.row,children:[e(u,{style:a.rowText,children:e(p,{style:a.rowTitle,children:t})}),e(ee,{value:o,testID:i,accessibilityLabel:t,onValueChange:n})]})}function U(t,o){let n=null;let i=Infinity;for(const r of t){const d=Math.abs(Number(r.key)-o);if(d<i){n=r.key;i=d}}return n!==null&&i<=Math.max(.05,Number(n)*.05)?n:null}function L(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}const a=A.create({fill:{flex:1},flex:{flex:1},content:{paddingHorizontal:l.gutter,paddingTop:8,gap:l.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},status:{padding:l.cardPad+2,gap:6},statusTitle:{color:l.color.text,fontSize:28,fontWeight:"600"},titleSimulated:{color:l.color.accent},titleBroken:{color:be},statusLine:{color:l.color.textSecondary,fontSize:l.font.row,fontVariant:["tabular-nums"]},coordinates:{color:l.color.textTertiary,fontSize:l.font.caption,fontFamily:re},statusButtons:{flexDirection:"row",alignItems:"center",gap:10,marginTop:10},round:{width:44,height:44,borderRadius:22,alignItems:"center",justifyContent:"center",backgroundColor:l.color.accent},progressTrack:{height:6,borderRadius:3,marginTop:8,backgroundColor:l.color.fillSecondary,overflow:"hidden"},progressFill:{position:"absolute",left:0,top:0,bottom:0,backgroundColor:l.color.accent},progressGap:{position:"absolute",top:0,bottom:0,backgroundColor:"rgba(255, 255, 255, 0.28)"},permission:{borderTopWidth:A.hairlineWidth,borderTopColor:l.color.separator,paddingHorizontal:l.rowPadH,paddingVertical:12,gap:4},rowBetween:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12},valueWarning:{color:l.color.warning},row:{flexDirection:"row",alignItems:"center",gap:10,minHeight:48,paddingHorizontal:l.rowPadH,paddingVertical:10},rowText:{flex:1,gap:2},rowTitle:{color:l.color.text,fontSize:l.font.row},titleTint:{color:l.color.accent},rowValue:{color:l.color.textSecondary,fontSize:l.font.row,maxWidth:"50%"},rowAction:{color:l.color.accent,fontSize:l.font.row,fontWeight:"500"},detail:{color:l.color.textTertiary,fontSize:l.font.caption},note:{color:l.color.textSecondary,fontSize:l.font.caption,marginTop:2},noteOk:{color:l.color.accent},noteBad:{color:l.color.danger},warning:{color:l.color.warning,fontSize:l.font.caption},separatorTop:{borderTopWidth:A.hairlineWidth,borderTopColor:l.color.separator},segmentWrap:{flexDirection:"row",padding:10},editor:{paddingHorizontal:l.rowPadH,paddingVertical:14,gap:8},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:l.color.text,fontSize:l.font.body,backgroundColor:l.color.bg,borderRadius:l.radius.input,borderWidth:1,borderColor:l.color.border,paddingHorizontal:12,paddingVertical:9},backRow:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4},backLabel:{color:l.color.accent,fontSize:l.font.row},backTitle:{flex:1,color:l.color.text,fontSize:l.font.row,fontWeight:"600",textAlign:"center",marginRight:70},logRow:{flexDirection:"row",alignItems:"flex-start",gap:10,paddingHorizontal:l.rowPadH,paddingVertical:10},logDot:{width:8,height:8,borderRadius:4,marginTop:6,backgroundColor:l.color.textTertiary},dotEnter:{backgroundColor:l.color.accent},dotExit:{backgroundColor:l.color.warning},dotError:{backgroundColor:l.color.danger},dotTask:{backgroundColor:l.color.info},logText:{color:l.color.text,fontSize:l.font.body},logDetail:{color:l.color.textTertiary,fontSize:l.font.caption,marginTop:2},logWhen:{color:l.color.textTertiary,fontSize:l.font.caption,fontVariant:["tabular-nums"],marginTop:1}});
@@ -0,0 +1 @@
1
+ "use strict";import{StyleSheet as k,Text as v,TouchableOpacity as F,View as s}from"react-native";import{night as d}from"@buoy-gg/shared-ui";import{distanceMeters as V}from"../engine/geo";import{formatDistance as X,usesMiles as P}from"./format";import{jsx as c,jsxs as $}from"react/jsx-runtime";const j="#F87171";const x=1.8;const A=6e4;const q=400;export function SchematicMap({snapshot:e,onPinPlace:u,onCrossRegion:p}){const r=e.position;const a=e.override.mode==="route"?e.override.route:null;const l=r??e.places[0]??G(e.tasks)??null;if(!l)return null;const f=t=>!r||V(r,t)<=A;const w=e.places.filter(f);const _=e.tasks.filter(t=>t.kind==="geofencing").flatMap(t=>t.regions.filter(f).map(o=>({task:t,region:o})));const I=e.places.length-w.length;const z=Math.cos(l.latitude*Math.PI/180);const b=t=>({x:(t.longitude-l.longitude)*111320*z,y:(t.latitude-l.latitude)*110540});const g=[];if(r)g.push({...b(r),r:60});for(const t of a?.points??[])g.push({...b(t),r:0});for(const t of w)g.push({...b(t),r:60});for(const t of _)g.push({...b(t.region),r:t.region.radius});let C=Infinity;let M=-Infinity;let S=Infinity;let R=-Infinity;for(const t of g){C=Math.min(C,t.x-t.r);M=Math.max(M,t.x+t.r);S=Math.min(S,t.y-t.r);R=Math.max(R,t.y+t.r)}const N=(C+M)/2;const O=(S+R)/2;const E=Math.max(q,(R-S)*1.35,(M-C)*1.2/x);const L=E*x;const h=t=>{const o=b(t);return{x:.5+(o.x-N)/L,y:.5-(o.y-O)/E}};const T=K(L);const W=e.override.mode==="fixed"?e.override.place.label:void 0;return c(s,{children:$(s,{style:n.map,testID:"location-map",accessibilityLabel:"Map of places, geofences and the simulated position",children:[Y.map(t=>c(s,{style:[n.gridV,{left:i(t)}]},`v${t}`)),Y.map(t=>c(s,{style:[n.gridH,{top:i(t)}]},`h${t}`)),_.map(({task:t,region:o})=>{const m=h(o);const y=2*o.radius/L;const D=y*x;const H=o.state==="inside";return c(F,{testID:`location-map-region-${B(o.identifier)}`,accessibilityRole:"button",accessibilityLabel:`${H?"Leave":"Enter"} ${o.label??o.identifier}`,activeOpacity:.6,onPress:()=>p(t,o),style:[n.fence,H?n.fenceInside:null,{left:i(m.x-y/2),top:i(m.y-D/2),width:i(y),height:i(D)}]},`${t.name}:${o.identifier}`)}),a?J(a.points.map(h)).map((t,o)=>c(s,{pointerEvents:"none",style:[n.segment,{left:i(t.midX-t.length/2),top:i(t.midY),width:i(t.length),transform:[{rotate:`${t.angle}rad`}]}]},`seg${o}`)):null,w.map((t,o)=>{const m=h(t);const y=!!W&&W===t.label;return $(F,{testID:`location-map-place-${B(t.label??String(o))}`,accessibilityRole:"button",accessibilityLabel:`Pin ${t.label??"this place"}`,activeOpacity:.6,onPress:()=>u(t),style:[n.placeHit,{left:i(m.x),top:i(m.y)}],children:[c(s,{style:[n.placeDot,y?n.placeDotSelected:null]}),t.label?c(v,{style:n.placeLabel,numberOfLines:1,children:t.label}):null]},`${t.label??o}`)}),r?$(s,{pointerEvents:"none",style:[n.pinWrap,{left:i(h(r).x),top:i(h(r).y)}],children:[c(s,{style:n.pinHalo}),c(s,{style:[n.pin,e.current.reason==="gap"?n.pinHollow:null]})]}):null,$(s,{style:n.scale,pointerEvents:"none",children:[c(s,{style:[n.scaleBar,{width:i(T.fraction)}]}),c(v,{style:n.scaleLabel,children:T.label})]}),I>0?c(v,{style:n.offMap,pointerEvents:"none",children:`${I} more ${I===1?"place":"places"} off the map`}):null]})})}const Y=[.2,.4,.6,.8];function i(e){return`${e*100}%`}function G(e){for(const u of e)if(u.regions[0])return u.regions[0];return null}function J(e){const u=[];for(let p=1;p<e.length;p++){const r=e[p-1];const a=e[p];const l=a.x-r.x;const f=(a.y-r.y)/x;u.push({midX:(r.x+a.x)/2,midY:(r.y+a.y)/2,length:Math.sqrt(l*l+f*f),angle:Math.atan2(f,l)})}return u}function K(e){const u=e/4;const p=P()?1609.344:1e3;const r=P()?[.01,.02,.05,.1,.2,.5,1,2,5,10,20,50,100].map(l=>l*p):[10,20,50,100,200,500,1e3,2e3,5e3,1e4,2e4,5e4,1e5];let a=r[0];for(const l of r)if(l<=u)a=l;return{fraction:a/e,label:X(a)}}function B(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}const n=k.create({map:{width:"100%",aspectRatio:x,borderRadius:d.radius.card,borderWidth:1,borderColor:d.color.border,backgroundColor:d.color.surface,overflow:"hidden"},gridV:{position:"absolute",top:0,bottom:0,width:k.hairlineWidth,backgroundColor:"rgba(255, 255, 255, 0.04)"},gridH:{position:"absolute",left:0,right:0,height:k.hairlineWidth,backgroundColor:"rgba(255, 255, 255, 0.04)"},fence:{position:"absolute",borderRadius:9999,borderWidth:1,borderColor:"rgba(255, 255, 255, 0.22)",backgroundColor:"rgba(255, 255, 255, 0.04)",minWidth:10,minHeight:10},fenceInside:{borderColor:d.color.accentBorderStrong,backgroundColor:d.color.accentSoft},segment:{position:"absolute",height:3,marginTop:-1.5,borderRadius:1.5,backgroundColor:"rgba(248, 113, 113, 0.45)"},placeHit:{position:"absolute",flexDirection:"row",alignItems:"center",gap:4,height:24,marginTop:-12,marginLeft:-12,paddingLeft:8,paddingRight:4},placeDot:{width:8,height:8,borderRadius:4,backgroundColor:d.color.textSecondary},placeDotSelected:{backgroundColor:d.color.text},placeLabel:{color:d.color.textSecondary,fontSize:10,fontWeight:"500",maxWidth:110},pinWrap:{position:"absolute",width:28,height:28,marginLeft:-14,marginTop:-14,alignItems:"center",justifyContent:"center"},pinHalo:{position:"absolute",width:28,height:28,borderRadius:14,backgroundColor:"rgba(248, 113, 113, 0.22)"},pin:{width:14,height:14,borderRadius:7,backgroundColor:j,borderWidth:2,borderColor:"#FFFFFF"},pinHollow:{backgroundColor:"transparent",borderColor:j},scale:{position:"absolute",left:10,right:10,bottom:8,gap:3},scaleBar:{height:2,borderRadius:1,backgroundColor:d.color.textTertiary},scaleLabel:{color:d.color.textTertiary,fontSize:10,fontVariant:["tabular-nums"]},offMap:{position:"absolute",right:10,bottom:8,color:d.color.textTertiary,fontSize:10}});
@@ -0,0 +1 @@
1
+ "use strict";import{formatCoordinate as u}from"../engine/geo";export{u as formatCoordinate};const f=new Set(["US","GB","LR","MM"]);let i=null;export function setImperialUnits(e){i=e}function l(){try{const e=Intl.DateTimeFormat().resolvedOptions().locale;const r=/[-_]([A-Z]{2})\b/.exec(e);return r?r[1]:null}catch{return null}}let o=null;export function usesMiles(){if(i!==null)return i;if(o===null)o=f.has(l()??"");return o}const a=3.28084;const s=1609.344;export function formatDistance(e){if(!Number.isFinite(e))return"\u2013";const r=Math.abs(e);if(usesMiles()){const t=r/s;if(t<.1)return`${Math.round(r*a/10)*10} ft`;return`${c(t)} mi`}if(r<1e3)return`${Math.round(r)} m`;return`${c(r/1e3)} km`}function c(e){const r=Math.round(e*10)/10;return r<10?r.toFixed(1):Math.round(e).toLocaleString("en-US")}export function formatAccuracy(e){if(!Number.isFinite(e))return"\u2013";if(e>=1e3)return`\xB1${formatDistance(e)}`;return usesMiles()?`\xB1${Math.round(e*a)} ft`:`\xB1${Math.round(e)} m`}export function formatSpeed(e){if(e==null||e<0)return"\u2013";const r=usesMiles()?e*3600/s:e*3.6;const t=usesMiles()?"mph":"km/h";return`${r<10?r.toFixed(1):Math.round(r)} ${t}`}export function formatDuration(e){if(!Number.isFinite(e)||e<0)return"\u2013";const r=Math.round(e/6e4);if(r<1)return`${Math.max(1,Math.round(e/1e3))} sec`;if(r<60)return`${r} min`;const t=Math.floor(r/60);const n=r%60;return n?`${t} hr ${n} min`:`${t} hr`}export function formatWhen(e,r){const t=Math.max(0,Math.round((r-e)/1e3));if(t<5)return"now";if(t<60)return`${t}s ago`;try{return new Date(e).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}catch{const n=new Date(e);return`${n.getHours()}:${String(n.getMinutes()).padStart(2,"0")}`}}export function titleLine(e){if(!e.override.services)return"Location Services Off";if(!e.override.signal)return"No GPS Signal";if(e.override.mode==="real")return"Real Location";if(e.override.mode==="route")return e.override.route?.name??"Route";return e.override.place.label||"Dropped Pin"}export function titleTone(e){if(!e.override.services||!e.override.signal)return"broken";return e.override.mode==="real"?"real":"simulated"}export function stateLine(e){if(!e.override.services)return"The app is told location services are off";if(!e.override.signal)return"Updates stop and location requests fail";if(e.override.mode==="real")return"The app gets the device's location";const r=[];if(e.override.mode==="route"&&e.progress){const n=e.progress;if(n.finished)r.push("Arrived");else if(!e.override.playing)r.push("Paused");if(e.current.reason==="gap")r.push("no signal here");if(!n.finished){r.push(`${formatDistance(n.along)} of ${formatDistance(n.length)}`);if(n.etaMs!=null)r.push(`${formatDuration(n.etaMs)} left`);else if(e.override.route?.loop)r.push("on repeat")}}else{r.push("Pinned")}const t=e.current.fix;if(t&&e.override.mode==="fixed")r.push(formatAccuracy(t.accuracy));if(e.current.precision==="reduced")r.push("approximate");return r.join(" \xB7 ")}export function permissionLine(e){if(e.status==="denied")return"Not Allowed";if(e.status==="undetermined")return"Not Asked Yet";const r=e.background?"Always":"While Using";return`${r} \xB7 ${e.precision==="reduced"?"Approximate":"Precise"}`}export function chipLine(e){if(!e.override.services)return"The app is told location is off";if(!e.override.signal)return"Updates stop, requests fail";if(e.override.mode==="route"&&e.progress){if(e.progress.finished)return"Arrived";const t=`${formatDistance(e.progress.along)} of ${formatDistance(e.progress.length)}`;return e.override.playing?t:`Paused \xB7 ${t}`}const r=e.current.fix;return r?`Pinned \xB7 ${u(r,3)}`:"Pinned"}
@@ -0,0 +1 @@
1
+ "use strict";import{addLog as l,currentFix as E,isLocationActive as b,realSetTimeout as y,registerAdapter as C,servicesEnabled as M,trackWatch as O,untrackWatch as p}from"../store";import{wrapMethod as s}from"./wrap";import*as P from"react-native";export const COMMUNITY_MODULES=[{module:"RNCGeolocation",library:"@react-native-community/geolocation"},{module:"RNFusedLocation",library:"react-native-geolocation-service"}];const A={PERMISSION_DENIED:1,POSITION_UNAVAILABLE:2,TIMEOUT:3};function c(t,e){return{code:t,message:e,...A}}function g(){return P}function T(t){const e=g();if(!e)return null;let i=null;try{const a=globalThis.__turboModuleProxy!=null;if(a||typeof e.TurboModuleRegistry?.get==="function")i=e.TurboModuleRegistry?.get?.(t)}catch{i=null}if(!i){try{i=e.NativeModules?.[t]}catch{i=null}}return i&&typeof i==="object"?i:null}export function exportPosition(t,e,i){const a={coords:{latitude:t.latitude,longitude:t.longitude,altitude:t.altitude,accuracy:t.accuracy,altitudeAccuracy:t.altitudeAccuracy,heading:t.heading??(e==="ios"?-1:0),speed:t.speed??(e==="ios"?-1:0)},timestamp:i};if(e==="android")a.mocked=false;return a}const D=[];function I(t){const e=T(t.module);if(!e||typeof e.getCurrentPosition!=="function")return false;D.push(e);const i=g();const a=i?.Platform?.OS??"ios";const d=(r,n)=>i?.DeviceEventEmitter?.emit(r,n);const o={options:null,native:false,on:false};const f=()=>O({library:t.library,id:"observer",kind:"position",options:o.options??{},deliver:r=>d("geolocationDidChange",exportPosition(r,a,Date.now())),fail:r=>d("geolocationError",c(2,r))});s(e,"getCurrentPosition",r=>(...n)=>{if(!b())return r(...n);const N=n[1];const v=n[2];if(!M()){l("request",t.library,"getCurrentPosition \u2192 services off");v?.(c(2,"No location provider available."));return void 0}const{fix:u}=E();if(!u){l("request",t.library,"getCurrentPosition \u2192 no signal");y(()=>v?.(c(3,"Unable to fetch location within 1.0s.")),1e3);return void 0}l("request",t.library,`getCurrentPosition \u2192 ${u.latitude.toFixed(5)}, ${u.longitude.toFixed(5)}`);y(()=>N?.(exportPosition(u,a,Date.now())),0);return void 0});const m=s(e,"startObserving",r=>(...n)=>{o.options=n[0]&&typeof n[0]==="object"?n[0]:{};o.on=true;if(!b()){o.native=true;return r(...n)}o.native=false;f();return void 0});const h=s(e,"stopObserving",r=>(...n)=>{o.on=false;p(t.library,"position","observer");if(o.native){o.native=false;return r(...n)}return void 0});C({library:t.library,onActiveChange(r){if(!o.on)return;if(r&&o.native){o.native=false;h?.();f()}else if(!r&&!o.native){p(t.library,"position","observer");o.native=true;m?.(o.options??{})}}});return true}export function installCommunityAdapters(){return COMMUNITY_MODULES.filter(I).map(t=>t.library)}
@@ -0,0 +1,3 @@
1
+ "use strict";import{addLog as k,currentFix as D,getTask as v,getTasks as R,hasWatch as X,isLocationActive as f,notePrecision as J,realSetTimeout as I,registerAdapter as Q,servicesEnabled as w,setTaskIntercepted as x,trackTask as _,trackWatch as ee,untrackTask as L,untrackWatch as b}from"../store";import{codedError as te,wrapMethod as u}from"./wrap";import{isTaskDefined as ne,requireOptionalExpoModule as oe}from"./expoModulesCore";import*as M from"react-native";export const EXPO_LIBRARY="expo-location";function ie(){return M.Platform?.OS??"ios"}function B(c){try{const r=globalThis.expo?.modules;const a=r?.[c];if(a&&typeof a==="object")return a}catch{}const s=oe(c);return s&&typeof s==="object"?s:null}export function exportLocation(c,s,r){const a=s==="ios";const p={coords:{latitude:c.latitude,longitude:c.longitude,altitude:c.altitude??(a?0:null),accuracy:c.accuracy,altitudeAccuracy:c.altitudeAccuracy??(a?-1:null),heading:c.heading??(a?-1:null),speed:c.speed??(a?-1:null)},timestamp:r};if(s==="android")p.mocked=false;return p}function se(c,s,r){return r==="ios"?`Calling the '${c}' function has failed
2
+ \u2192 Caused by: ${s}`:`Call to function 'ExpoLocation.${c}' has been rejected.
3
+ \u2192 Caused by: ${s}`}const G={denied:{ios:{code:"ERR_DENIED_FOREGROUND_LOCATION_PERMISSION",reason:"Location permission is required to do this operation"},android:{code:"ERR_LOCATION_UNAUTHORIZED",reason:"Not authorized to use location services"}},deniedBackground:{ios:{code:"ERR_DENIED_BACKGROUND_LOCATION_PERMISSION",reason:"Background location permission is required to do this operation"},android:{code:"ERR_LOCATION_BACKGROUND_UNAUTHORIZED",reason:"Not authorized to use background location services"}},services:{ios:{code:"ERR_LOCATION_SERVICES_DISABLED",reason:"Location services are disabled"},android:{code:"ERR_LOCATION_SETTINGS_UNSATISFIED",reason:"Location request failed due to unsatisfied device settings"}},unavailable:{ios:{code:"ERR_LOCATION_UNAVAILABLE",reason:"Cannot obtain current location"},android:{code:"ERR_CURRENT_LOCATION_IS_UNAVAILABLE",reason:"Current location is unavailable. Make sure that location services are enabled"}}};function y(c,s,r){const a=r==="android"?G[c].android:G[c].ios;return Promise.reject(te(a.code,se(s,a.reason,r)))}let $=false;export function installExpoLocationAdapter(){const c=B("ExpoLocation");if(!c||typeof c.getCurrentPositionAsync!=="function")return false;const s=c;const r=B("ExpoTaskManager");const a=ie();const p=new Map;const d={};const T=()=>Date.now();const q=n=>e=>s.emit?.("Expo.locationChanged",{watchId:n,location:exportLocation(e,a,T())});const H=n=>e=>{const t=e.heading??0;s.emit?.("Expo.headingChanged",{watchId:n,heading:{trueHeading:t,magHeading:t,accuracy:3}})};const S=n=>e=>s.emit?.("Expo.locationError",{watchId:n,reason:e});async function m(){const n=s.getForegroundPermissionsAsync;const e={granted:true,status:"granted",precision:"full",reported:false};if(typeof n!=="function")return e;try{const t=await n.call(s);const o=t?.ios?.accuracy==="reduced"||t?.android?.accuracy==="coarse";const i=o?"reduced":"full";J(i);const l=t?.granted===true;const g=l?"granted":t?.status==="undetermined"?"undetermined":"denied";return{granted:l,status:g,precision:i,reported:true}}catch{return e}}async function F(){const n=s.getBackgroundPermissionsAsync;if(typeof n!=="function")return null;try{return(await n.call(s))?.granted===true}catch{return null}}async function j(){const n=s.getBackgroundPermissionsAsync;if(typeof n!=="function")return true;try{return(await n.call(s))?.granted===true}catch{return true}}function E(n,e){ee({library:EXPO_LIBRARY,id:n,kind:e.kind,options:e.options,deliver:e.kind==="position"?q(n):H(n),fail:S(n)})}d.getCurrentPositionAsync=u(s,"getCurrentPositionAsync",n=>async(...e)=>{if(!f())return n(...e);const t="getCurrentPositionAsync";if(!w()){k("request",EXPO_LIBRARY,"getCurrentPositionAsync \u2192 services off");return y("services",t,a)}const o=await m();if(!o.granted){k("request",EXPO_LIBRARY,"getCurrentPositionAsync \u2192 permission denied");return y("denied",t,a)}const{fix:i}=D();if(!i){k("request",EXPO_LIBRARY,"getCurrentPositionAsync \u2192 no signal");await new Promise(l=>I(()=>l(null),1e3));return y("unavailable",t,a)}k("request",EXPO_LIBRARY,`getCurrentPositionAsync \u2192 ${i.latitude.toFixed(5)}, ${i.longitude.toFixed(5)}`);return exportLocation(i,a,T())});d.getLastKnownPositionAsync=u(s,"getLastKnownPositionAsync",n=>async(...e)=>{if(!f())return n(...e);const t=await m();if(!t.granted)return y("denied","getLastKnownPositionAsync",a);const{fix:o}=D();k("request",EXPO_LIBRARY,`getLastKnownPositionAsync \u2192 ${o?"simulated":"null"}`);return o?exportLocation(o,a,T()):null});d.watchPositionImplAsync=u(s,"watchPositionImplAsync",n=>async(...e)=>{const t=Number(e[0]);const o=e[1]&&typeof e[1]==="object"?e[1]:{};if(!f()){const g=await n(...e);const A={kind:"position",options:o,native:true};p.set(t,A);if(f())N(t,A);return g}const i=await m();if(!i.granted)return y("denied","watchPositionImplAsync",a);if(!f()){p.set(t,{kind:"position",options:o,native:true});return n(...e)}const l={kind:"position",options:o,native:false};p.set(t,l);E(t,l);return void 0});d.watchDeviceHeading=u(s,"watchDeviceHeading",n=>async(...e)=>{const t=Number(e[0]);if(!f()){const l=await n(...e);const g={kind:"heading",options:{},native:true};p.set(t,g);if(f())N(t,g);return l}const o=await m();if(!o.granted)return y("denied","watchDeviceHeading",a);if(!f()){p.set(t,{kind:"heading",options:{},native:true});return n(...e)}const i={kind:"heading",options:{},native:false};p.set(t,i);E(t,i);return void 0});d.removeWatchAsync=u(s,"removeWatchAsync",n=>async(...e)=>{const t=Number(e[0]);const o=p.get(t);p.delete(t);b(EXPO_LIBRARY,"position",t);b(EXPO_LIBRARY,"heading",t);if(!o||o.native)return n(...e);return void 0});u(s,"hasServicesEnabledAsync",n=>async(...e)=>{if(f()&&!w())return false;return n(...e)});u(s,"getProviderStatusAsync",n=>async(...e)=>{const t=await n(...e);if(!f()||w())return t;const o={...t,locationServicesEnabled:false};for(const i of["gpsAvailable","networkAvailable","passiveAvailable"])if(i in o)o[i]=false;return o});const C=(n,e)=>u(s,e,t=>async(...o)=>{const i=String(o[0]);const l=o[1]&&typeof o[1]==="object"?o[1]:{};const g={name:i,kind:n,library:EXPO_LIBRARY,options:l};if(!f()){const Z=await t(...o);_(g,false);if(f())P(true);return Z}if(n==="locationUpdates"&&!w())return y("services",e,a);const A=await m();if(!A.granted)return y("denied",e,a);if(n==="geofencing"&&!await j()){return y("deniedBackground",e,a)}_(g,true);return void 0});d.startLocationUpdatesAsync=C("locationUpdates","startLocationUpdatesAsync");d.startGeofencingAsync=C("geofencing","startGeofencingAsync");const O=(n,e)=>u(s,e,t=>async(...o)=>{const i=v(String(o[0]));if(i&&i.kind===n){L(i.name);if(i.intercepted)return void 0}return t(...o)});d.stopLocationUpdatesAsync=O("locationUpdates","stopLocationUpdatesAsync");d.stopGeofencingAsync=O("geofencing","stopGeofencingAsync");const U=(n,e)=>u(s,e,t=>async(...o)=>{const i=v(String(o[0]));if(i&&i.kind===n)return true;return t(...o)});U("locationUpdates","hasStartedLocationUpdatesAsync");U("geofencing","hasStartedGeofencingAsync");const h=new Map;let K=0;const W={geofencing:"geofencing",locationUpdates:"location"};if(r){u(r,"notifyTaskFinishedAsync",n=>async(...e)=>{const t=e[1]??{};const o=t.eventId?h.get(t.eventId):void 0;if(o&&t.eventId){h.delete(t.eventId);o(t.result);return void 0}return n(...e)});u(r,"isTaskRegisteredAsync",n=>async(...e)=>{if(v(String(e[0]))?.intercepted)return true;return n(...e)});u(r,"getTaskOptionsAsync",n=>async(...e)=>{const t=v(String(e[0]));if(t?.intercepted)return t.options;return n(...e)});u(r,"getRegisteredTasksAsync",n=>async(...e)=>{const t=await n(...e)??[];const o=R().filter(i=>i.intercepted).map(i=>({taskName:i.name,taskType:W[i.kind],options:i.options}));return[...t,...o]});u(r,"unregisterTaskAsync",n=>async(...e)=>{const t=v(String(e[0]));if(t){L(t.name);if(t.intercepted)return void 0}return n(...e)});u(r,"unregisterAllTasksAsync",n=>async(...e)=>{for(const t of R())L(t.name);return n(...e)})}function V(){if(!r)return null;if(r.__expo_module_name__&&typeof r.emit==="function")return(e,t)=>r.emit(e,t);const n=M.DeviceEventEmitter;return n?(e,t)=>n.emit(e,t):null}async function z(n){for(let e=0;e<5e3&&ne(n)===false;e+=100){await new Promise(t=>I(()=>t(null),100))}}async function Y(n,e){await z(n.name);const t=V();if(!t)return Promise.reject(new Error("expo-task-manager is not installed"));const o=`buoy-location-${++K}`;const i=typeof r?.EVENT_NAME==="string"?r.EVENT_NAME:"TaskManager.executeTask";return new Promise((l,g)=>{h.set(o,l);I(()=>{if(h.delete(o))g(new Error("did not finish within 30 s"))},3e4);try{t(i,{data:e,error:null,executionInfo:{eventId:o,taskName:n.name,appState:"active"}})}catch(A){h.delete(o);g(A)}})}function N(n,e){if(!e.native)return;e.native=false;void Promise.resolve(d.removeWatchAsync?.(n)).catch(()=>{});E(n,e)}function P(n){for(const[e,t]of Array.from(p.entries())){if(n&&t.native){N(e,t)}else if(!n&&!t.native){b(EXPO_LIBRARY,t.kind,e);const o=t.kind==="position"?d.watchPositionImplAsync:d.watchDeviceHeading;t.native=true;void Promise.resolve(t.kind==="position"?o?.(e,t.options):o?.(e)).catch(i=>{t.native=false;S(e)(String(i?.message??i))})}else if(n&&!t.native&&!X(EXPO_LIBRARY,t.kind,e)){E(e,t)}}for(const e of R()){if(e.library!==EXPO_LIBRARY)continue;const t=e.kind==="geofencing";if(n&&!e.intercepted){const o=t?d.stopGeofencingAsync:d.stopLocationUpdatesAsync;void Promise.resolve(o?.(e.name)).catch(()=>{});x(e.name,true)}else if(!n&&e.intercepted){const o=t?d.startGeofencingAsync:d.startLocationUpdatesAsync;x(e.name,false);void Promise.resolve(o?.(e.name,e.options)).catch(i=>{k("error",EXPO_LIBRARY,`Could not restart ${e.name} natively: ${String(i?.message??i)}`)})}}}Q({library:EXPO_LIBRARY,fireTask:Y,onActiveChange:P,readPermission:async()=>{const n=await m();if(!n.reported)return null;const e=n.status==="granted"?await F():false;return{status:n.status,background:e,precision:n.precision}}});if(!$){$=true;if(r&&typeof r.getRegisteredTasksAsync==="function"){void Promise.resolve(r.getRegisteredTasksAsync.call(r)).then(n=>{for(const e of n??[]){if(!e?.taskName||v(e.taskName))continue;const t=e.taskType==="geofencing"?"geofencing":e.taskType==="location"?"locationUpdates":null;if(!t)continue;_({name:e.taskName,kind:t,library:EXPO_LIBRARY,options:e.options??{}},false);if(f())P(true)}}).catch(()=>{})}}return true}
@@ -0,0 +1 @@
1
+ "use strict";export function requireOptionalExpoModule(r){try{const e=require("expo-modules-core");return e.requireOptionalNativeModule?.(r)??null}catch{return null}}export function isTaskDefined(r){try{const e=require("expo-task-manager");return typeof e.isTaskDefined==="function"?e.isTaskDefined(r):null}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";export function requireOptionalExpoModule(e){return null}export function isTaskDefined(e){return null}
@@ -0,0 +1 @@
1
+ "use strict";import{installCommunityAdapters as o}from"./community";import{installExpoLocationAdapter as i}from"./expo";let t=null;export function installLocationAdapters(){if(t)return t;t=[];if(i())t.push("expo-location");t.push(...o());return t}
@@ -0,0 +1 @@
1
+ "use strict";const p="__buoyLocationNext";export function wrapMethod(r,n,o){const t=r[n];if(typeof t!=="function")return null;const u=t[p]??t;const e=(...s)=>u.apply(r,s);const c=o(e);c[p]=u;try{r[n]=c}catch{return null}return r[n]===c?e:null}export function codedError(r,n){const o=new Error(n);o.code=r;return o}