diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 43d2848e16..98a5f4cb20 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -815,6 +815,9 @@ importers: tabbable: specifier: ^6.2.0 version: 6.3.0 + three: + specifier: ^0.179.1 + version: 0.179.1 thumbhash: specifier: ^0.1.1 version: 0.1.1 @@ -876,6 +879,9 @@ importers: '@types/qrcode': specifier: ^1.5.5 version: 1.5.6 + '@types/three': + specifier: ^0.181.0 + version: 0.181.0 '@vitest/coverage-v8': specifier: ^3.0.0 version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) @@ -2078,6 +2084,9 @@ packages: peerDependencies: postcss: ^8.4 + '@dimforge/rapier3d-compat@0.12.0': + resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} + '@discoveryjs/json-ext@0.5.7': resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} @@ -4640,6 +4649,9 @@ packages: '@turf/invariant@7.2.0': resolution: {integrity: sha512-kV4u8e7Gkpq+kPbAKNC21CmyrXzlbBgFjO1PhrHPgEdNqXqDawoZ3i6ivE3ULJj2rSesCjduUaC/wyvH/sNr2Q==} + '@tweenjs/tween.js@23.1.3': + resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} + '@types/accepts@1.3.7': resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} @@ -4960,6 +4972,9 @@ packages: '@types/ssh2@1.15.5': resolution: {integrity: sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==} + '@types/stats.js@0.17.4': + resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} + '@types/superagent@8.1.9': resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} @@ -4969,6 +4984,9 @@ packages: '@types/supertest@6.0.3': resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} + '@types/three@0.181.0': + resolution: {integrity: sha512-MLF1ks8yRM2k71D7RprFpDb9DOX0p22DbdPqT/uAkc6AtQXjxWCVDjCy23G9t1o8HcQPk7woD2NIyiaWcWPYmA==} + '@types/through@0.0.33': resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} @@ -4984,6 +5002,9 @@ packages: '@types/validator@13.15.10': resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} + '@types/webxr@0.5.24': + resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} + '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -5145,6 +5166,9 @@ packages: '@webassemblyjs/wast-printer@1.14.1': resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + '@webgpu/types@0.1.67': + resolution: {integrity: sha512-uk53+2ECGUkWoDFez/hymwpRfdgdIn6y1ref70fEecGMe5607f4sozNFgBk0oxlr7j2CRGWBEc3IBYMmFdGGTQ==} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -8407,6 +8431,9 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + meshoptimizer@0.22.0: + resolution: {integrity: sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==} + methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} @@ -10934,9 +10961,6 @@ packages: three@0.179.1: resolution: {integrity: sha512-5y/elSIQbrvKOISxpwXCR4sQqHtGiOI+MKLc3SsBdDXA2hz3Mdp3X59aUp8DyybMa34aeBwbFTpdoLJaUDEWSw==} - three@0.180.0: - resolution: {integrity: sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==} - throttleit@2.1.0: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} engines: {node: '>=18'} @@ -13458,6 +13482,8 @@ snapshots: dependencies: postcss: 8.5.6 + '@dimforge/rapier3d-compat@0.12.0': {} + '@discoveryjs/json-ext@0.5.7': {} '@docsearch/css@4.2.0': {} @@ -15629,7 +15655,7 @@ snapshots: dependencies: '@photo-sphere-viewer/core': 5.14.0 '@photo-sphere-viewer/video-plugin': 5.14.0(@photo-sphere-viewer/core@5.14.0) - three: 0.180.0 + three: 0.179.1 '@photo-sphere-viewer/markers-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)': dependencies: @@ -15647,7 +15673,7 @@ snapshots: '@photo-sphere-viewer/video-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)': dependencies: '@photo-sphere-viewer/core': 5.14.0 - three: 0.180.0 + three: 0.179.1 '@photostructure/tz-lookup@11.3.0': {} @@ -16559,6 +16585,8 @@ snapshots: '@types/geojson': 7946.0.16 tslib: 2.8.1 + '@tweenjs/tween.js@23.1.3': {} + '@types/accepts@1.3.7': dependencies: '@types/node': 24.10.1 @@ -16955,6 +16983,8 @@ snapshots: dependencies: '@types/node': 18.19.130 + '@types/stats.js@0.17.4': {} + '@types/superagent@8.1.9': dependencies: '@types/cookiejar': 2.1.5 @@ -16971,6 +17001,16 @@ snapshots: '@types/methods': 1.1.4 '@types/superagent': 8.1.9 + '@types/three@0.181.0': + dependencies: + '@dimforge/rapier3d-compat': 0.12.0 + '@tweenjs/tween.js': 23.1.3 + '@types/stats.js': 0.17.4 + '@types/webxr': 0.5.24 + '@webgpu/types': 0.1.67 + fflate: 0.8.2 + meshoptimizer: 0.22.0 + '@types/through@0.0.33': dependencies: '@types/node': 24.10.1 @@ -16983,6 +17023,8 @@ snapshots: '@types/validator@13.15.10': {} + '@types/webxr@0.5.24': {} + '@types/whatwg-mimetype@3.0.2': {} '@types/ws@8.18.1': @@ -17228,6 +17270,8 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 + '@webgpu/types@0.1.67': {} + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -21121,6 +21165,8 @@ snapshots: merge2@1.4.1: {} + meshoptimizer@0.22.0: {} + methods@1.1.2: {} micromark-core-commonmark@2.0.3: @@ -24194,8 +24240,6 @@ snapshots: three@0.179.1: {} - three@0.180.0: {} - throttleit@2.1.0: {} through@2.3.8: {} diff --git a/web/package.json b/web/package.json index 2e7b740153..8cf544d486 100644 --- a/web/package.json +++ b/web/package.json @@ -61,6 +61,7 @@ "svelte-maplibre": "^1.2.5", "svelte-persisted-store": "^0.12.0", "tabbable": "^6.2.0", + "three": "^0.179.1", "thumbhash": "^0.1.1", "uplot": "^1.6.32" }, @@ -83,6 +84,7 @@ "@types/lodash-es": "^4.17.12", "@types/luxon": "^3.4.2", "@types/qrcode": "^1.5.5", + "@types/three": "^0.181.0", "@vitest/coverage-v8": "^3.0.0", "dotenv": "^17.0.0", "eslint": "^9.36.0", diff --git a/web/src/lib/components/asset-viewer/image-viewer.svelte b/web/src/lib/components/asset-viewer/image-viewer.svelte new file mode 100644 index 0000000000..554985289d --- /dev/null +++ b/web/src/lib/components/asset-viewer/image-viewer.svelte @@ -0,0 +1,426 @@ + + +
+ + +
+ + diff --git a/web/src/lib/components/asset-viewer/photo-viewer.svelte b/web/src/lib/components/asset-viewer/photo-viewer.svelte index 2607f6de79..fb69c85403 100644 --- a/web/src/lib/components/asset-viewer/photo-viewer.svelte +++ b/web/src/lib/components/asset-viewer/photo-viewer.svelte @@ -2,6 +2,7 @@ import { shortcuts } from '$lib/actions/shortcut'; import { zoomImageAction } from '$lib/actions/zoom-image'; import FaceEditor from '$lib/components/asset-viewer/face-editor/face-editor.svelte'; + import ImageViewer from '$lib/components/asset-viewer/image-viewer.svelte'; import OcrBoundingBox from '$lib/components/asset-viewer/ocr-bounding-box.svelte'; import BrokenAsset from '$lib/components/assets/broken-asset.svelte'; import { assetViewerFadeDuration } from '$lib/constants'; @@ -158,7 +159,8 @@ // when true, will force loading of the original image let forceUseOriginal: boolean = $derived( (asset.type === AssetTypeEnum.Image && asset.duration && !asset.duration.includes('0:00:00.000')) || - $photoZoomState.currentZoom > 1, + $photoZoomState.currentZoom > 1 || + true, ); const targetImageSize = $derived.by(() => { @@ -250,42 +252,44 @@ {:else if !imageError} -
- {#if $slideshowState !== SlideshowState.None && $slideshowLook === SlideshowLook.BlurredBackground} + +
+
+ {#if $slideshowState !== SlideshowState.None && $slideshowLook === SlideshowLook.BlurredBackground} + + {/if} - {/if} - {$getAltText(toTimelineAsset(asset))} - - {#each getBoundingBox($boundingBoxesArray, $photoZoomState, $photoViewerImgElement) as boundingbox} -
- {/each} + + {#each getBoundingBox($boundingBoxesArray, $photoZoomState, $photoViewerImgElement) as boundingbox} +
+ {/each} - {#each ocrBoxes as ocrBox (ocrBox.id)} - - {/each} + {#each ocrBoxes as ocrBox (ocrBox.id)} + + {/each} +
- {#if isFaceEditMode.value} {/if}