diff --git a/package-lock.json b/package-lock.json index 987454b..3610bee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,7 +46,7 @@ "mui-tel-input": "^7.0.0", "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", - "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#bin_modes_v2", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", @@ -146,9 +146,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -156,21 +156,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -233,14 +233,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -482,9 +482,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -507,14 +507,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2481,9 +2481,9 @@ } }, "node_modules/@mediapipe/tasks-vision": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.8.tgz", - "integrity": "sha512-Rp7ll8BHrKB3wXaRFKhrltwZl1CiXGdibPxuWXvqGnKTnv8fqa/nvftYNuSbf+pbJWKYCXdBtYTITdAUTGGh0Q==", + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz", + "integrity": "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==", "license": "Apache-2.0" }, "node_modules/@mui/core-downloads-tracker": { @@ -3239,28 +3239,27 @@ } }, "node_modules/@react-spring/animated": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz", - "integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.5.tgz", + "integrity": "sha512-Tqrwz7pIlsSDITzxoLS3n/v/YCUHQdOIKtOJf4yL6kYVSDTSmVK1LI1Q3M/uu2Sx4X3pIWF3xLUhlsA6SPNTNg==", "license": "MIT", "dependencies": { - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@react-spring/core": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz", - "integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.5.tgz", + "integrity": "sha512-rmEqcxRcu7dWh7MnCcMXLvrf6/SDlSokLaLTxiPlAYi11nN3B5oiCUAblO72o+9z/87j2uzxa2Inm8UbLjXA+w==", "license": "MIT", "dependencies": { - "@react-spring/animated": "~9.6.1", - "@react-spring/rafz": "~9.6.1", - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/animated": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" }, "funding": { "type": "opencollective", @@ -3271,34 +3270,34 @@ } }, "node_modules/@react-spring/rafz": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz", - "integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.5.tgz", + "integrity": "sha512-5ZenDQMC48wjUzPAm1EtwQ5Ot3bLIAwwqP2w2owG5KoNdNHpEJV263nGhCeKKmuA3vG2zLLOdu3or6kuDjA6Aw==", "license": "MIT" }, "node_modules/@react-spring/shared": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz", - "integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.5.tgz", + "integrity": "sha512-wdtoJrhUeeyD/PP/zo+np2s1Z820Ohr/BbuVYv+3dVLW7WctoiN7std8rISoYoHpUXtbkpesSKuPIw/6U1w1Pw==", "license": "MIT", "dependencies": { - "@react-spring/rafz": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/rafz": "~9.7.5", + "@react-spring/types": "~9.7.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@react-spring/three": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.6.1.tgz", - "integrity": "sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.7.5.tgz", + "integrity": "sha512-RxIsCoQfUqOS3POmhVHa1wdWS0wyHAUway73uRLp3GAL5U2iYVNdnzQsep6M2NZ994BlW8TcKuMtQHUqOsy6WA==", "license": "MIT", "dependencies": { - "@react-spring/animated": "~9.6.1", - "@react-spring/core": "~9.6.1", - "@react-spring/shared": "~9.6.1", - "@react-spring/types": "~9.6.1" + "@react-spring/animated": "~9.7.5", + "@react-spring/core": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" }, "peerDependencies": { "@react-three/fiber": ">=6.0", @@ -3307,45 +3306,44 @@ } }, "node_modules/@react-spring/types": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz", - "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.5.tgz", + "integrity": "sha512-HVj7LrZ4ReHWBimBvu2SKND3cDVUPWKLqRTmWe/fNY6o1owGOX0cAHbdPDTMelgBlVbrTKrre6lFkhqGZErK/g==", "license": "MIT" }, "node_modules/@react-three/drei": { - "version": "9.105.6", - "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.105.6.tgz", - "integrity": "sha512-JBgYeV36N9N9f1c3o1ZfLYW4rXZA7UQTq32Y8s3DEF6lwj1/y+RP/yq2VG5I8OzUPl7gsmWdy8fpWZgrlAqUpQ==", + "version": "9.122.0", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.122.0.tgz", + "integrity": "sha512-SEO/F/rBCTjlLez7WAlpys+iGe9hty4rNgjZvgkQeXFSiwqD4Hbk/wNHMAbdd8vprO2Aj81mihv4dF5bC7D0CA==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.11.2", - "@mediapipe/tasks-vision": "0.10.8", - "@monogrid/gainmap-js": "^3.0.5", - "@react-spring/three": "~9.6.1", - "@use-gesture/react": "^10.2.24", - "camera-controls": "^2.4.2", + "@babel/runtime": "^7.26.0", + "@mediapipe/tasks-vision": "0.10.17", + "@monogrid/gainmap-js": "^3.0.6", + "@react-spring/three": "~9.7.5", + "@use-gesture/react": "^10.3.1", + "camera-controls": "^2.9.0", "cross-env": "^7.0.3", - "detect-gpu": "^5.0.28", + "detect-gpu": "^5.0.56", "glsl-noise": "^0.0.0", - "hls.js": "1.3.5", - "maath": "^0.10.7", - "meshline": "^3.1.6", + "hls.js": "^1.5.17", + "maath": "^0.10.8", + "meshline": "^3.3.1", "react-composer": "^5.0.3", - "stats-gl": "^2.0.0", + "stats-gl": "^2.2.8", "stats.js": "^0.17.0", "suspend-react": "^0.1.3", - "three-mesh-bvh": "^0.7.0", - "three-stdlib": "^2.29.9", - "troika-three-text": "^0.49.0", + "three-mesh-bvh": "^0.7.8", + "three-stdlib": "^2.35.6", + "troika-three-text": "^0.52.0", "tunnel-rat": "^0.1.2", - "utility-types": "^3.10.0", - "uuid": "^9.0.1", - "zustand": "^3.7.1" + "utility-types": "^3.11.0", + "zustand": "^5.0.1" }, "peerDependencies": { - "@react-three/fiber": ">=8.0", - "react": ">=18.0", - "react-dom": ">=18.0", + "@react-three/fiber": "^8", + "react": "^18", + "react-dom": "^18", "three": ">=0.137" }, "peerDependenciesMeta": { @@ -3366,6 +3364,35 @@ "three": ">= 0.159.0" } }, + "node_modules/@react-three/drei/node_modules/zustand": { + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.14.tgz", + "integrity": "sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, "node_modules/@react-three/fiber": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.18.0.tgz", @@ -6986,9 +7013,9 @@ } }, "node_modules/axios": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.17.0.tgz", - "integrity": "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", @@ -6998,16 +7025,16 @@ } }, "node_modules/axios/node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -8050,9 +8077,9 @@ } }, "node_modules/deeks": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/deeks/-/deeks-3.1.0.tgz", - "integrity": "sha512-e7oWH1LzIdv/prMQ7pmlDlaVoL64glqzvNgkgQNgyec9ORPHrT2jaOqMtRyqJuwWjtfb6v+2rk9pmaHj+F137A==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/deeks/-/deeks-3.2.1.tgz", + "integrity": "sha512-D/o0k3pCG1aI1cxb/dDiWmtMc4Rh7ZQBybXpfMsw9Rbtqwg8kUA9SpYkWcw0pAUjZSnPm8MluctiS0o68r69jQ==", "license": "MIT", "engines": { "node": ">= 16" @@ -8182,9 +8209,9 @@ "license": "MIT" }, "node_modules/doc-path": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/doc-path/-/doc-path-4.1.1.tgz", - "integrity": "sha512-h1ErTglQAVv2gCnOpD3sFS6uolDbOKHDU1BZq+Kl3npPqroU3dYL42lUgMfd5UimlwtRgp7C9dLGwqQ5D2HYgQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/doc-path/-/doc-path-4.1.4.tgz", + "integrity": "sha512-yw5D++UCIB6a033PvQaUvSpW2QuKW0+DOId763n0Q4z3brxS7G8oQr8yBQ1nQFkognKrAVrV6I55TLeU9cfXTg==", "license": "MIT", "engines": { "node": ">=16" @@ -8357,6 +8384,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-cookie": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.3.2.tgz", @@ -8416,15 +8462,18 @@ } }, "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", "dev": true, "license": "MIT", "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -8764,9 +8813,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", "dev": true, "funding": [ { @@ -8977,15 +9026,15 @@ } }, "node_modules/form-data": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", - "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz", + "integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", + "hasown": "^2.0.4", "mime-types": "^2.1.35" }, "engines": { @@ -9060,18 +9109,21 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9316,9 +9368,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "dev": true, "license": "MIT", "dependencies": { @@ -9535,9 +9587,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9547,9 +9599,9 @@ } }, "node_modules/hls.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.3.5.tgz", - "integrity": "sha512-uybAvKS6uDe0MnWNEPnO0krWVr+8m2R0hJ/viql8H3MVK+itq8gGQuIYoFHL3rECkIpNH98Lw8YuuWMKZxp3Ew==", + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.16.tgz", + "integrity": "sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA==", "license": "Apache-2.0" }, "node_modules/hoist-non-react-statics": { @@ -9913,6 +9965,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -10356,10 +10424,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -10381,13 +10459,13 @@ } }, "node_modules/json-2-csv": { - "version": "5.5.10", - "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.10.tgz", - "integrity": "sha512-Dep8wO3Fr5wNjQevO2Z8Y7yeee/nYSGRsi7q6zJDKEVHxXkXT+v21vxHmDX923UzmCXXkSo62HaTz6eTWzFLaw==", + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.11.tgz", + "integrity": "sha512-kVuwgVL7rfad9ETf02ZZxJPuMR5ZSUn139+T34BfmVxYhb/IsAIm/LzEeQ8YLJmXfuQ5z7LUAFrgPZZM6VLJPw==", "license": "MIT", "dependencies": { - "deeks": "3.1.0", - "doc-path": "4.1.1" + "deeks": "3.2.1", + "doc-path": "4.1.4" }, "engines": { "node": ">= 16" @@ -11631,9 +11709,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", + "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", "dev": true, "funding": [ { @@ -11666,9 +11744,9 @@ "license": "MIT" }, "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", "dev": true, "funding": [ { @@ -11752,7 +11830,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#8a8ec79e9cc72bb770856c9e8e66f5294141da66", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#d6a992e46192a8ab8195235357318dc297738064", "dependencies": { "protobufjs": "^6.8.8" } @@ -12903,9 +12981,9 @@ } }, "node_modules/serialize-javascript": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", - "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.7.tgz", + "integrity": "sha512-YAy8Od6KV+uuwUuU50np8fGB/Aues6Y0nAhA9y/hId74PlKUcme4pXcBD46NWKr1Q4osN/iseZ17YqO1XfmI8g==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -13681,9 +13759,10 @@ "license": "MIT" }, "node_modules/three-mesh-bvh": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.6.tgz", - "integrity": "sha512-rCjsnxEqR9r1/C/lCqzGLS67NDty/S/eT6rAJfDvsanrIctTWdNoR4ZOGWewCB13h1QkVo2BpmC0wakj1+0m8A==", + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.8.tgz", + "integrity": "sha512-BGEZTOIC14U0XIRw3tO4jY7IjP7n7v24nv9JXS1CyeVRWOCkcOMhRnmENUjuV39gktAw4Ofhr0OvIAiTspQrrw==", + "deprecated": "Deprecated due to three.js version incompatibility. Please use v0.8.0, instead.", "license": "MIT", "peerDependencies": { "three": ">= 0.151.0" @@ -13861,14 +13940,14 @@ } }, "node_modules/troika-three-text": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.49.1.tgz", - "integrity": "sha512-lXGWxgjJP9kw4i4Wh+0k0Q/7cRfS6iOME4knKht/KozPu9GcFA9NnNpRvehIhrUawq9B0ZRw+0oiFHgRO+4Wig==", + "version": "0.52.4", + "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.4.tgz", + "integrity": "sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==", "license": "MIT", "dependencies": { "bidi-js": "^1.0.2", - "troika-three-utils": "^0.49.0", - "troika-worker-utils": "^0.49.0", + "troika-three-utils": "^0.52.4", + "troika-worker-utils": "^0.52.0", "webgl-sdf-generator": "1.1.1" }, "peerDependencies": { @@ -13876,18 +13955,18 @@ } }, "node_modules/troika-three-utils": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.49.0.tgz", - "integrity": "sha512-umitFL4cT+Fm/uONmaQEq4oZlyRHWwVClaS6ZrdcueRvwc2w+cpNQ47LlJKJswpqtMFWbEhOLy0TekmcPZOdYA==", + "version": "0.52.4", + "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.52.4.tgz", + "integrity": "sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==", "license": "MIT", "peerDependencies": { "three": ">=0.125.0" } }, "node_modules/troika-worker-utils": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.49.0.tgz", - "integrity": "sha512-1xZHoJrG0HFfCvT/iyN41DvI/nRykiBtHqFkGaGgJwq5iXfIZFBiPPEHFpPpgyKM3Oo5ITHXP5wM2TNQszYdVg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz", + "integrity": "sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==", "license": "MIT" }, "node_modules/ts-api-utils": { @@ -14341,19 +14420,6 @@ "node": ">= 4" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", diff --git a/package.json b/package.json index 07cb34d..76ac48b 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "mui-tel-input": "^7.0.0", "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", - "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#bin_modes_v2", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", diff --git a/src/3dModels/CameraControls/OrbitCameraControls.tsx b/src/3dModels/CameraControls/OrbitCameraControls.tsx index 4793024..7e098d6 100644 --- a/src/3dModels/CameraControls/OrbitCameraControls.tsx +++ b/src/3dModels/CameraControls/OrbitCameraControls.tsx @@ -1,5 +1,6 @@ -import { useThree, useFrame } from "@react-three/fiber"; -import { useCallback, useEffect, useRef } from "react"; +import React from "react"; +import { useThree } from "@react-three/fiber"; +import { useEffect, useRef } from "react"; import { Vector2, Vector3 } from "three"; interface CameraTarget { @@ -44,18 +45,6 @@ interface Props { * Wire it by passing a ref setter: onReset={fn => resetFn.current = fn} */ onReset?: (resetFn: () => void) => void; - /** - * Automatically spin the camera around the target on mount. - * Any user interaction (drag, pan, zoom, pinch) stops it permanently - * until the camera is reset (reset restarts it if this is still true). - * @default false - */ - autoRotate?: boolean; - /** - * Auto-rotate speed in radians per second. - * @default 0.3 - */ - autoRotateSpeed?: number; } export default function OrbitCameraControls(props: Props) { @@ -69,8 +58,6 @@ export default function OrbitCameraControls(props: Props) { initialRadius, maxRadius, onReset, - autoRotate = false, - autoRotateSpeed = 0.3, } = props; const { camera, gl } = useThree(); @@ -88,9 +75,6 @@ export default function OrbitCameraControls(props: Props) { const panCameraPosition = useRef(new Vector3()); const lastPinchDist = useRef(0); - // Auto-rotate: active until the user does *anything* (drag/pan/zoom/pinch) - const autoRotateActive = useRef(autoRotate); - // Spherical coords const spherical = useRef({ radius: initialRadius ?? 10, @@ -98,39 +82,6 @@ export default function OrbitCameraControls(props: Props) { phi: Math.PI / 2, // vertical angle }); - // Pulled out of the effect so both the DOM-event effect and the - // useFrame auto-rotate loop below can call it. - const updateCamera = useCallback(() => { - const { radius, theta, phi } = spherical.current; - - const x = radius * Math.sin(phi) * Math.sin(theta); - const y = radius * Math.cos(phi); - const z = radius * Math.sin(phi) * Math.cos(theta); - - camera.position.set( - targetRef.current.x + x, - targetRef.current.y + y, - targetRef.current.z + z - ); - camera.lookAt( - targetRef.current.x, - targetRef.current.y, - targetRef.current.z - ); - - // Shift the projected image without affecting orbit - const { width, height } = gl.domElement.getBoundingClientRect(); - (camera as any).setViewOffset(width, height, viewOffset ?? 0, 0, width, height); - }, [camera, gl, viewOffset]); - - // Drives the auto-spin every frame while it's active. Runs inside the - // R3F render loop, so it's cheap and stays in sync with everything else. - useFrame((_, delta) => { - if (!autoRotateActive.current) return; - spherical.current.theta += autoRotateSpeed * delta; - updateCamera(); - }); - useEffect(() => { // Sync radius whenever initialRadius prop changes (e.g. after bin data loads) spherical.current.radius = initialRadius ?? 10; @@ -138,6 +89,29 @@ export default function OrbitCameraControls(props: Props) { const canvas = gl.domElement; canvas.addEventListener("contextmenu", e => e.preventDefault()); + const updateCamera = () => { + const { radius, theta, phi } = spherical.current; + + const x = radius * Math.sin(phi) * Math.sin(theta); + const y = radius * Math.cos(phi); + const z = radius * Math.sin(phi) * Math.cos(theta); + + camera.position.set( + targetRef.current.x + x, + targetRef.current.y + y, + targetRef.current.z + z + ); + camera.lookAt( + targetRef.current.x, + targetRef.current.y, + targetRef.current.z + ); + + // Shift the projected image without affecting orbit + const { width, height } = gl.domElement.getBoundingClientRect(); + (camera as any).setViewOffset(width, height, viewOffset ?? 0, 0, width, height); + }; + // Hand the reset function to the caller so they can trigger it // (e.g. from a button in CameraOverlay) without needing an external ref. if (onReset) { @@ -150,25 +124,15 @@ export default function OrbitCameraControls(props: Props) { y: (target?.y ?? 0) + (offset?.y ?? 0), z: (target?.z ?? 0) + (offset?.z ?? 0), }; - // Resuming auto-rotate on reset feels natural — remove this - // line if you'd rather it stay stopped once the user has - // touched the camera. - autoRotateActive.current = autoRotate; updateCamera(); }); } updateCamera(); - const stopAutoRotate = () => { - autoRotateActive.current = false; - }; - const handleMouseDown = (e: MouseEvent) => { if (e.target !== canvas) return; - stopAutoRotate(); - lastPos.current = { x: e.clientX, y: e.clientY }; panCameraPosition.current.copy(camera.position); @@ -249,7 +213,6 @@ export default function OrbitCameraControls(props: Props) { if (e.target !== canvas) return; e.preventDefault(); - stopAutoRotate(); spherical.current.radius += e.deltaY * 0.01; spherical.current.radius = Math.max( @@ -263,8 +226,7 @@ export default function OrbitCameraControls(props: Props) { const handleTouchStart = (e: TouchEvent) => { if (e.target !== canvas) return; e.preventDefault(); - stopAutoRotate(); - + if (e.touches.length === 1) { isDragging.current = true; isPanning.current = false; @@ -282,10 +244,10 @@ export default function OrbitCameraControls(props: Props) { lastPinchDist.current = Math.sqrt(dx * dx + dy * dy); } }; - + const handleTouchMove = (e: TouchEvent) => { e.preventDefault(); - + if (e.touches.length === 1 && isDragging.current) { const deltaX = e.touches[0].clientX - lastPos.current.x; const deltaY = e.touches[0].clientY - lastPos.current.y; @@ -296,7 +258,7 @@ export default function OrbitCameraControls(props: Props) { } lastPos.current = { x: e.touches[0].clientX, y: e.touches[0].clientY }; updateCamera(); - + } else if (e.touches.length === 2) { // Pinch zoom const dx = e.touches[0].clientX - e.touches[1].clientX; @@ -306,13 +268,13 @@ export default function OrbitCameraControls(props: Props) { spherical.current.radius += pinchDelta * 0.05; spherical.current.radius = Math.max(3, Math.min(maxRadius ?? 30, spherical.current.radius)); lastPinchDist.current = dist; - + // Two-finger pan const midX = (e.touches[0].clientX + e.touches[1].clientX) / 2; const midY = (e.touches[0].clientY + e.touches[1].clientY) / 2; const panDeltaX = midX - lastPos.current.x; const panDeltaY = midY - lastPos.current.y; - + const distance = spherical.current.radius; const panSpeed = 0.002 * distance; const forward = new Vector3(); @@ -326,12 +288,12 @@ export default function OrbitCameraControls(props: Props) { targetRef.current.x += pan.x; targetRef.current.y += pan.y; targetRef.current.z += pan.z; - + lastPos.current = { x: midX, y: midY }; updateCamera(); } }; - + const handleTouchEnd = (e: TouchEvent) => { if (e.touches.length === 0) { isDragging.current = false; @@ -361,7 +323,7 @@ export default function OrbitCameraControls(props: Props) { canvas.removeEventListener("touchmove", handleTouchMove); canvas.removeEventListener("touchend", handleTouchEnd); }; - }, [camera, gl, target, offset, clampVerticalRotation, minPhi, maxPhi, initialRadius, maxRadius, onReset, autoRotate, updateCamera]); + }, [camera, gl, target, clampVerticalRotation, minPhi, maxPhi, initialRadius, maxRadius]); return null; } \ No newline at end of file diff --git a/src/app/Header.tsx b/src/app/Header.tsx index 6e4dbaf..5ff6184 100644 --- a/src/app/Header.tsx +++ b/src/app/Header.tsx @@ -16,7 +16,7 @@ const useStyles = makeStyles((theme: Theme) => { appBar: { zIndex: theme.zIndex.drawer + 1, backgroundImage: "none", // This prevents de-saturation of header in dark mode - backgroundColor: theme.palette.mode === "light" ? "#3b3b3b" : "#272727" + backgroundColor: theme.palette.header.main }, toolbar: { marginLeft: theme.spacing(0.5), @@ -128,4 +128,4 @@ export default function Header() { {isMobile && {setNavOpen(isOpen)}} sideIsOpen={navOpen} />} ) -} \ No newline at end of file +} diff --git a/src/bin/3dView/Scene/Bin3dView.tsx b/src/bin/3dView/Scene/Bin3dView.tsx index ff96995..0d15558 100644 --- a/src/bin/3dView/Scene/Bin3dView.tsx +++ b/src/bin/3dView/Scene/Bin3dView.tsx @@ -145,8 +145,6 @@ export default function Bin3dView(props: Props) { { resetCameraFn.current = fn; }} diff --git a/src/bin/BinConditioningInteraction.tsx b/src/bin/BinConditioningInteraction.tsx index 92a4f31..d729462 100644 --- a/src/bin/BinConditioningInteraction.tsx +++ b/src/bin/BinConditioningInteraction.tsx @@ -85,14 +85,10 @@ interface Props { sink: Component; grain?: pond.Grain; customGrain?: pond.GrainSettings - /** - * if true, the button to update the interaction will be hidden because it will be assumed that the parent will handle the interaction - */ - parentUpdate?: boolean } export default function BinConditioningInteraction(props: Props) { - const { interaction, source, sink, grain, deviceId, customGrain, parentUpdate} = props; + const { interaction, source, sink, grain, deviceId, customGrain } = props; const [sliderVals, setSliderVals] = useState>(new Map()); const [sliderMarks, setSliderMarks] = useState>(new Map()); //this is the emc value calculated from the interactions temp and humidity conditions @@ -147,13 +143,13 @@ export default function BinConditioningInteraction(props: Props) { const updateInteraction = () => { interactionAPI - .updateInteraction(deviceId, interaction.settings, as) - .then(resp => { - openSnack("Updated Interaction Conditions"); - }) - .catch(err => { - openSnack("Failed to Update Interaction Conditions"); - }); + .updateInteraction(deviceId, interaction.settings, as) + .then(resp => { + openSnack("Updated Interaction Conditions"); + }) + .catch(err => { + openSnack("Failed to Update Interaction Conditions"); + }); }; const customMark = (val: string, arrowColor: string) => { @@ -242,7 +238,6 @@ export default function BinConditioningInteraction(props: Props) { max={describer.max()} value={sliderVals.get(condition.measurementType) ?? describer.min()} onChange={(_, val) => { - //note that changing it here like this is what is changing it in the interaction itself condition.value = Math.round(describer.toStored(val as number)); let sliders = cloneDeep(sliderVals); sliders.set(condition.measurementType, val as number); @@ -254,16 +249,14 @@ export default function BinConditioningInteraction(props: Props) { ); })} - {!parentUpdate && - - } + ); diff --git a/src/bin/bin3dVisualizer.tsx b/src/bin/bin3dVisualizer.tsx index 9478d83..9bdfd0c 100644 --- a/src/bin/bin3dVisualizer.tsx +++ b/src/bin/bin3dVisualizer.tsx @@ -11,7 +11,6 @@ import { CableData } from "bin/3dView/Data/BuildCableData"; import ModeChangeDialog from "bin/conditioning/modeChangeDialog"; import { cloneDeep } from "lodash"; import { useMobile } from "hooks"; -import BinModeController from "./binModes/BinModeController"; interface Props { bin: Bin @@ -36,7 +35,6 @@ export default function bin3dVisualizer(props: Props){ const [showMoistureHeatmap, setShowMoistureHeatmap] = useState(false) const [binDisplay, setBinDisplay] = useState("temp") const [binMode, setBinMode] = useState(pond.BinMode.BIN_MODE_NONE) - const [newMode, setNewMode] = useState(pond.BinMode.BIN_MODE_NONE) const [openModeChange, setOpenModeChange] = useState(false) const [selectedCable, setSelectedCable] = useState(undefined) const [selectedNode, setSelectedNode] = useState(undefined) @@ -60,6 +58,14 @@ export default function bin3dVisualizer(props: Props){ setBinMode(bin.settings.mode) },[bin]) + const updateBin = () => { + if(updateBinCallback){ + let clone = cloneDeep(bin) + clone.settings.mode = binMode + updateBinCallback(clone) + } + }; + const binModeControl = () => { return ( @@ -80,10 +86,8 @@ export default function bin3dVisualizer(props: Props){ '&.Mui-focused .MuiOutlinedInput-notchedOutline': { border: 'none' }, }} onChange={event => { - setNewMode(event.target.value as pond.BinMode) + setBinMode(event.target.value as pond.BinMode) setOpenModeChange(true) - // for the re-built modes, each one will have its own dialog box and this will just control which one to open rather than the single dialog for all of them - // and having the mode determine what to show in the dialog }} > Select Mode.. @@ -323,7 +327,7 @@ export default function bin3dVisualizer(props: Props){ }} /> } - {/* { setModeChangeInProgress(false) }} - /> */} - {setOpenModeChange(false)}} - modeUpdated={(newMode) => { - setBinMode(newMode) - }} + /> void - bin: Bin - binPrefs?: Map - devices: Device[] - componentDevices: Map - componentMap: Map - modeUpdated?: (mode: pond.BinMode) => void -} - -export default function BinModeController(props: Props) { - const {open, onClose, newMode, devices, componentDevices, componentMap, binPrefs, bin, modeUpdated} = props - const [showProgress, setShowProgress] = useState(false) - const [deviceComponents, setDeviceComponents] = useState>(new Map()) - const [promiseStages, setPromiseStages] = useState([]) - const interactionAPI = useInteractionsAPI() - const componentAPI = useComponentAPI() - const binAPI = useBinAPI(); - - //the use effects for the initial setup of what will be needed - useEffect(()=>{ - let newMap:Map = new Map() - componentMap.forEach((comp, key) => { - //first we need to get the device id this component belongs to - let dev = componentDevices.get(key) - if(dev){ - //check if the key exists in the new map yet - if(newMap.has(dev)){ - newMap.get(dev)?.push(comp) - }else{ - newMap.set(dev, [comp]) - } - } - }) - setDeviceComponents(newMap) - },[componentDevices, componentMap]) - - //steps involved for devices when changing the bin mode: - //remove conflicting interactions - //add new interactions - //updating the controllers - - const closeDialog = () => { - setShowProgress(false) - onClose() - } - - const buildStages = (deviceData: DeviceChangeData[]) => { - //build the stages to pass into the PromiseProgress - //stage one is to remove conflicting interactions - let stages: Stage[] = [] - let stage1: Stage = { - title: "Remove Interactions", - steps: [] - } - let stage2: Stage = { - title: "Add New Interactions", - steps: [] - } - let stage3: Stage = { - title: "Update Controllers", - steps: [] - } - deviceData.forEach(data => { - data.toRemove.forEach(interaction => { - let newStep: Step = { - title: "Removing Interaction", - promise: () => interactionAPI.removeInteraction(data.deviceId, interaction.key()) - } - stage1.steps.push(newStep); - }) - let newInteractions = data.toAdd - if(newInteractions){ - stage2.steps.push({ - title: "Adding Interactions", - promise: () => interactionAPI.addMultiInteractions(data.deviceId, newInteractions) - }) - } - - data.controllers.forEach(controller => { - let newStep: Step = { - title: "Updating " + controller.name(), - promise: () => componentAPI.update(data.deviceId, controller.settings) - } - stage3.steps.push(newStep) - }) - }) - - if(stage1.steps.length > 0){ - stages.push(stage1) - } - if(stage2.steps.length > 0){ - stages.push(stage2) - } - if(stage3.steps.length > 0){ - stages.push(stage3) - } - //stage 4 is to update the bin with the new mode - let stage4: Stage = { - title: "Update Bin With New Mode", - steps: [ - { - title: "Update " + bin.name(), - promise: () => { - let clone = cloneDeep(bin.settings) - clone.mode = newMode - //this will set the bin to use the auto top nodes for cables when the bin is going into storage mode, and turn them off if the bin is being conditioned - if(newMode === pond.BinMode.BIN_MODE_STORAGE){ - clone.autoGrainNode = true - }else{ - clone.autoGrainNode = false - } - return binAPI.updateBin(bin.key(), clone) - }, - onComplete: () => modeUpdated?.(newMode) - } - ] - } - stages.push(stage4) - - //set those stages to a state variable - setPromiseStages(stages) - } - - /** - * the progress step is the last step of each mode change that shows what is being done and what succeeded/failed - * initially i was going to put it here because it would effectively be the same thing for each mode, however depending - * on how i decide to handle the api calls, and since i am thinking about passing the functions into the children it may go into each mode component - * - */ - const progressContent = () => { - return ( - - Change Mode - - { - //this is just a function that is rin as soon as the start button is clicked it can be used to disable things while the change is in progress if we want to - }} - onComplete={()=>{ - closeDialog() - }} - /> - - - - - - ) - } - - const modeContent = () => { - switch(newMode){ - case pond.BinMode.BIN_MODE_DRYING: - //setNumSteps(DryingStepCount) - return { - buildStages(deviceData) - setShowProgress(true) - }} - /> - case pond.BinMode.BIN_MODE_HYDRATING: - return { - buildStages(deviceData) - setShowProgress(true) - }} - /> - case pond.BinMode.BIN_MODE_COOLDOWN: - return { - buildStages(deviceData) - setShowProgress(true) - }} - /> - case pond.BinMode.BIN_MODE_THREE_PHASE_FAN_DRYING: - return - default: - return { - buildStages(deviceData) - setShowProgress(true) - }}/> - } - } - - return ( - - {showProgress ? progressContent() : modeContent()} - - ) -} \ No newline at end of file diff --git a/src/bin/binModes/CooldownMode.tsx b/src/bin/binModes/CooldownMode.tsx deleted file mode 100644 index 7e4c2e5..0000000 --- a/src/bin/binModes/CooldownMode.tsx +++ /dev/null @@ -1,394 +0,0 @@ -import { Box, Theme, Stepper, Step, StepLabel, Typography, Button, Autocomplete, TextField, DialogTitle, DialogContent, DialogActions, CircularProgress } from "@mui/material"; -import { makeStyles } from "@mui/styles"; -import ConditioningSelector from "bin/conditioning/conditioningSelector"; -import { Component, Device, Interaction } from "models"; -import { Ambient } from "models/Ambient"; -import { Controller } from "models/Controller"; -import { Plenum } from "models/Plenum"; -import { pond, quack } from "protobuf-ts/pond"; -import { useEffect, useState } from "react"; -import { ComponentSet } from "bin/conditioning/pickComponentSet" -import { componentIDToString, sameComponentID } from "pbHelpers/Component"; -import moment from "moment"; -import { lowerCase } from "lodash"; -import { describeMeasurement } from "pbHelpers/MeasurementDescriber"; -import { useGlobalState, useInteractionsAPI } from "providers"; -import ConditionDisplay from "./conditionDisplay"; -import React from "react"; -import { DeviceChangeData } from "./BinModeController"; -import { GrainCable } from "models/GrainCable"; - - -const useStyles = makeStyles((theme: Theme) => { - return ({ - stepper: { - padding: theme.spacing(0.5) - }, - }) -}); - -interface Step { - label: string; - completed?: boolean; -} - -interface Option { - label: string; - device: Device; - icon?: string; - } - -interface Props { - devices: Device[] - deviceComponents: Map - binPrefs?: Map - grain?: pond.Grain - customGrain?: pond.GrainSettings - cancel: () => void - confirm: (deviceData: DeviceChangeData[]) => void -} - -const steps = [{label: "Device"}, {label: "Interaction"}] - -//this is our simple drying mode the way it currently works, just building the dialog to be a little more trnasparent and customizable as to what the interaction is doing -export default function CooldownMode(props: Props){ - const {devices, deviceComponents, binPrefs, grain, customGrain, cancel, confirm} = props - const classes = useStyles() - const [{user}] = useGlobalState() - const interactionAPI = useInteractionsAPI() - const [options, setOptions] = useState([]) - const [deviceOption, setDeviceOption] = useState