@ifc-lite/viewer 1.17.2 → 1.17.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +34 -24
- package/.turbo/turbo-typecheck.log +1 -42
- package/CHANGELOG.md +24 -0
- package/DESKTOP_CONTRACT_VERSION +1 -0
- package/dist/assets/arrow-CZ5kQ26f.js +20 -0
- package/dist/assets/basketViewActivator-BmnNtVfZ.js +1 -0
- package/dist/assets/bcf-DOG9_WPX.js +281 -0
- package/dist/assets/{browser-BDShTXzi.js → browser-C5TFR7sH.js} +1 -1
- package/dist/assets/cesium-ADbP7waU.css +1 -0
- package/dist/assets/cesium-DUOzBlqv.js +17817 -0
- package/dist/assets/drawing-2d-gWfpdfYe.js +257 -0
- package/dist/assets/epsg-index.generated-BjJrt_0S.js +1 -0
- package/dist/assets/exporters-ChAtBmlj.js +80367 -0
- package/dist/assets/geometry.worker-BQ0rzNo-.js +1 -0
- package/dist/assets/ids-B4jTqB1O.js +1 -0
- package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
- package/dist/assets/index-Co8E2-FE.js +106013 -0
- package/dist/assets/index-DckuDqlv.css +1 -0
- package/dist/assets/lens-CSASnhAL.js +1 -0
- package/dist/assets/maplibre-gl-CGLcoNXc.js +811 -0
- package/dist/assets/native-bridge-BRvbckFQ.js +429 -0
- package/dist/assets/{arrow2-bb-jcVEo.js → parquet-CEXmQNRO.js} +2 -2
- package/dist/assets/sandbox-DZiNLNMk.js +5933 -0
- package/dist/assets/server-client-BV8zHZ7Y.js +626 -0
- package/dist/assets/tauri-core-stub-D8Fa-u43.js +1 -0
- package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +1 -0
- package/dist/assets/tauri-fs-stub-BdeRC7aK.js +1 -0
- package/dist/assets/wasm-bridge-g01g7T9b.js +1 -0
- package/dist/assets/zip-DBEtpeu6.js +12 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json +1 -0
- package/dist/cesium/Assets/Images/bing_maps_credit.png +0 -0
- package/dist/cesium/Assets/Images/cesium_credit.png +0 -0
- package/dist/cesium/Assets/Images/google_earth_credit.png +0 -0
- package/dist/cesium/Assets/Images/ion-credit.png +0 -0
- package/dist/cesium/Assets/Textures/LensFlare/DirtMask.jpg +0 -0
- package/dist/cesium/Assets/Textures/LensFlare/StarBurst.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/0/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/0/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/tilemapresource.xml +14 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg +0 -0
- package/dist/cesium/Assets/Textures/maki/airfield.png +0 -0
- package/dist/cesium/Assets/Textures/maki/airport.png +0 -0
- package/dist/cesium/Assets/Textures/maki/alcohol-shop.png +0 -0
- package/dist/cesium/Assets/Textures/maki/america-football.png +0 -0
- package/dist/cesium/Assets/Textures/maki/art-gallery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bakery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bank.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bar.png +0 -0
- package/dist/cesium/Assets/Textures/maki/baseball.png +0 -0
- package/dist/cesium/Assets/Textures/maki/basketball.png +0 -0
- package/dist/cesium/Assets/Textures/maki/beer.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bicycle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/building.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bus.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cafe.png +0 -0
- package/dist/cesium/Assets/Textures/maki/camera.png +0 -0
- package/dist/cesium/Assets/Textures/maki/campsite.png +0 -0
- package/dist/cesium/Assets/Textures/maki/car.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cemetery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cesium.png +0 -0
- package/dist/cesium/Assets/Textures/maki/chemist.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cinema.png +0 -0
- package/dist/cesium/Assets/Textures/maki/circle-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/circle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/city.png +0 -0
- package/dist/cesium/Assets/Textures/maki/clothing-store.png +0 -0
- package/dist/cesium/Assets/Textures/maki/college.png +0 -0
- package/dist/cesium/Assets/Textures/maki/commercial.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cricket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cross.png +0 -0
- package/dist/cesium/Assets/Textures/maki/dam.png +0 -0
- package/dist/cesium/Assets/Textures/maki/danger.png +0 -0
- package/dist/cesium/Assets/Textures/maki/disability.png +0 -0
- package/dist/cesium/Assets/Textures/maki/dog-park.png +0 -0
- package/dist/cesium/Assets/Textures/maki/embassy.png +0 -0
- package/dist/cesium/Assets/Textures/maki/emergency-telephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/entrance.png +0 -0
- package/dist/cesium/Assets/Textures/maki/farm.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fast-food.png +0 -0
- package/dist/cesium/Assets/Textures/maki/ferry.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fire-station.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fuel.png +0 -0
- package/dist/cesium/Assets/Textures/maki/garden.png +0 -0
- package/dist/cesium/Assets/Textures/maki/gift.png +0 -0
- package/dist/cesium/Assets/Textures/maki/golf.png +0 -0
- package/dist/cesium/Assets/Textures/maki/grocery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/hairdresser.png +0 -0
- package/dist/cesium/Assets/Textures/maki/harbor.png +0 -0
- package/dist/cesium/Assets/Textures/maki/heart.png +0 -0
- package/dist/cesium/Assets/Textures/maki/heliport.png +0 -0
- package/dist/cesium/Assets/Textures/maki/hospital.png +0 -0
- package/dist/cesium/Assets/Textures/maki/ice-cream.png +0 -0
- package/dist/cesium/Assets/Textures/maki/industrial.png +0 -0
- package/dist/cesium/Assets/Textures/maki/land-use.png +0 -0
- package/dist/cesium/Assets/Textures/maki/laundry.png +0 -0
- package/dist/cesium/Assets/Textures/maki/library.png +0 -0
- package/dist/cesium/Assets/Textures/maki/lighthouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/lodging.png +0 -0
- package/dist/cesium/Assets/Textures/maki/logging.png +0 -0
- package/dist/cesium/Assets/Textures/maki/london-underground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/marker-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/marker.png +0 -0
- package/dist/cesium/Assets/Textures/maki/minefield.png +0 -0
- package/dist/cesium/Assets/Textures/maki/mobilephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/monument.png +0 -0
- package/dist/cesium/Assets/Textures/maki/museum.png +0 -0
- package/dist/cesium/Assets/Textures/maki/music.png +0 -0
- package/dist/cesium/Assets/Textures/maki/oil-well.png +0 -0
- package/dist/cesium/Assets/Textures/maki/park.png +0 -0
- package/dist/cesium/Assets/Textures/maki/park2.png +0 -0
- package/dist/cesium/Assets/Textures/maki/parking-garage.png +0 -0
- package/dist/cesium/Assets/Textures/maki/parking.png +0 -0
- package/dist/cesium/Assets/Textures/maki/pharmacy.png +0 -0
- package/dist/cesium/Assets/Textures/maki/pitch.png +0 -0
- package/dist/cesium/Assets/Textures/maki/place-of-worship.png +0 -0
- package/dist/cesium/Assets/Textures/maki/playground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/police.png +0 -0
- package/dist/cesium/Assets/Textures/maki/polling-place.png +0 -0
- package/dist/cesium/Assets/Textures/maki/post.png +0 -0
- package/dist/cesium/Assets/Textures/maki/prison.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-above.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-light.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-metro.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-underground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-christian.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-jewish.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-muslim.png +0 -0
- package/dist/cesium/Assets/Textures/maki/restaurant.png +0 -0
- package/dist/cesium/Assets/Textures/maki/roadblock.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rocket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/school.png +0 -0
- package/dist/cesium/Assets/Textures/maki/scooter.png +0 -0
- package/dist/cesium/Assets/Textures/maki/shop.png +0 -0
- package/dist/cesium/Assets/Textures/maki/skiing.png +0 -0
- package/dist/cesium/Assets/Textures/maki/slaughterhouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/soccer.png +0 -0
- package/dist/cesium/Assets/Textures/maki/square-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/square.png +0 -0
- package/dist/cesium/Assets/Textures/maki/star-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/star.png +0 -0
- package/dist/cesium/Assets/Textures/maki/suitcase.png +0 -0
- package/dist/cesium/Assets/Textures/maki/swimming.png +0 -0
- package/dist/cesium/Assets/Textures/maki/telephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/tennis.png +0 -0
- package/dist/cesium/Assets/Textures/maki/theatre.png +0 -0
- package/dist/cesium/Assets/Textures/maki/toilets.png +0 -0
- package/dist/cesium/Assets/Textures/maki/town-hall.png +0 -0
- package/dist/cesium/Assets/Textures/maki/town.png +0 -0
- package/dist/cesium/Assets/Textures/maki/triangle-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/triangle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/village.png +0 -0
- package/dist/cesium/Assets/Textures/maki/warehouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/waste-basket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/water.png +0 -0
- package/dist/cesium/Assets/Textures/maki/wetland.png +0 -0
- package/dist/cesium/Assets/Textures/maki/zoo.png +0 -0
- package/dist/cesium/Assets/Textures/moonSmall.jpg +0 -0
- package/dist/cesium/Assets/Textures/pin.svg +1 -0
- package/dist/cesium/Assets/Textures/waterNormals.jpg +0 -0
- package/dist/cesium/Assets/Textures/waterNormalsSmall.jpg +0 -0
- package/dist/cesium/Assets/approximateTerrainHeights.json +1 -0
- package/dist/cesium/ThirdParty/Workers/package.json +1 -0
- package/dist/cesium/ThirdParty/Workers/zip-web-worker.js +1 -0
- package/dist/cesium/ThirdParty/basis_transcoder.wasm +0 -0
- package/dist/cesium/ThirdParty/draco_decoder.wasm +0 -0
- package/dist/cesium/ThirdParty/google-earth-dbroot-parser.js +1 -0
- package/dist/cesium/ThirdParty/wasm_splats_bg.wasm +0 -0
- package/dist/cesium/ThirdParty/zip-module.wasm +0 -0
- package/dist/cesium/Widgets/Animation/Animation.css +127 -0
- package/dist/cesium/Widgets/Animation/lighter.css +70 -0
- package/dist/cesium/Widgets/BaseLayerPicker/BaseLayerPicker.css +108 -0
- package/dist/cesium/Widgets/BaseLayerPicker/lighter.css +22 -0
- package/dist/cesium/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.css +102 -0
- package/dist/cesium/Widgets/CesiumInspector/CesiumInspector.css +113 -0
- package/dist/cesium/Widgets/CesiumWidget/CesiumWidget.css +119 -0
- package/dist/cesium/Widgets/CesiumWidget/lighter.css +14 -0
- package/dist/cesium/Widgets/FullscreenButton/FullscreenButton.css +8 -0
- package/dist/cesium/Widgets/Geocoder/Geocoder.css +70 -0
- package/dist/cesium/Widgets/Geocoder/lighter.css +17 -0
- package/dist/cesium/Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorer.css +27 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldHillshade.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldImagery.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldOcean.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/azureAerial.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/azureRoads.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingAerial.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingAerialLabels.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingRoads.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/blueMarble.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/earthAtNight.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleContour.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleRoadmap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleSatellite.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleSatelliteLabels.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxSatellite.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxStreets.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxTerrain.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/naturalEarthII.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/openStreetMap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/sentinel-2.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmooth.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmoothDark.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stamenToner.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stamenWatercolor.png +0 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/Mouse.svg +84 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseLeft.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseMiddle.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseRight.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/Touch.svg +120 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchDrag.svg +129 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchRotate.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchTilt.svg +135 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchZoom.svg +74 -0
- package/dist/cesium/Widgets/Images/TerrainProviders/CesiumWorldTerrain.png +0 -0
- package/dist/cesium/Widgets/Images/TerrainProviders/Ellipsoid.png +0 -0
- package/dist/cesium/Widgets/Images/TimelineIcons.png +0 -0
- package/dist/cesium/Widgets/Images/info-loading.gif +0 -0
- package/dist/cesium/Widgets/InfoBox/InfoBox.css +92 -0
- package/dist/cesium/Widgets/InfoBox/InfoBoxDescription.css +178 -0
- package/dist/cesium/Widgets/NavigationHelpButton/NavigationHelpButton.css +93 -0
- package/dist/cesium/Widgets/NavigationHelpButton/lighter.css +38 -0
- package/dist/cesium/Widgets/PerformanceWatchdog/PerformanceWatchdog.css +15 -0
- package/dist/cesium/Widgets/ProjectionPicker/ProjectionPicker.css +38 -0
- package/dist/cesium/Widgets/SceneModePicker/SceneModePicker.css +56 -0
- package/dist/cesium/Widgets/SelectionIndicator/SelectionIndicator.css +20 -0
- package/dist/cesium/Widgets/Timeline/Timeline.css +103 -0
- package/dist/cesium/Widgets/Timeline/lighter.css +23 -0
- package/dist/cesium/Widgets/VRButton/VRButton.css +8 -0
- package/dist/cesium/Widgets/Viewer/Viewer.css +107 -0
- package/dist/cesium/Widgets/VoxelInspector/VoxelInspector.css +16 -0
- package/dist/cesium/Widgets/lighter.css +237 -0
- package/dist/cesium/Widgets/lighterShared.css +46 -0
- package/dist/cesium/Widgets/shared.css +103 -0
- package/dist/cesium/Widgets/widgets.css +1342 -0
- package/dist/cesium/Workers/chunk-23ZQ2IVV.js +29 -0
- package/dist/cesium/Workers/chunk-2EQO3Q56.js +26 -0
- package/dist/cesium/Workers/chunk-2MJIIVP4.js +26 -0
- package/dist/cesium/Workers/chunk-2TE5NTVD.js +26 -0
- package/dist/cesium/Workers/chunk-2ZBHLJST.js +26 -0
- package/dist/cesium/Workers/chunk-5TJMAQVL.js +26 -0
- package/dist/cesium/Workers/chunk-6BD4U3VO.js +26 -0
- package/dist/cesium/Workers/chunk-7TVGLKQF.js +26 -0
- package/dist/cesium/Workers/chunk-BTSYJ5XU.js +26 -0
- package/dist/cesium/Workers/chunk-BXMEEOCS.js +63 -0
- package/dist/cesium/Workers/chunk-BYLCY7GP.js +29 -0
- package/dist/cesium/Workers/chunk-CTHM3W6I.js +26 -0
- package/dist/cesium/Workers/chunk-CUUSNIVQ.js +26 -0
- package/dist/cesium/Workers/chunk-E3JOOS3S.js +26 -0
- package/dist/cesium/Workers/chunk-E7KYDCM5.js +26 -0
- package/dist/cesium/Workers/chunk-EDVBB7SS.js +27 -0
- package/dist/cesium/Workers/chunk-EFBN7QNX.js +26 -0
- package/dist/cesium/Workers/chunk-EQ4YRVWL.js +26 -0
- package/dist/cesium/Workers/chunk-F6PRE7D6.js +26 -0
- package/dist/cesium/Workers/chunk-FC4ZZ65J.js +26 -0
- package/dist/cesium/Workers/chunk-FFBVWF2L.js +26 -0
- package/dist/cesium/Workers/chunk-GBAA6GVX.js +26 -0
- package/dist/cesium/Workers/chunk-ICALLYLG.js +26 -0
- package/dist/cesium/Workers/chunk-ILRYTWTP.js +26 -0
- package/dist/cesium/Workers/chunk-IRNLBSEJ.js +26 -0
- package/dist/cesium/Workers/chunk-IX4VMHEV.js +26 -0
- package/dist/cesium/Workers/chunk-L6QHHACZ.js +26 -0
- package/dist/cesium/Workers/chunk-LI2ZSORM.js +26 -0
- package/dist/cesium/Workers/chunk-LSLE2RL4.js +26 -0
- package/dist/cesium/Workers/chunk-M4HLDBCG.js +26 -0
- package/dist/cesium/Workers/chunk-MJHHSGEH.js +26 -0
- package/dist/cesium/Workers/chunk-NMVKML6W.js +26 -0
- package/dist/cesium/Workers/chunk-OCWJRAXS.js +26 -0
- package/dist/cesium/Workers/chunk-OIRKANTH.js +26 -0
- package/dist/cesium/Workers/chunk-OIT7J4IC.js +26 -0
- package/dist/cesium/Workers/chunk-OLZ3FYUM.js +26 -0
- package/dist/cesium/Workers/chunk-Q5BPHJQF.js +26 -0
- package/dist/cesium/Workers/chunk-QFM5DCMQ.js +26 -0
- package/dist/cesium/Workers/chunk-QKUIYMGC.js +28 -0
- package/dist/cesium/Workers/chunk-S44JILQT.js +26 -0
- package/dist/cesium/Workers/chunk-SLT4J352.js +26 -0
- package/dist/cesium/Workers/chunk-SQMIIXB7.js +26 -0
- package/dist/cesium/Workers/chunk-TJ4XLGBQ.js +26 -0
- package/dist/cesium/Workers/chunk-TNSUQXWK.js +27 -0
- package/dist/cesium/Workers/chunk-UBOGZS7F.js +26 -0
- package/dist/cesium/Workers/chunk-V3OSTMM6.js +26 -0
- package/dist/cesium/Workers/chunk-V7QEYVP3.js +26 -0
- package/dist/cesium/Workers/chunk-VUKYSU4H.js +26 -0
- package/dist/cesium/Workers/chunk-W37FE5GR.js +26 -0
- package/dist/cesium/Workers/chunk-WBOV35NL.js +26 -0
- package/dist/cesium/Workers/chunk-WPMZLB3Y.js +26 -0
- package/dist/cesium/Workers/chunk-WWWZVEEH.js +26 -0
- package/dist/cesium/Workers/chunk-XFIQ5DEQ.js +28 -0
- package/dist/cesium/Workers/chunk-XQHLGIO7.js +26 -0
- package/dist/cesium/Workers/chunk-XUSCFAVF.js +26 -0
- package/dist/cesium/Workers/chunk-YP7I5QBZ.js +26 -0
- package/dist/cesium/Workers/chunk-Z3QF2EHT.js +26 -0
- package/dist/cesium/Workers/combineGeometry.js +26 -0
- package/dist/cesium/Workers/createBoxGeometry.js +26 -0
- package/dist/cesium/Workers/createBoxOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCircleGeometry.js +26 -0
- package/dist/cesium/Workers/createCircleOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCoplanarPolygonGeometry.js +26 -0
- package/dist/cesium/Workers/createCoplanarPolygonOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCorridorGeometry.js +26 -0
- package/dist/cesium/Workers/createCorridorOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCylinderGeometry.js +26 -0
- package/dist/cesium/Workers/createCylinderOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipseGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipseOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipsoidGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipsoidOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createFrustumGeometry.js +26 -0
- package/dist/cesium/Workers/createFrustumOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createGeometry.js +26 -0
- package/dist/cesium/Workers/createGroundPolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createPlaneGeometry.js +26 -0
- package/dist/cesium/Workers/createPlaneOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolygonGeometry.js +26 -0
- package/dist/cesium/Workers/createPolygonOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineVolumeGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineVolumeOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createRectangleGeometry.js +26 -0
- package/dist/cesium/Workers/createRectangleOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createSimplePolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createSphereGeometry.js +26 -0
- package/dist/cesium/Workers/createSphereOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createTaskProcessorWorker.js +26 -0
- package/dist/cesium/Workers/createVectorTileClampedPolylines.js +26 -0
- package/dist/cesium/Workers/createVectorTileGeometries.js +26 -0
- package/dist/cesium/Workers/createVectorTilePoints.js +26 -0
- package/dist/cesium/Workers/createVectorTilePolygons.js +26 -0
- package/dist/cesium/Workers/createVectorTilePolylines.js +26 -0
- package/dist/cesium/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -0
- package/dist/cesium/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -0
- package/dist/cesium/Workers/createVerticesFromHeightmap.js +26 -0
- package/dist/cesium/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -0
- package/dist/cesium/Workers/createWallGeometry.js +26 -0
- package/dist/cesium/Workers/createWallOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/decodeDraco.js +26 -0
- package/dist/cesium/Workers/decodeGoogleEarthEnterprisePacket.js +26 -0
- package/dist/cesium/Workers/decodeI3S.js +26 -0
- package/dist/cesium/Workers/gaussianSplatSorter.js +26 -0
- package/dist/cesium/Workers/gaussianSplatTextureGenerator.js +26 -0
- package/dist/cesium/Workers/incrementallyBuildTerrainPicker.js +26 -0
- package/dist/cesium/Workers/transcodeKTX2.js +56 -0
- package/dist/cesium/Workers/transferTypedArrayTest.js +26 -0
- package/dist/cesium/Workers/upsampleQuantizedTerrainMesh.js +26 -0
- package/dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -0
- package/dist/index.html +13 -2
- package/package.json +27 -19
- package/src/App.tsx +1 -17
- package/src/components/viewer/BCFPanel.tsx +46 -4
- package/src/components/viewer/CesiumOverlay.tsx +672 -0
- package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
- package/src/components/viewer/ChatPanel.tsx +54 -16
- package/src/components/viewer/CommandPalette.tsx +6 -1
- package/src/components/viewer/DesktopEntitlementBanner.tsx +74 -0
- package/src/components/viewer/ExportChangesButton.tsx +24 -4
- package/src/components/viewer/ExportDialog.tsx +38 -9
- package/src/components/viewer/HierarchyPanel.tsx +202 -6
- package/src/components/viewer/IDSPanel.tsx +52 -3
- package/src/components/viewer/KeyboardShortcutsDialog.tsx +1 -1
- package/src/components/viewer/MainToolbar.tsx +353 -27
- package/src/components/viewer/PropertiesPanel.tsx +306 -131
- package/src/components/viewer/ScriptPanel.tsx +34 -8
- package/src/components/viewer/Section2DPanel.tsx +3 -2
- package/src/components/viewer/SettingsPage.tsx +430 -0
- package/src/components/viewer/StatusBar.tsx +17 -1
- package/src/components/viewer/UpgradePage.tsx +6 -4
- package/src/components/viewer/ViewerLayout.tsx +47 -6
- package/src/components/viewer/Viewport.tsx +49 -8
- package/src/components/viewer/ViewportContainer.tsx +285 -32
- package/src/components/viewer/ViewportOverlays.tsx +129 -27
- package/src/components/viewer/hierarchy/treeDataBuilder.ts +2 -1
- package/src/components/viewer/properties/EpsgLookupDialog.tsx +418 -0
- package/src/components/viewer/properties/GeoreferencingPanel.tsx +703 -0
- package/src/components/viewer/properties/LocationMap.tsx +730 -0
- package/src/components/viewer/properties/ModelMetadataPanel.tsx +3 -70
- package/src/components/viewer/selectionHandlers.ts +4 -3
- package/src/components/viewer/useAnimationLoop.ts +4 -0
- package/src/components/viewer/useGeometryStreaming.ts +127 -40
- package/src/components/viewer/useMouseControls.ts +4 -1
- package/src/hooks/bcfIdLookup.ts +13 -11
- package/src/hooks/ids/idsColorSystem.ts +3 -8
- package/src/hooks/ingest/viewerModelIngest.ts +275 -0
- package/src/hooks/useIDS.ts +32 -17
- package/src/hooks/useIfc.ts +7 -1
- package/src/hooks/useIfcCache.ts +28 -15
- package/src/hooks/useIfcFederation.ts +59 -227
- package/src/hooks/useIfcLoader.ts +1656 -130
- package/src/hooks/useIfcServer.ts +0 -69
- package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +175 -0
- package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
- package/src/lib/desktop-entitlement.ts +45 -0
- package/src/lib/desktop-product.ts +124 -0
- package/src/lib/geo/cesium-bridge.ts +310 -0
- package/src/lib/geo/kmz-exporter.ts +112 -0
- package/src/lib/geo/reproject.ts +370 -0
- package/src/lib/lens/adapter.ts +3 -1
- package/src/lib/recent-files.ts +2 -1
- package/src/main.tsx +1 -0
- package/src/sdk/adapters/export-adapter.ts +14 -1
- package/src/sdk/adapters/viewer-adapter.ts +5 -9
- package/src/sdk/adapters/visibility-adapter.ts +6 -9
- package/src/services/analysis-extensions.ts +125 -0
- package/src/services/app-navigation.ts +13 -0
- package/src/services/bsdd.ts +53 -4
- package/src/services/cacheService.ts +1 -1
- package/src/services/desktop-cache.ts +43 -0
- package/src/services/desktop-export.ts +77 -0
- package/src/services/desktop-harness.ts +196 -0
- package/src/services/desktop-logger.ts +20 -0
- package/src/services/desktop-native-metadata.ts +207 -0
- package/src/services/desktop-panel-actions.ts +43 -0
- package/src/services/desktop-preferences.ts +44 -0
- package/src/services/file-dialog.ts +147 -0
- package/src/services/tauri-core-stub.ts +7 -0
- package/src/services/tauri-dialog-stub.ts +7 -0
- package/src/services/tauri-fs-stub.ts +7 -0
- package/src/store/basketVisibleSet.ts +3 -4
- package/src/store/globalId.ts +79 -0
- package/src/store/index.ts +41 -2
- package/src/store/slices/cesiumSlice.ts +122 -0
- package/src/store/slices/chatSlice.ts +5 -1
- package/src/store/slices/dataSlice.ts +139 -28
- package/src/store/slices/desktopEntitlementSlice.ts +86 -0
- package/src/store/slices/loadingSlice.ts +14 -2
- package/src/store/slices/modelSlice.ts +58 -3
- package/src/store/slices/mutationSlice.ts +178 -0
- package/src/store/slices/pinboardSlice.ts +4 -8
- package/src/store/types.ts +96 -2
- package/src/store.ts +1 -1
- package/src/utils/desktopModelSnapshot.ts +358 -0
- package/src/utils/ifcConfig.ts +6 -1
- package/src/utils/nativeSpatialDataStore.ts +250 -0
- package/src/utils/serverDataModel.ts +4 -0
- package/src/utils/spatialHierarchy.ts +10 -11
- package/vite.config.ts +41 -0
- package/dist/assets/Arrow.dom-BhOg9lpn.js +0 -20
- package/dist/assets/arrow2_bg-BlXl-cSQ.js +0 -1
- package/dist/assets/basketViewActivator-BRG5DBmM.js +0 -1
- package/dist/assets/desktop-cache-oPzaWXYE.js +0 -1
- package/dist/assets/geometry.worker-kgiT_Qhh.js +0 -1
- package/dist/assets/ifc-lite_bg-FNRmpSvM.wasm +0 -0
- package/dist/assets/index-B1Ecw4AU.js +0 -189756
- package/dist/assets/index-Ba4eoTe7.css +0 -1
- package/dist/assets/index-CrgYBjTn.js +0 -229
- package/dist/assets/module-6F3E5H7Y-tx0BadV3.js +0 -6
- package/dist/assets/native-bridge-Crsb7TKz.js +0 -111
- package/dist/assets/wasm-bridge-mJUhb7uk.js +0 -1
|
@@ -132,7 +132,6 @@ export function useIfcServer() {
|
|
|
132
132
|
): Promise<boolean> => {
|
|
133
133
|
const { setProgress, setIfcDataStore, setGeometryResult } = useViewerStore.getState();
|
|
134
134
|
try {
|
|
135
|
-
const serverStart = performance.now();
|
|
136
135
|
setProgress({ phase: 'Connecting to server', percent: 5 });
|
|
137
136
|
|
|
138
137
|
const client = new IfcServerClient({ baseUrl: SERVER_URL });
|
|
@@ -151,8 +150,6 @@ export function useIfcServer() {
|
|
|
151
150
|
|
|
152
151
|
let allMeshes: MeshData[];
|
|
153
152
|
let result: ServerParseResultType;
|
|
154
|
-
let parseTime: number;
|
|
155
|
-
let convertTime: number;
|
|
156
153
|
|
|
157
154
|
// Use streaming for large files (>150MB) for progressive rendering
|
|
158
155
|
// Smaller files use non-streaming path (faster - avoids ~1.1s background re-processing overhead)
|
|
@@ -164,8 +161,6 @@ export function useIfcServer() {
|
|
|
164
161
|
|
|
165
162
|
if (parquetSupported && fileSizeMB > USE_STREAMING_THRESHOLD_MB) {
|
|
166
163
|
// STREAMING PATH - for large files, render progressively
|
|
167
|
-
console.log(`[useIfc] Using STREAMING endpoint for large file (${fileSizeMB.toFixed(1)}MB)`);
|
|
168
|
-
|
|
169
164
|
allMeshes = [];
|
|
170
165
|
let totalVertices = 0;
|
|
171
166
|
let totalTriangles = 0;
|
|
@@ -177,8 +172,6 @@ export function useIfcServer() {
|
|
|
177
172
|
// Progressive bounds calculation
|
|
178
173
|
const bounds = createEmptyBounds();
|
|
179
174
|
|
|
180
|
-
const parseStart = performance.now();
|
|
181
|
-
|
|
182
175
|
// Throttle server streaming updates - large files get less frequent UI updates
|
|
183
176
|
let lastServerStreamRenderTime = 0;
|
|
184
177
|
const SERVER_STREAM_INTERVAL_MS = getServerStreamIntervalMs(fileSizeMB);
|
|
@@ -232,15 +225,10 @@ export function useIfcServer() {
|
|
|
232
225
|
}
|
|
233
226
|
});
|
|
234
227
|
|
|
235
|
-
parseTime = performance.now() - parseStart;
|
|
236
228
|
cacheKey = streamResult.cache_key;
|
|
237
229
|
streamMetadata = streamResult.metadata;
|
|
238
230
|
streamStats = streamResult.stats;
|
|
239
231
|
|
|
240
|
-
console.log(`[useIfc] Streaming complete in ${parseTime.toFixed(0)}ms`);
|
|
241
|
-
console.log(` ${batchCount} batches, ${allMeshes.length} meshes`);
|
|
242
|
-
console.log(` Cache key: ${cacheKey}`);
|
|
243
|
-
|
|
244
232
|
// Build final result object for data model fetching
|
|
245
233
|
// Note: meshes field is omitted - allMeshes is passed separately to convertServerDataModel
|
|
246
234
|
result = {
|
|
@@ -248,7 +236,6 @@ export function useIfcServer() {
|
|
|
248
236
|
metadata: streamMetadata,
|
|
249
237
|
stats: streamStats,
|
|
250
238
|
} as ParquetStreamResult;
|
|
251
|
-
convertTime = 0; // Already converted inline
|
|
252
239
|
|
|
253
240
|
// Final geometry set with complete bounds
|
|
254
241
|
// Server already applies RTC shift to mesh positions, so bounds are shifted
|
|
@@ -286,49 +273,23 @@ export function useIfcServer() {
|
|
|
286
273
|
|
|
287
274
|
} else if (parquetSupported) {
|
|
288
275
|
// NON-STREAMING PATH - for smaller files, use batch request (with cache check)
|
|
289
|
-
console.log(`[useIfc] Using PARQUET endpoint - 15x smaller payload, faster transfer`);
|
|
290
|
-
|
|
291
276
|
// Use Parquet endpoint - much smaller payload (~15x compression)
|
|
292
|
-
const parseStart = performance.now();
|
|
293
277
|
const parquetResult = await client.parseParquet(file);
|
|
294
278
|
result = parquetResult;
|
|
295
|
-
parseTime = performance.now() - parseStart;
|
|
296
|
-
|
|
297
|
-
console.log(`[useIfc] Server parse response received in ${parseTime.toFixed(0)}ms`);
|
|
298
|
-
console.log(` Server stats: ${parquetResult.stats.total_time_ms}ms total (parse: ${parquetResult.stats.parse_time_ms}ms, geometry: ${parquetResult.stats.geometry_time_ms}ms)`);
|
|
299
|
-
console.log(` Parquet payload: ${(parquetResult.parquet_stats.payload_size / 1024 / 1024).toFixed(2)}MB, decode: ${parquetResult.parquet_stats.decode_time_ms}ms`);
|
|
300
|
-
console.log(` Meshes: ${parquetResult.meshes.length}, Vertices: ${parquetResult.stats.total_vertices}, Triangles: ${parquetResult.stats.total_triangles}`);
|
|
301
|
-
console.log(` Cache key: ${parquetResult.cache_key}`);
|
|
302
279
|
|
|
303
280
|
setProgress({ phase: 'Converting meshes', percent: 70 });
|
|
304
281
|
|
|
305
282
|
// Convert server mesh format to viewer format (TypedArrays)
|
|
306
|
-
const convertStart = performance.now();
|
|
307
283
|
allMeshes = parquetResult.meshes.map(convertServerMesh);
|
|
308
|
-
convertTime = performance.now() - convertStart;
|
|
309
|
-
console.log(`[useIfc] Mesh conversion: ${convertTime.toFixed(0)}ms for ${allMeshes.length} meshes`);
|
|
310
284
|
} else {
|
|
311
|
-
console.log(`[useIfc] Parquet not available, using JSON endpoint (install parquet-wasm for 15x faster transfer)`);
|
|
312
|
-
console.log(`[useIfc] Using FULL PARSE (parallel) - all geometry processed at once`);
|
|
313
|
-
|
|
314
285
|
// Fallback to JSON endpoint
|
|
315
|
-
const parseStart = performance.now();
|
|
316
286
|
result = await client.parse(file);
|
|
317
|
-
parseTime = performance.now() - parseStart;
|
|
318
|
-
|
|
319
|
-
console.log(`[useIfc] Server parse response received in ${parseTime.toFixed(0)}ms`);
|
|
320
|
-
console.log(` Server stats: ${result.stats.total_time_ms}ms total (parse: ${result.stats.parse_time_ms}ms, geometry: ${result.stats.geometry_time_ms}ms)`);
|
|
321
|
-
console.log(` Meshes: ${result.meshes.length}, Vertices: ${result.stats.total_vertices}, Triangles: ${result.stats.total_triangles}`);
|
|
322
|
-
console.log(` Cache key: ${result.cache_key}`);
|
|
323
287
|
|
|
324
288
|
setProgress({ phase: 'Converting meshes', percent: 70 });
|
|
325
289
|
|
|
326
290
|
// Convert server mesh format to viewer format
|
|
327
|
-
const convertStart = performance.now();
|
|
328
291
|
const jsonResult = result as ParseResponse;
|
|
329
292
|
allMeshes = jsonResult.meshes.map(convertServerMesh);
|
|
330
|
-
convertTime = performance.now() - convertStart;
|
|
331
|
-
console.log(`[useIfc] Mesh conversion: ${convertTime.toFixed(0)}ms for ${allMeshes.length} meshes`);
|
|
332
293
|
}
|
|
333
294
|
|
|
334
295
|
// For non-streaming paths, calculate bounds and set geometry
|
|
@@ -376,23 +337,14 @@ export function useIfcServer() {
|
|
|
376
337
|
hasLargeCoordinates: serverCoordInfo?.is_geo_referenced ?? false,
|
|
377
338
|
};
|
|
378
339
|
|
|
379
|
-
console.log(`[useIfc] Calculated bounds:`, {
|
|
380
|
-
min: `(${bounds.min.x.toFixed(1)}, ${bounds.min.y.toFixed(1)}, ${bounds.min.z.toFixed(1)})`,
|
|
381
|
-
max: `(${bounds.max.x.toFixed(1)}, ${bounds.max.y.toFixed(1)}, ${bounds.max.z.toFixed(1)})`,
|
|
382
|
-
size: `${(bounds.max.x - bounds.min.x).toFixed(1)} x ${(bounds.max.y - bounds.min.y).toFixed(1)} x ${(bounds.max.z - bounds.min.z).toFixed(1)}`,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
340
|
// Set all geometry at once
|
|
386
341
|
setProgress({ phase: 'Rendering geometry', percent: 80 });
|
|
387
|
-
const renderStart = performance.now();
|
|
388
342
|
setGeometryResult({
|
|
389
343
|
meshes: allMeshes,
|
|
390
344
|
totalVertices: result.stats.total_vertices,
|
|
391
345
|
totalTriangles: result.stats.total_triangles,
|
|
392
346
|
coordinateInfo,
|
|
393
347
|
});
|
|
394
|
-
const renderTime = performance.now() - renderStart;
|
|
395
|
-
console.log(`[useIfc] Geometry set: ${renderTime.toFixed(0)}ms`);
|
|
396
348
|
}
|
|
397
349
|
|
|
398
350
|
// Fetch and decode data model asynchronously (geometry already displayed)
|
|
@@ -403,8 +355,6 @@ export function useIfcServer() {
|
|
|
403
355
|
(async () => {
|
|
404
356
|
if (isStale?.()) return;
|
|
405
357
|
setProgress({ phase: 'Fetching data model', percent: 85 });
|
|
406
|
-
const dataModelStart = performance.now();
|
|
407
|
-
|
|
408
358
|
try {
|
|
409
359
|
// If data model was included in response (ParquetParseResponse), use it directly
|
|
410
360
|
// Otherwise, fetch from the data model endpoint
|
|
@@ -414,25 +364,15 @@ export function useIfcServer() {
|
|
|
414
364
|
}
|
|
415
365
|
|
|
416
366
|
if (!dataModelBuffer || dataModelBuffer.byteLength === 0) {
|
|
417
|
-
console.log('[useIfc] Fetching data model from server (background processing)...');
|
|
418
367
|
dataModelBuffer = await client.fetchDataModel(cacheKey);
|
|
419
368
|
}
|
|
420
369
|
|
|
421
370
|
if (!dataModelBuffer) {
|
|
422
|
-
console.log('[useIfc] ⚡ Data model not available - property panel disabled');
|
|
423
371
|
return;
|
|
424
372
|
}
|
|
425
373
|
|
|
426
374
|
const dataModel: DataModel = await decodeDataModel(dataModelBuffer);
|
|
427
375
|
|
|
428
|
-
console.log(`[useIfc] Data model decoded in ${(performance.now() - dataModelStart).toFixed(0)}ms`);
|
|
429
|
-
console.log(` Entities: ${dataModel.entities.size}`);
|
|
430
|
-
console.log(` PropertySets: ${dataModel.propertySets.size}`);
|
|
431
|
-
const quantitySetsSize = (dataModel as { quantitySets?: Map<number, unknown> }).quantitySets?.size ?? 0;
|
|
432
|
-
console.log(` QuantitySets: ${quantitySetsSize}`);
|
|
433
|
-
console.log(` Relationships: ${dataModel.relationships.length}`);
|
|
434
|
-
console.log(` Spatial nodes: ${dataModel.spatialHierarchy.nodes.length}`);
|
|
435
|
-
|
|
436
376
|
// Convert server data model directly to IfcDataStore format
|
|
437
377
|
const dataStore = convertServerDataModel(
|
|
438
378
|
dataModel,
|
|
@@ -443,23 +383,14 @@ export function useIfcServer() {
|
|
|
443
383
|
|
|
444
384
|
if (isStale?.()) return;
|
|
445
385
|
setIfcDataStore(dataStore);
|
|
446
|
-
console.log('[useIfc] ✅ Property panel ready with server data model');
|
|
447
|
-
console.log(`[useIfc] Data model loaded in ${(performance.now() - dataModelStart).toFixed(0)}ms (background)`);
|
|
448
386
|
|
|
449
387
|
buildSpatialIndexGuarded(allMeshes, dataStore, setIfcDataStore);
|
|
450
388
|
} catch (err) {
|
|
451
|
-
console.warn('[useIfc] Failed to decode data model:', err);
|
|
452
|
-
console.log('[useIfc] ⚡ Skipping data model (decoding failed)');
|
|
453
389
|
}
|
|
454
390
|
})(); // End of async data model fetch block - runs in background, doesn't block
|
|
455
391
|
|
|
456
392
|
// Geometry is ready - mark complete immediately (data model loads in background)
|
|
457
393
|
setProgress({ phase: 'Complete', percent: 100 });
|
|
458
|
-
const totalServerTime = performance.now() - serverStart;
|
|
459
|
-
console.log(`[useIfc] SERVER PARALLEL complete: ${file.name}`);
|
|
460
|
-
console.log(` Total time: ${totalServerTime.toFixed(0)}ms`);
|
|
461
|
-
console.log(` Breakdown: parse=${parseTime.toFixed(0)}ms, convert=${convertTime.toFixed(0)}ms`);
|
|
462
|
-
|
|
463
394
|
return true;
|
|
464
395
|
} catch (err) {
|
|
465
396
|
console.error('[useIfc] Server parse failed:', err);
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
import { useAuth, useUser } from '@clerk/clerk-react';
|
|
7
|
+
import { getDefaultDesktopEntitlement, type DesktopEntitlement } from '@/lib/desktop-product';
|
|
8
|
+
import { resolveDesktopEntitlement } from '@/lib/desktop-entitlement';
|
|
9
|
+
import { useViewerStore } from '@/store';
|
|
10
|
+
import { DESKTOP_ENTITLEMENT_REFRESH_EVENT } from './desktopEntitlementEvents';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Sync Clerk auth + entitlement state into the viewer store.
|
|
14
|
+
* Desktop plan state is authoritative here; chat inherits only the AI-specific permission.
|
|
15
|
+
*/
|
|
16
|
+
const ENTITLEMENT_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
17
|
+
|
|
18
|
+
function entitlementsEqual(left: DesktopEntitlement, right: DesktopEntitlement): boolean {
|
|
19
|
+
return left.tier === right.tier
|
|
20
|
+
&& left.status === right.status
|
|
21
|
+
&& left.source === right.source
|
|
22
|
+
&& left.userId === right.userId
|
|
23
|
+
&& left.validatedAt === right.validatedAt
|
|
24
|
+
&& left.graceUntil === right.graceUntil
|
|
25
|
+
&& left.trialEndsAt === right.trialEndsAt;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function ClerkDesktopEntitlementSync() {
|
|
29
|
+
const { isLoaded, isSignedIn, userId, getToken, has } = useAuth();
|
|
30
|
+
const { user } = useUser();
|
|
31
|
+
const setChatAuthToken = useViewerStore((s) => s.setChatAuthToken);
|
|
32
|
+
const switchChatUserContext = useViewerStore((s) => s.switchChatUserContext);
|
|
33
|
+
const setDesktopEntitlement = useViewerStore((s) => s.setDesktopEntitlement);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!isLoaded) return;
|
|
37
|
+
|
|
38
|
+
if (!isSignedIn) {
|
|
39
|
+
const state = useViewerStore.getState();
|
|
40
|
+
const next = (
|
|
41
|
+
state.desktopEntitlement.tier === 'pro'
|
|
42
|
+
&& state.desktopEntitlement.graceUntil
|
|
43
|
+
&& state.desktopEntitlement.graceUntil > Date.now()
|
|
44
|
+
)
|
|
45
|
+
? {
|
|
46
|
+
...state.desktopEntitlement,
|
|
47
|
+
status: 'grace_offline' as const,
|
|
48
|
+
source: 'cached' as const,
|
|
49
|
+
}
|
|
50
|
+
: {
|
|
51
|
+
...getDefaultDesktopEntitlement(),
|
|
52
|
+
status: 'signed_out' as const,
|
|
53
|
+
source: 'cached' as const,
|
|
54
|
+
};
|
|
55
|
+
if (!entitlementsEqual(state.desktopEntitlement, next)) {
|
|
56
|
+
setDesktopEntitlement(next);
|
|
57
|
+
}
|
|
58
|
+
if (next.status === 'grace_offline') {
|
|
59
|
+
switchChatUserContext(next.userId, false, {
|
|
60
|
+
clearPersistedCurrent: false,
|
|
61
|
+
restoreMessages: true,
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
switchChatUserContext(null, false, {
|
|
65
|
+
clearPersistedCurrent: state.chatStorageUserId !== null,
|
|
66
|
+
restoreMessages: false,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
setChatAuthToken(null);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let cancelled = false;
|
|
74
|
+
|
|
75
|
+
const syncAuth = async () => {
|
|
76
|
+
try {
|
|
77
|
+
const token = await getToken({ skipCache: true });
|
|
78
|
+
const { entitlement, aiAssistantEnabled } = resolveDesktopEntitlement({
|
|
79
|
+
userId: userId ?? null,
|
|
80
|
+
token,
|
|
81
|
+
has,
|
|
82
|
+
publicMetadata: (user?.publicMetadata ?? null) as Record<string, unknown> | null,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (cancelled) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const state = useViewerStore.getState();
|
|
90
|
+
if (!entitlementsEqual(state.desktopEntitlement, entitlement)) {
|
|
91
|
+
setDesktopEntitlement(entitlement);
|
|
92
|
+
}
|
|
93
|
+
if (state.chatStorageUserId !== (userId ?? null) || state.chatHasPro !== aiAssistantEnabled) {
|
|
94
|
+
switchChatUserContext(userId ?? null, aiAssistantEnabled, {
|
|
95
|
+
clearPersistedCurrent: state.chatStorageUserId !== null && state.chatStorageUserId !== userId,
|
|
96
|
+
restoreMessages: true,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
setChatAuthToken(token ?? null);
|
|
100
|
+
} catch {
|
|
101
|
+
if (cancelled) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const state = useViewerStore.getState();
|
|
106
|
+
if (
|
|
107
|
+
state.desktopEntitlement.tier === 'pro'
|
|
108
|
+
&& state.desktopEntitlement.graceUntil
|
|
109
|
+
&& state.desktopEntitlement.graceUntil > Date.now()
|
|
110
|
+
) {
|
|
111
|
+
const next = {
|
|
112
|
+
...state.desktopEntitlement,
|
|
113
|
+
status: 'grace_offline',
|
|
114
|
+
source: 'cached',
|
|
115
|
+
} satisfies DesktopEntitlement;
|
|
116
|
+
if (!entitlementsEqual(state.desktopEntitlement, next)) {
|
|
117
|
+
setDesktopEntitlement(next);
|
|
118
|
+
}
|
|
119
|
+
if (state.chatStorageUserId !== (userId ?? null) || state.chatHasPro !== true) {
|
|
120
|
+
switchChatUserContext(userId ?? null, true, {
|
|
121
|
+
clearPersistedCurrent: false,
|
|
122
|
+
restoreMessages: true,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const next = {
|
|
129
|
+
...getDefaultDesktopEntitlement(),
|
|
130
|
+
userId: userId ?? null,
|
|
131
|
+
status: 'signed_out' as const,
|
|
132
|
+
source: 'cached' as const,
|
|
133
|
+
};
|
|
134
|
+
if (!entitlementsEqual(state.desktopEntitlement, next)) {
|
|
135
|
+
setDesktopEntitlement(next);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
void syncAuth();
|
|
141
|
+
const timer = window.setInterval(() => {
|
|
142
|
+
void syncAuth();
|
|
143
|
+
}, ENTITLEMENT_REFRESH_INTERVAL_MS);
|
|
144
|
+
const onWindowFocus = () => {
|
|
145
|
+
void syncAuth();
|
|
146
|
+
};
|
|
147
|
+
const onManualRefresh = (event: Event) => {
|
|
148
|
+
const detail = (event as CustomEvent<{ resolve: () => void; reject: (error?: unknown) => void }>).detail;
|
|
149
|
+
void syncAuth()
|
|
150
|
+
.then(() => detail?.resolve())
|
|
151
|
+
.catch((error) => detail?.reject(error));
|
|
152
|
+
};
|
|
153
|
+
window.addEventListener('focus', onWindowFocus);
|
|
154
|
+
window.addEventListener(DESKTOP_ENTITLEMENT_REFRESH_EVENT, onManualRefresh);
|
|
155
|
+
|
|
156
|
+
return () => {
|
|
157
|
+
cancelled = true;
|
|
158
|
+
window.clearInterval(timer);
|
|
159
|
+
window.removeEventListener('focus', onWindowFocus);
|
|
160
|
+
window.removeEventListener(DESKTOP_ENTITLEMENT_REFRESH_EVENT, onManualRefresh);
|
|
161
|
+
};
|
|
162
|
+
}, [
|
|
163
|
+
getToken,
|
|
164
|
+
has,
|
|
165
|
+
isLoaded,
|
|
166
|
+
isSignedIn,
|
|
167
|
+
setChatAuthToken,
|
|
168
|
+
setDesktopEntitlement,
|
|
169
|
+
switchChatUserContext,
|
|
170
|
+
user?.publicMetadata,
|
|
171
|
+
userId,
|
|
172
|
+
]);
|
|
173
|
+
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
|
|
5
|
+
export const DESKTOP_ENTITLEMENT_REFRESH_EVENT = 'ifc-lite:desktop-entitlement-refresh';
|
|
6
|
+
|
|
7
|
+
interface DesktopEntitlementRefreshDetail {
|
|
8
|
+
resolve: () => void;
|
|
9
|
+
reject: (error?: unknown) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ENTITLEMENT_REFRESH_TIMEOUT_MS = 10_000;
|
|
13
|
+
|
|
14
|
+
export function requestDesktopEntitlementRefresh(): Promise<void> {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const timeoutId = globalThis.setTimeout(() => {
|
|
17
|
+
reject(new Error(
|
|
18
|
+
`Desktop entitlement refresh timed out after ${ENTITLEMENT_REFRESH_TIMEOUT_MS}ms — ` +
|
|
19
|
+
'no listener responded to the refresh event.',
|
|
20
|
+
));
|
|
21
|
+
}, ENTITLEMENT_REFRESH_TIMEOUT_MS);
|
|
22
|
+
|
|
23
|
+
window.dispatchEvent(new CustomEvent<DesktopEntitlementRefreshDetail>(
|
|
24
|
+
DESKTOP_ENTITLEMENT_REFRESH_EVENT,
|
|
25
|
+
{
|
|
26
|
+
detail: {
|
|
27
|
+
resolve: () => {
|
|
28
|
+
globalThis.clearTimeout(timeoutId);
|
|
29
|
+
resolve();
|
|
30
|
+
},
|
|
31
|
+
reject: (error?: unknown) => {
|
|
32
|
+
globalThis.clearTimeout(timeoutId);
|
|
33
|
+
reject(error);
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
getDefaultDesktopEntitlement,
|
|
7
|
+
hasDesktopFeatureAccess,
|
|
8
|
+
type DesktopEntitlement,
|
|
9
|
+
type DesktopFeature,
|
|
10
|
+
} from './desktop-product';
|
|
11
|
+
|
|
12
|
+
type HasFn = ((params: { plan?: string; feature?: string }) => boolean) | undefined;
|
|
13
|
+
|
|
14
|
+
interface ResolveDesktopEntitlementOptions {
|
|
15
|
+
userId: string | null;
|
|
16
|
+
token: string | null;
|
|
17
|
+
has: HasFn;
|
|
18
|
+
publicMetadata: Record<string, unknown> | null | undefined;
|
|
19
|
+
now?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface ResolvedDesktopEntitlement {
|
|
23
|
+
entitlement: DesktopEntitlement;
|
|
24
|
+
aiAssistantEnabled: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function resolveDesktopEntitlement(options: ResolveDesktopEntitlementOptions): ResolvedDesktopEntitlement {
|
|
28
|
+
// NOTE: `token`, `has`, `publicMetadata`, and `now` are accepted but
|
|
29
|
+
// intentionally unused in this initial implementation. Full Clerk-based
|
|
30
|
+
// entitlement resolution (plan checks via `has`, metadata-driven overrides,
|
|
31
|
+
// token validation, and time-based expiry via `now`) will be wired up once
|
|
32
|
+
// the Clerk integration is available in the desktop shell.
|
|
33
|
+
const { userId } = options;
|
|
34
|
+
const entitlement: DesktopEntitlement = {
|
|
35
|
+
...getDefaultDesktopEntitlement(),
|
|
36
|
+
userId,
|
|
37
|
+
};
|
|
38
|
+
const aiAssistantEnabled = hasDesktopFeatureAccess(entitlement, 'ai_assistant');
|
|
39
|
+
return { entitlement, aiAssistantEnabled };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function canUseDesktopFeatureOffline(entitlement: DesktopEntitlement, feature: DesktopFeature, now = Date.now()): boolean {
|
|
43
|
+
void now;
|
|
44
|
+
return hasDesktopFeatureAccess(entitlement, feature);
|
|
45
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
|
|
5
|
+
export type DesktopPlanTier = 'free' | 'pro';
|
|
6
|
+
export type DesktopEntitlementStatus = 'anonymous' | 'signed_out' | 'active' | 'trial' | 'expired' | 'grace_offline';
|
|
7
|
+
export type DesktopEntitlementSource = 'anonymous' | 'clerk_claims' | 'cached';
|
|
8
|
+
|
|
9
|
+
export type DesktopFeature =
|
|
10
|
+
| 'viewer_basic'
|
|
11
|
+
| 'workspace_restore'
|
|
12
|
+
| 'exports'
|
|
13
|
+
| 'ids_validation'
|
|
14
|
+
| 'bcf_issue_management'
|
|
15
|
+
| 'ai_assistant';
|
|
16
|
+
|
|
17
|
+
export interface DesktopEntitlement {
|
|
18
|
+
tier: DesktopPlanTier;
|
|
19
|
+
status: DesktopEntitlementStatus;
|
|
20
|
+
source: DesktopEntitlementSource;
|
|
21
|
+
userId: string | null;
|
|
22
|
+
validatedAt: number | null;
|
|
23
|
+
graceUntil: number | null;
|
|
24
|
+
trialEndsAt: number | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface DesktopUsageSummary {
|
|
28
|
+
type: 'credits' | 'requests';
|
|
29
|
+
used: number;
|
|
30
|
+
limit: number;
|
|
31
|
+
pct?: number;
|
|
32
|
+
resetAt?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface DesktopFeatureDefinition {
|
|
36
|
+
label: string;
|
|
37
|
+
description: string;
|
|
38
|
+
free: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const DESKTOP_FEATURES: Record<DesktopFeature, DesktopFeatureDefinition> = {
|
|
42
|
+
viewer_basic: {
|
|
43
|
+
label: 'Viewer features',
|
|
44
|
+
description: 'Core model viewing and inspection capabilities.',
|
|
45
|
+
free: true,
|
|
46
|
+
},
|
|
47
|
+
workspace_restore: {
|
|
48
|
+
label: 'Workspace restore',
|
|
49
|
+
description: 'Host-provided workspace persistence features.',
|
|
50
|
+
free: true,
|
|
51
|
+
},
|
|
52
|
+
exports: {
|
|
53
|
+
label: 'Exports',
|
|
54
|
+
description: 'Host-provided export integrations.',
|
|
55
|
+
free: true,
|
|
56
|
+
},
|
|
57
|
+
ids_validation: {
|
|
58
|
+
label: 'IDS validation',
|
|
59
|
+
description: 'Host-provided IDS workflows.',
|
|
60
|
+
free: true,
|
|
61
|
+
},
|
|
62
|
+
bcf_issue_management: {
|
|
63
|
+
label: 'BCF issue management',
|
|
64
|
+
description: 'Host-provided BCF workflows.',
|
|
65
|
+
free: true,
|
|
66
|
+
},
|
|
67
|
+
ai_assistant: {
|
|
68
|
+
label: 'Host AI assistant',
|
|
69
|
+
description: 'Optional host-provided AI integrations.',
|
|
70
|
+
free: true,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export function isDesktopBillingEnforced(): boolean {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getDesktopPlanTier(entitlementOrHasPro: DesktopEntitlement | boolean): DesktopPlanTier {
|
|
79
|
+
return typeof entitlementOrHasPro === 'boolean'
|
|
80
|
+
? (entitlementOrHasPro ? 'pro' : 'free')
|
|
81
|
+
: entitlementOrHasPro.tier;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function hasDesktopPro(entitlementOrHasPro: DesktopEntitlement | boolean): boolean {
|
|
85
|
+
return getDesktopPlanTier(entitlementOrHasPro) === 'pro';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function hasDesktopFeatureAccess(entitlementOrHasPro: DesktopEntitlement | boolean, feature: DesktopFeature): boolean {
|
|
89
|
+
return hasDesktopPro(entitlementOrHasPro) || DESKTOP_FEATURES[feature].free;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getDesktopFeatureCatalog(entitlementOrHasPro: DesktopEntitlement | boolean) {
|
|
93
|
+
return (Object.entries(DESKTOP_FEATURES) as Array<[DesktopFeature, DesktopFeatureDefinition]>).map(([key, value]) => ({
|
|
94
|
+
key,
|
|
95
|
+
...value,
|
|
96
|
+
enabled: hasDesktopFeatureAccess(entitlementOrHasPro, key),
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function buildDesktopUpgradeUrl(returnTo?: string): string {
|
|
101
|
+
const fallbackReturnTo = typeof window !== 'undefined'
|
|
102
|
+
? `${window.location.pathname}${window.location.search}`
|
|
103
|
+
: '/';
|
|
104
|
+
const nextReturnTo = returnTo ?? fallbackReturnTo;
|
|
105
|
+
return `/upgrade?returnTo=${encodeURIComponent(nextReturnTo)}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function getDefaultDesktopEntitlement(): DesktopEntitlement {
|
|
109
|
+
return {
|
|
110
|
+
tier: 'free',
|
|
111
|
+
status: 'anonymous',
|
|
112
|
+
source: 'anonymous',
|
|
113
|
+
userId: null,
|
|
114
|
+
validatedAt: null,
|
|
115
|
+
graceUntil: null,
|
|
116
|
+
trialEndsAt: null,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function getDesktopPlanSummary(entitlementOrHasPro: DesktopEntitlement | boolean, usage: DesktopUsageSummary | null): string {
|
|
121
|
+
void entitlementOrHasPro;
|
|
122
|
+
void usage;
|
|
123
|
+
return 'Desktop entitlements are host-defined and disabled in the open-source web viewer build.';
|
|
124
|
+
}
|