diff --git a/website/package-lock.json b/website/package-lock.json index 0b30d44d..641b5c5f 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -18,6 +18,7 @@ "immer": "^10.1.1", "lucide-svelte": "^0.395.0", "mapbox-gl": "^3.4.0", + "mapillary-js": "^4.1.2", "mode-watcher": "^0.3.1", "sortablejs": "^1.15.2", "svelte-i18n": "^4.0.0", @@ -1397,6 +1398,11 @@ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "dev": true }, + "node_modules/@types/earcut": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.4.tgz", + "integrity": "sha512-qp3m9PPz4gULB9MhjGID7wpo3gJ4bTGXm7ltNDsmOvsPduTeHp8wSW9YckBj3mljeOh4F0m2z/0JKAALRKbmLQ==" + }, "node_modules/@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", @@ -1480,12 +1486,32 @@ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" }, + "node_modules/@types/pako": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.7.tgz", + "integrity": "sha512-YBtzT2ztNF6R/9+UXj2wTGFnC9NklAnASt3sC0h2m1bbH7G6FyBIkt4AN8ThZpNfxUo1b2iMVO0UawiJymEt8A==" + }, + "node_modules/@types/pbf": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", + "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" + }, + "node_modules/@types/polylabel": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/polylabel/-/polylabel-1.1.3.tgz", + "integrity": "sha512-9Zw2KoDpi+T4PZz2G6pO2xArE0m/GSMTW1MIxF2s8ZY8x9XDO6fv9um0ydRGvcbkFLlaq8yNK6eZxnmMZtDgWQ==" + }, "node_modules/@types/pug": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==", "dev": true }, + "node_modules/@types/rbush": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-3.0.3.tgz", + "integrity": "sha512-lX55lR0iYCgapxD3IrgujpQA1zDxwZI5qMRelKvmKAsSMplFVr7wmMpG7/6+Op2tjrgEex8o3vjg8CRDrRNYxg==" + }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", @@ -1500,6 +1526,16 @@ "integrity": "sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==", "dev": true }, + "node_modules/@types/three": { + "version": "0.134.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.134.0.tgz", + "integrity": "sha512-4YB+99Rgqq27EjiYTItEoZtdjLnTh8W9LxowgpC9eWsjaQJIL4Kn/ZcUKAnW3gB/jS4hqGN8iqmid+RcUZDzpA==" + }, + "node_modules/@types/virtual-dom": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/virtual-dom/-/virtual-dom-2.1.4.tgz", + "integrity": "sha512-Y7L/frVydXRd16MevczslJZQu+QWsrqZlj6ytk7mST3xen0fkx7Ollw31By/89A8Wq+nfNWm/IoTR1ac/0fRhA==" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.13.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", @@ -1925,6 +1961,11 @@ "node": ">=8" } }, + "node_modules/browser-split": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browser-split/-/browser-split-0.0.1.tgz", + "integrity": "sha512-JhvgRb2ihQhsljNda3BI8/UcRHVzrVwo3Q+P8vDtSiyobXuFpuZ9mq+MbRGMnC22CjW3RrfXdg6j6ITX8M+7Ow==" + }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", @@ -2054,6 +2095,14 @@ "node": ">=8" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001606", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz", @@ -2454,6 +2503,11 @@ "node": ">=6.0.0" } }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "node_modules/earcut": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", @@ -2483,6 +2537,16 @@ "once": "^1.4.0" } }, + "node_modules/error": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/error/-/error-4.4.0.tgz", + "integrity": "sha512-SNDKualLUtT4StGFP7xNfuFybL2f6iJujFtrWuvJqGbVQGaN+adE23veqzPz1hjUjTunLi2EnJ+0SJxtbJreKw==", + "dependencies": { + "camelize": "^1.0.0", + "string-template": "~0.2.0", + "xtend": "~4.0.0" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2873,6 +2937,14 @@ "node": ">=0.10.0" } }, + "node_modules/ev-store": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ev-store/-/ev-store-7.0.0.tgz", + "integrity": "sha512-otazchNRnGzp2YarBJ+GXKVGvhxVATB1zmaStxJBYet0Dyq7A9VhH8IUEB/gRcL6Ch52lfpgPTRJ2m49epyMsQ==", + "dependencies": { + "individual": "^3.0.0" + } + }, "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", @@ -3166,6 +3238,15 @@ "node": "*" } }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -3392,6 +3473,11 @@ "node": ">=8" } }, + "node_modules/individual": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/individual/-/individual-3.0.0.tgz", + "integrity": "sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3481,6 +3567,14 @@ "node": ">=0.12.0" } }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -3678,6 +3772,14 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -3766,6 +3868,51 @@ "vt-pbf": "^3.1.3" } }, + "node_modules/mapillary-js": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/mapillary-js/-/mapillary-js-4.1.2.tgz", + "integrity": "sha512-LYj6xbp/Y9wfBkr/prRwgJGb3+KwvzUri0yl5QEpMEH7oC1p52ErshWmPXysKefmm6JaFML4D7FJ89viwJ4T5g==", + "dependencies": { + "@types/earcut": "^2.1.1", + "@types/node": "^14.14.31", + "@types/pako": "^1.0.2", + "@types/pbf": "^3.0.2", + "@types/polylabel": "^1.0.5", + "@types/rbush": "^3.0.0", + "@types/three": "^0.134.0", + "@types/virtual-dom": "^2.1.1", + "earcut": "^2.2.3", + "martinez-polygon-clipping": "^0.7.1", + "pako": "^2.0.4", + "pbf": "^3.2.1", + "polylabel": "^1.1.0", + "rbush": "^3.0.1", + "rxjs": "^7.3.0", + "s2-geometry": "^1.2.10", + "three": "^0.134.0", + "virtual-dom": "^2.1.1" + } + }, + "node_modules/mapillary-js/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==" + }, + "node_modules/martinez-polygon-clipping": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/martinez-polygon-clipping/-/martinez-polygon-clipping-0.7.3.tgz", + "integrity": "sha512-i1CM1sgj6v7Vy2ZeaxZKmAKAin1QApPaBKk/kW8QENxTrWliTHDDEBhwQz0gdFx+F3JkWiIz4y5IhoaGkcfOIA==", + "dependencies": { + "robust-predicates": "^2.0.4", + "splaytree": "^0.1.4", + "tinyqueue": "^1.2.0" + } + }, + "node_modules/martinez-polygon-clipping/node_modules/tinyqueue": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-1.2.3.tgz", + "integrity": "sha512-Qz9RgWuO9l8lT+Y9xvbzhPT2efIUIFd69N7eF7tJ9lnQl0iLj1M7peK7IoUGZL9DJHw9XftqLreccfxcQgYLxA==" + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -3869,6 +4016,14 @@ "node": ">=4" } }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -4142,6 +4297,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4287,6 +4447,14 @@ "node": ">= 6" } }, + "node_modules/polylabel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/polylabel/-/polylabel-1.1.0.tgz", + "integrity": "sha512-bxaGcA40sL3d6M4hH72Z4NdLqxpXRsCFk8AITYg6x1rn1Ei3izf00UMLklerBZTO49aPA3CYrIwVulx2Bce2pA==", + "dependencies": { + "tinyqueue": "^2.0.3" + } + }, "node_modules/postcss": { "version": "8.4.38", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", @@ -4493,6 +4661,14 @@ "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/protocol-buffers-schema": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", @@ -4551,6 +4727,14 @@ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" }, + "node_modules/rbush": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "dependencies": { + "quickselect": "^2.0.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -4779,6 +4963,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz", + "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" + }, "node_modules/rollup": { "version": "4.14.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.0.tgz", @@ -4840,6 +5029,22 @@ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/s2-geometry": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/s2-geometry/-/s2-geometry-1.2.10.tgz", + "integrity": "sha512-5WejfQu1XZ25ZerW8uL6xP1sM2krcOYKhI6TbfybGRf+vTQLrm3E+4n0+1lWg+MYqFjPzoe51zKhn2sBRMCt5g==", + "dependencies": { + "long": "^3.2.0" + } + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -5009,6 +5214,16 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" }, + "node_modules/splaytree": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-0.1.4.tgz", + "integrity": "sha512-D50hKrjZgBzqD3FT2Ek53f2dcDLAQT8SSGrzj3vidNH5ISRgceeGVJ2dQIthKOuayqFXfFjXheHNo4bbt9LhRQ==" + }, + "node_modules/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==" + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -5902,6 +6117,11 @@ "node": ">=0.8" } }, + "node_modules/three": { + "version": "0.134.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.134.0.tgz", + "integrity": "sha512-LbBerg7GaSPjYtTOnu41AMp7tV6efUNR3p4Wk5NzkSsNTBuA5mDGOfwwZL1jhhVMLx9V20HolIUo0+U3AXehbg==" + }, "node_modules/timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -6091,6 +6311,26 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/virtual-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/virtual-dom/-/virtual-dom-2.1.1.tgz", + "integrity": "sha512-wb6Qc9Lbqug0kRqo/iuApfBpJJAq14Sk1faAnSmtqXiwahg7PVTvWMs9L02Z8nNIMqbwsxzBAA90bbtRLbw0zg==", + "dependencies": { + "browser-split": "0.0.1", + "error": "^4.3.0", + "ev-store": "^7.0.0", + "global": "^4.3.0", + "is-object": "^1.0.1", + "next-tick": "^0.2.2", + "x-is-array": "0.1.0", + "x-is-string": "0.1.0" + } + }, + "node_modules/virtual-dom/node_modules/next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==" + }, "node_modules/vite": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz", @@ -6276,6 +6516,16 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/x-is-array": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-array/-/x-is-array-0.1.0.tgz", + "integrity": "sha512-goHPif61oNrr0jJgsXRfc8oqtYzvfiMJpTqwE7Z4y9uH+T3UozkGqQ4d2nX9mB9khvA8U2o/UbPOFjgC7hLWIA==" + }, + "node_modules/x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/website/package.json b/website/package.json index c71313a6..8b06b329 100644 --- a/website/package.json +++ b/website/package.json @@ -51,6 +51,7 @@ "immer": "^10.1.1", "lucide-svelte": "^0.395.0", "mapbox-gl": "^3.4.0", + "mapillary-js": "^4.1.2", "mode-watcher": "^0.3.1", "sortablejs": "^1.15.2", "svelte-i18n": "^4.0.0", diff --git a/website/src/lib/components/App.svelte b/website/src/lib/components/App.svelte index b57f12cf..68d74cf5 100644 --- a/website/src/lib/components/App.svelte +++ b/website/src/lib/components/App.svelte @@ -6,6 +6,7 @@ import Map from '$lib/components/Map.svelte'; import Menu from '$lib/components/Menu.svelte'; import Toolbar from '$lib/components/toolbar/Toolbar.svelte'; + import StreetViewControl from '$lib/components/street-view-control/StreetViewControl.svelte'; import LayerControl from '$lib/components/layer-control/LayerControl.svelte'; import { Toaster } from '$lib/components/ui/sonner'; @@ -20,6 +21,7 @@ + diff --git a/website/src/lib/components/Menu.svelte b/website/src/lib/components/Menu.svelte index a86438f4..2fe77239 100644 --- a/website/src/lib/components/Menu.svelte +++ b/website/src/lib/components/Menu.svelte @@ -32,7 +32,8 @@ File, View, FilePen, - HeartHandshake + HeartHandshake, + PersonStanding } from 'lucide-svelte'; import { @@ -77,7 +78,8 @@ currentOverlays, previousOverlays, distanceMarkers, - directionMarkers + directionMarkers, + streetViewSource } = settings; $: if ($mode === 'system') { @@ -326,6 +328,18 @@ + + + + {$_('menu.street_view_source')} + + + + {$_('menu.mapillary')} + {$_('menu.google')} + + + (layerSettingsOpen = true)}> {$_('menu.layers')} diff --git a/website/src/lib/components/custom-control/CustomControl.svelte b/website/src/lib/components/custom-control/CustomControl.svelte index 735569d4..f7830ebe 100644 --- a/website/src/lib/components/custom-control/CustomControl.svelte +++ b/website/src/lib/components/custom-control/CustomControl.svelte @@ -1,3 +1,15 @@ + + diff --git a/website/src/lib/components/street-view-control/Google.ts b/website/src/lib/components/street-view-control/Google.ts new file mode 100644 index 00000000..3057f255 --- /dev/null +++ b/website/src/lib/components/street-view-control/Google.ts @@ -0,0 +1,33 @@ +import { resetCursor, setCrosshairCursor } from "$lib/utils"; +import type mapboxgl from "mapbox-gl"; + +export class GoogleRedirect { + map: mapboxgl.Map; + enabled = false; + + constructor(map: mapboxgl.Map) { + this.map = map; + } + + add() { + if (this.enabled) return; + + this.enabled = true; + setCrosshairCursor(); + this.map.on('click', this.openStreetView); + } + + remove() { + if (!this.enabled) return; + + this.enabled = false; + resetCursor(); + this.map.off('click', this.openStreetView); + } + + openStreetView(e) { + window.open( + `https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${e.lngLat.lat},${e.lngLat.lng}` + ); + } +} \ No newline at end of file diff --git a/website/src/lib/components/street-view-control/Mapillary.ts b/website/src/lib/components/street-view-control/Mapillary.ts new file mode 100644 index 00000000..dc7d4f32 --- /dev/null +++ b/website/src/lib/components/street-view-control/Mapillary.ts @@ -0,0 +1,123 @@ +import mapboxgl from "mapbox-gl"; +import { Viewer } from 'mapillary-js/dist/mapillary.module'; +import 'mapillary-js/dist/mapillary.css'; +import { t } from "svelte-i18n"; +import { resetCursor, setPointerCursor } from "$lib/utils"; + +const mapillarySource = { + type: 'vector', + tiles: ['https://tiles.mapillary.com/maps/vtp/mly1_computed_public/2/{z}/{x}/{y}?access_token=MLY|4381405525255083|3204871ec181638c3c31320490f03011'], + minzoom: 6, + maxzoom: 14, +}; + +const mapillarySequenceLayer = { + id: 'mapillary-sequence', + type: 'line', + source: 'mapillary', + 'source-layer': 'sequence', + paint: { + 'line-color': 'rgb(53, 175, 109)', + 'line-opacity': 0.5, + 'line-width': 4, + }, + layout: { + 'line-cap': 'round', + 'line-join': 'round', + }, +}; + +const mapillaryImageLayer = { + id: 'mapillary-image', + type: 'circle', + source: 'mapillary', + 'source-layer': 'image', + paint: { + 'circle-color': 'rgb(53, 175, 109)', + 'circle-radius': 4, + 'circle-opacity': 0.5, + }, +}; + +export class MapillaryLayer { + map: mapboxgl.Map; + popup: mapboxgl.Popup; + viewer: Viewer; + addBinded = this.add.bind(this); + onMouseEnterBinded = this.onMouseEnter.bind(this); + onMouseLeaveBinded = this.onMouseLeave.bind(this); + + constructor(map: mapboxgl.Map) { + this.map = map; + + const container = document.createElement('div'); + container.style.width = '400px'; + container.style.height = '300px'; + container.className = 'rounded-md border-background border-2' + + this.viewer = new Viewer({ + accessToken: 'MLY|4381405525255083|3204871ec181638c3c31320490f03011', + container, + }); + + this.popup = new mapboxgl.Popup({ + closeButton: false, + maxWidth: container.style.width, + }).setDOMContent(container); + + this.viewer.on('position', async () => { + if (this.popup.isOpen()) { + let latLng = await this.viewer.getPosition(); + this.popup.setLngLat(latLng); + if (!this.map.getBounds().contains(latLng)) { + this.map.panTo(latLng); + } + } + }); + } + + add() { + if (!this.map.getSource('mapillary')) { + this.map.addSource('mapillary', mapillarySource); + } + if (!this.map.getLayer('mapillary-sequence')) { + this.map.addLayer(mapillarySequenceLayer); + } + if (!this.map.getLayer('mapillary-image')) { + this.map.addLayer(mapillaryImageLayer); + } + this.map.on('style.load', this.addBinded); + this.map.on('mouseenter', 'mapillary-image', this.onMouseEnterBinded); + this.map.on('mouseleave', 'mapillary-image', this.onMouseLeaveBinded); + } + + remove() { + this.map.off('style.load', this.addBinded); + this.map.off('mouseenter', 'mapillary-image', this.onMouseEnterBinded); + this.map.off('mouseleave', 'mapillary-image', this.onMouseLeaveBinded); + + if (this.map.getLayer('mapillary-image')) { + this.map.removeLayer('mapillary-image'); + } + if (this.map.getLayer('mapillary-sequence')) { + this.map.removeLayer('mapillary-sequence'); + } + if (this.map.getSource('mapillary')) { + this.map.removeSource('mapillary'); + } + + this.popup.remove(); + } + + onMouseEnter(e: mapboxgl.MapLayerMouseEvent) { + this.popup.addTo(this.map).setLngLat(e.lngLat); + this.viewer.resize(); + this.viewer.moveTo(e.features[0].properties.id); + + setPointerCursor(); + } + + onMouseLeave() { + resetCursor(); + } +} \ No newline at end of file diff --git a/website/src/lib/components/street-view-control/StreetViewControl.svelte b/website/src/lib/components/street-view-control/StreetViewControl.svelte new file mode 100644 index 00000000..3f8d0e67 --- /dev/null +++ b/website/src/lib/components/street-view-control/StreetViewControl.svelte @@ -0,0 +1,43 @@ + + + + + + + diff --git a/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts b/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts index 43be8818..6e4dfb21 100644 --- a/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts +++ b/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts @@ -10,7 +10,7 @@ import { _ } from "svelte-i18n"; import { dbUtils, type GPXFileWithStatistics } from "$lib/db"; import { selection } from "$lib/components/file-list/Selection"; import { ListFileItem, ListTrackItem, ListTrackSegmentItem } from "$lib/components/file-list/FileList"; -import { currentTool, Tool } from "$lib/stores"; +import { currentTool, streetViewEnabled, Tool } from "$lib/stores"; import { resetCursor, setCrosshairCursor, setGrabbingCursor } from "$lib/utils"; export const canChangeStart = writable(false); @@ -227,6 +227,10 @@ export class RoutingControls { } showTemporaryAnchor(e: any) { + if (get(streetViewEnabled)) { + return; + } + if (!get(selection).hasAnyParent(new ListTrackSegmentItem(this.fileId, e.features[0].properties.trackIndex, e.features[0].properties.segmentIndex))) { return; } @@ -376,6 +380,10 @@ export class RoutingControls { } async appendAnchor(e: mapboxgl.MapMouseEvent) { // Add a new anchor to the end of the last segment + if (get(streetViewEnabled)) { + return; + } + this.appendAnchorWithCoordinates({ lat: e.lngLat.lat, lon: e.lngLat.lng diff --git a/website/src/lib/db.ts b/website/src/lib/db.ts index 034b862f..8af0bd54 100644 --- a/website/src/lib/db.ts +++ b/website/src/lib/db.ts @@ -101,6 +101,7 @@ export const settings = { directionMarkers: dexieSettingStore('directionMarkers', false), distanceMarkers: dexieSettingStore('distanceMarkers', false), stravaHeatmapColor: dexieSettingStore('stravaHeatmapColor', 'bluered'), + streetViewSource: dexieSettingStore('streetViewSource', 'mapillary'), fileOrder: dexieSettingStore('fileOrder', []), defaultOpacity: dexieSettingStore('defaultOpacity', 0.7), defaultWeight: dexieSettingStore('defaultWeight', 5), diff --git a/website/src/lib/stores.ts b/website/src/lib/stores.ts index 9a34f4ec..84d294fd 100644 --- a/website/src/lib/stores.ts +++ b/website/src/lib/stores.ts @@ -132,6 +132,7 @@ export enum Tool { } export const currentTool = writable(null); export const splitAs = writable(SplitType.FILES); +export const streetViewEnabled = writable(false); export function newGPXFile() { const newFileName = get(_)("menu.new_file"); diff --git a/website/src/locales/en.json b/website/src/locales/en.json index 172ab015..8511c616 100644 --- a/website/src/locales/en.json +++ b/website/src/locales/en.json @@ -37,6 +37,9 @@ "light": "Light", "dark": "Dark", "system": "System", + "street_view_source": "Street view source", + "mapillary": "Mapillary", + "google": "Google", "layers": "Map layers...", "distance_markers": "Distance markers", "direction_markers": "Direction markers",