Add 3MF viewer and enable PDF thumbnails
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m12s
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m12s
This commit is contained in:
parent
cd540499ca
commit
72b1de2937
5 changed files with 571 additions and 17 deletions
|
|
@ -82,7 +82,7 @@ func (m *ThumbnailManager) ScanMissingThumbnails() {
|
|||
mimeType = "video/"
|
||||
} else if ext == ".mp3" || ext == ".flac" || ext == ".wav" || ext == ".m4a" || ext == ".aac" {
|
||||
mimeType = "audio/"
|
||||
} else if ext == ".docx" || ext == ".pptx" || ext == ".xlsx" {
|
||||
} else if ext == ".docx" || ext == ".pptx" || ext == ".xlsx" || ext == ".pdf" {
|
||||
mimeType = "application/"
|
||||
} else {
|
||||
continue
|
||||
|
|
@ -148,7 +148,7 @@ func (m *ThumbnailManager) worker(id int) {
|
|||
err = generateVideoThumbnail(fullSourcePath, destPath)
|
||||
} else if strings.HasPrefix(job.MimeType, "audio/") {
|
||||
err = generateAudioThumbnail(fullSourcePath, destPath)
|
||||
} else if strings.HasSuffix(job.FilePath, ".docx") || strings.HasSuffix(job.FilePath, ".pptx") || strings.HasSuffix(job.FilePath, ".xlsx") {
|
||||
} else if strings.HasSuffix(job.FilePath, ".docx") || strings.HasSuffix(job.FilePath, ".pptx") || strings.HasSuffix(job.FilePath, ".xlsx") || strings.HasSuffix(strings.ToLower(job.FilePath), ".pdf") {
|
||||
err = generateOfficeThumbnail(job.FilePath, destPath, m.Config)
|
||||
} else {
|
||||
continue
|
||||
|
|
|
|||
480
frontend/package-lock.json
generated
480
frontend/package-lock.json
generated
|
|
@ -10,6 +10,8 @@
|
|||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@onlyoffice/document-editor-react": "^2.2.0",
|
||||
"@react-three/drei": "^10.7.7",
|
||||
"@react-three/fiber": "^9.6.1",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"framer-motion": "^11.15.0",
|
||||
"lucide-react": "^0.468.0",
|
||||
|
|
@ -21,6 +23,7 @@
|
|||
"react-pdf": "^10.4.1",
|
||||
"react-syntax-highlighter": "^16.1.1",
|
||||
"three": "^0.184.0",
|
||||
"three-stdlib": "^2.36.1",
|
||||
"tus-js-client": "^4.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -100,6 +103,12 @@
|
|||
"integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@dimforge/rapier3d-compat": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz",
|
||||
"integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
||||
|
|
@ -615,6 +624,24 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mediapipe/tasks-vision": {
|
||||
"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/@monogrid/gainmap-js": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.4.0.tgz",
|
||||
"integrity": "sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"promise-worker-transferable": "^1.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.159.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas": {
|
||||
"version": "0.1.100",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.100.tgz",
|
||||
|
|
@ -1058,11 +1085,52 @@
|
|||
"react-dom": "^16.9.0 || ^17 || ^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/drei": {
|
||||
"version": "10.7.7",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-10.7.7.tgz",
|
||||
"integrity": "sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mediapipe/tasks-vision": "0.10.17",
|
||||
"@monogrid/gainmap-js": "^3.0.6",
|
||||
"@use-gesture/react": "^10.3.1",
|
||||
"camera-controls": "^3.1.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"detect-gpu": "^5.0.56",
|
||||
"glsl-noise": "^0.0.0",
|
||||
"hls.js": "^1.5.17",
|
||||
"maath": "^0.10.8",
|
||||
"meshline": "^3.3.1",
|
||||
"stats-gl": "^2.2.8",
|
||||
"stats.js": "^0.17.0",
|
||||
"suspend-react": "^0.1.3",
|
||||
"three-mesh-bvh": "^0.8.3",
|
||||
"three-stdlib": "^2.35.6",
|
||||
"troika-three-text": "^0.52.4",
|
||||
"tunnel-rat": "^0.1.2",
|
||||
"use-sync-external-store": "^1.4.0",
|
||||
"utility-types": "^3.11.0",
|
||||
"zustand": "^5.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": "^9.0.0",
|
||||
"react": "^19",
|
||||
"react-dom": "^19",
|
||||
"three": ">=0.159"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/fiber": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.6.1.tgz",
|
||||
"integrity": "sha512-zF0rsKcVYpcJwbFEnv2HkHX9cvOEgsfQo/X8lwmR2dn13S4qEQJXir9fxf5js2LQFoXqxOY7MDkOkYx2uZ4gSg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.17.8",
|
||||
"@types/webxr": "*",
|
||||
|
|
@ -1115,6 +1183,18 @@
|
|||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tweenjs/tween.js": {
|
||||
"version": "23.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
|
||||
"integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/draco3d": {
|
||||
"version": "1.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz",
|
||||
"integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/hast": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
||||
|
|
@ -1184,6 +1264,33 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stats.js": {
|
||||
"version": "0.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz",
|
||||
"integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/three": {
|
||||
"version": "0.184.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.184.1.tgz",
|
||||
"integrity": "sha512-6q4VdiqVsrTRqmk62/BnlcAvIrnDM0zf2ZDVKI5kZiniWrSaOHaQzmbp+BNzoggc/8tgW412pL//wZIxu2PPTA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@dimforge/rapier3d-compat": "~0.12.0",
|
||||
"@tweenjs/tween.js": "~23.1.3",
|
||||
"@types/stats.js": "*",
|
||||
"@types/webxr": ">=0.5.17",
|
||||
"fflate": "~0.8.2",
|
||||
"meshoptimizer": "~1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/three/node_modules/fflate": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
|
||||
"integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||
|
|
@ -1196,6 +1303,24 @@
|
|||
"integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@use-gesture/core": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz",
|
||||
"integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@use-gesture/react": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz",
|
||||
"integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@use-gesture/core": "10.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@webgpu/glslang": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@webgpu/glslang/-/glslang-0.0.15.tgz",
|
||||
|
|
@ -1300,6 +1425,15 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bidi-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
|
||||
"integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"require-from-string": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
|
|
@ -1401,6 +1535,19 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/camera-controls": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-3.1.2.tgz",
|
||||
"integrity": "sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.0.0",
|
||||
"npm": ">=10.5.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.126.1"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001793",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
|
||||
|
|
@ -1553,6 +1700,38 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "src/bin/cross-env.js",
|
||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.14",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
|
|
@ -1600,6 +1779,15 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-gpu": {
|
||||
"version": "5.0.70",
|
||||
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.70.tgz",
|
||||
"integrity": "sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"webgl-constants": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
|
|
@ -1816,6 +2004,12 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glsl-noise": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz",
|
||||
"integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
|
|
@ -1880,6 +2074,12 @@
|
|||
"integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/hls.js": {
|
||||
"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/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
|
|
@ -1900,6 +2100,12 @@
|
|||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-alphabetical": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
||||
|
|
@ -2006,6 +2212,12 @@
|
|||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-promise": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
|
||||
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
|
|
@ -2018,6 +2230,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/its-fine": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz",
|
||||
|
|
@ -2058,6 +2276,15 @@
|
|||
"integrity": "sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||
|
|
@ -2181,6 +2408,16 @@
|
|||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/maath": {
|
||||
"version": "0.10.8",
|
||||
"resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz",
|
||||
"integrity": "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/three": ">=0.134.0",
|
||||
"three": ">=0.134.0"
|
||||
}
|
||||
},
|
||||
"node_modules/make-cancellable-promise": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-2.0.0.tgz",
|
||||
|
|
@ -2226,6 +2463,21 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/meshline": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz",
|
||||
"integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.137"
|
||||
}
|
||||
},
|
||||
"node_modules/meshoptimizer": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz",
|
||||
"integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
|
|
@ -2452,6 +2704,15 @@
|
|||
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
|
|
@ -2646,6 +2907,16 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/promise-worker-transferable": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz",
|
||||
"integrity": "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"is-promise": "^2.1.0",
|
||||
"lie": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/proper-lockfile": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
|
||||
|
|
@ -2719,6 +2990,28 @@
|
|||
"three": ">=0.160"
|
||||
}
|
||||
},
|
||||
"node_modules/react-19-stl-viewer/node_modules/three-stdlib": {
|
||||
"version": "2.17.2",
|
||||
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.17.2.tgz",
|
||||
"integrity": "sha512-7ZLCJJogtn1D1MlUi7q0iLUbrxj7K++YxjHIIz5AZ4wX4E137BgiiTmhH4XhAuvXGRk9ph3ZtoHTfJBXhqDX3w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.7",
|
||||
"@types/offscreencanvas": "^2019.6.4",
|
||||
"@webgpu/glslang": "^0.0.15",
|
||||
"chevrotain": "^10.1.2",
|
||||
"draco3d": "^1.4.1",
|
||||
"fflate": "^0.6.9",
|
||||
"ktx-parse": "^0.4.5",
|
||||
"mmd-parser": "^1.0.4",
|
||||
"opentype.js": "^1.3.3",
|
||||
"potpack": "^1.0.1",
|
||||
"zstddec": "^0.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.122.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "19.2.6",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz",
|
||||
|
|
@ -2853,6 +3146,15 @@
|
|||
"integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
|
|
@ -2989,6 +3291,27 @@
|
|||
"@img/sharp-win32-x64": "0.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
|
|
@ -3014,6 +3337,32 @@
|
|||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/stats-gl": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz",
|
||||
"integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/three": "*",
|
||||
"three": "^0.170.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/three": "*",
|
||||
"three": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/stats-gl/node_modules/three": {
|
||||
"version": "0.170.0",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz",
|
||||
"integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stats.js": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
|
||||
"integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||
|
|
@ -3192,26 +3541,30 @@
|
|||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/three-mesh-bvh": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.8.3.tgz",
|
||||
"integrity": "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.159.0"
|
||||
}
|
||||
},
|
||||
"node_modules/three-stdlib": {
|
||||
"version": "2.17.2",
|
||||
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.17.2.tgz",
|
||||
"integrity": "sha512-7ZLCJJogtn1D1MlUi7q0iLUbrxj7K++YxjHIIz5AZ4wX4E137BgiiTmhH4XhAuvXGRk9ph3ZtoHTfJBXhqDX3w==",
|
||||
"version": "2.36.1",
|
||||
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.36.1.tgz",
|
||||
"integrity": "sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.16.7",
|
||||
"@types/draco3d": "^1.4.0",
|
||||
"@types/offscreencanvas": "^2019.6.4",
|
||||
"@webgpu/glslang": "^0.0.15",
|
||||
"chevrotain": "^10.1.2",
|
||||
"@types/webxr": "^0.5.2",
|
||||
"draco3d": "^1.4.1",
|
||||
"fflate": "^0.6.9",
|
||||
"ktx-parse": "^0.4.5",
|
||||
"mmd-parser": "^1.0.4",
|
||||
"opentype.js": "^1.3.3",
|
||||
"potpack": "^1.0.1",
|
||||
"zstddec": "^0.0.2"
|
||||
"potpack": "^1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.122.0"
|
||||
"three": ">=0.128.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-inflate": {
|
||||
|
|
@ -3288,6 +3641,36 @@
|
|||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-three-text": {
|
||||
"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.52.4",
|
||||
"troika-worker-utils": "^0.52.0",
|
||||
"webgl-sdf-generator": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.125.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-three-utils": {
|
||||
"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.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-interface-checker": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||
|
|
@ -3301,6 +3684,43 @@
|
|||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tunnel-rat": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz",
|
||||
"integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"zustand": "^4.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-rat/node_modules/zustand": {
|
||||
"version": "4.5.7",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz",
|
||||
"integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"use-sync-external-store": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=16.8",
|
||||
"immer": ">=9.0.6",
|
||||
"react": ">=16.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"immer": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tus-js-client": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-4.3.1.tgz",
|
||||
|
|
@ -3386,7 +3806,6 @@
|
|||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
|
|
@ -3398,6 +3817,15 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/utility-types": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz",
|
||||
"integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
|
|
@ -3407,6 +3835,32 @@
|
|||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webgl-constants": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz",
|
||||
"integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg=="
|
||||
},
|
||||
"node_modules/webgl-sdf-generator": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz",
|
||||
"integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@onlyoffice/document-editor-react": "^2.2.0",
|
||||
"@react-three/drei": "^10.7.7",
|
||||
"@react-three/fiber": "^9.6.1",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"framer-motion": "^11.15.0",
|
||||
"lucide-react": "^0.468.0",
|
||||
|
|
@ -22,6 +24,7 @@
|
|||
"react-pdf": "^10.4.1",
|
||||
"react-syntax-highlighter": "^16.1.1",
|
||||
"three": "^0.184.0",
|
||||
"three-stdlib": "^2.36.1",
|
||||
"tus-js-client": "^4.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { formatSize, getFileDisplayName } from '@/lib/utils';
|
|||
|
||||
const DynamicPdfViewer = dynamic(() => import('./PdfViewer'), { ssr: false });
|
||||
const DynamicStlPreview = dynamic(() => import('./StlPreview'), { ssr: false });
|
||||
const DynamicThreeMfPreview = dynamic(() => import('./ThreeMfPreview'), { ssr: false });
|
||||
|
||||
interface FilePreviewProps {
|
||||
file: {
|
||||
|
|
@ -86,7 +87,7 @@ export default function FilePreview({ file, onClose, downloadToken }: FilePrevie
|
|||
exit={{ scale: 0.95, opacity: 0, y: 20 }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className={`relative flex flex-col max-w-[95vw] max-h-[95vh] rounded-2xl overflow-hidden shadow-2xl ${
|
||||
(previewType === 'image' || previewType === 'video' || previewType === 'pdf' || previewType === 'stl' || previewType === 'audio') ? 'w-fit' : 'w-full'
|
||||
(previewType === 'image' || previewType === 'video' || previewType === 'pdf' || previewType === 'stl' || previewType === '3mf' || previewType === 'audio') ? 'w-fit' : 'w-full'
|
||||
} ${
|
||||
(previewType === 'image' || previewType === 'video' || previewType === 'audio') ? 'h-fit' : 'h-full'
|
||||
}`}
|
||||
|
|
@ -171,6 +172,16 @@ export default function FilePreview({ file, onClose, downloadToken }: FilePrevie
|
|||
)
|
||||
)}
|
||||
|
||||
{previewType === '3mf' && (
|
||||
!downloadToken ? (
|
||||
<div className="flex items-center justify-center p-8"><Loader2 className="w-8 h-8 animate-spin text-accent" /></div>
|
||||
) : (
|
||||
<div className="w-[80vw] h-[80vh] max-w-[1200px] max-h-[800px]">
|
||||
<DynamicThreeMfPreview url={downloadUrl} />
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
|
||||
{(previewType === 'text' || previewType === 'code') && (
|
||||
<div className="absolute inset-0 p-4">
|
||||
{loading ? (
|
||||
|
|
@ -245,13 +256,14 @@ export default function FilePreview({ file, onClose, downloadToken }: FilePrevie
|
|||
|
||||
// --- Helpers ---
|
||||
|
||||
type PreviewType = 'image' | 'video' | 'audio' | 'text' | 'code' | 'pdf' | 'stl' | 'unsupported';
|
||||
type PreviewType = 'image' | 'video' | 'audio' | 'text' | 'code' | 'pdf' | 'stl' | '3mf' | 'unsupported';
|
||||
|
||||
function getPreviewType(file: { name: string; mime_type: string }): PreviewType {
|
||||
const ext = file.name.split('.').pop()?.toLowerCase() || '';
|
||||
|
||||
if (ext === 'pdf' || file.mime_type === 'application/pdf') return 'pdf';
|
||||
if (ext === 'stl' || file.mime_type === 'model/stl') return 'stl';
|
||||
if (ext === '3mf' || file.mime_type === 'model/3mf') return '3mf';
|
||||
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp'].includes(ext)) return 'image';
|
||||
if (['mp4', 'webm', 'ogg'].includes(ext)) return 'video'; // Only browser-supported videos
|
||||
if (['mp3', 'wav', 'flac', 'm4a', 'aac'].includes(ext)) return 'audio';
|
||||
|
|
|
|||
85
frontend/src/components/ThreeMfPreview.tsx
Normal file
85
frontend/src/components/ThreeMfPreview.tsx
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Canvas } from '@react-three/fiber';
|
||||
import { OrbitControls, Stage } from '@react-three/drei';
|
||||
import { ThreeMFLoader } from 'three-stdlib';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import * as THREE from 'three';
|
||||
|
||||
interface ThreeMfPreviewProps {
|
||||
url: string;
|
||||
}
|
||||
|
||||
function Model({ url, onLoad, onError }: { url: string; onLoad: () => void; onError: (e: any) => void }) {
|
||||
const [model, setModel] = useState<THREE.Group | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loader = new ThreeMFLoader();
|
||||
loader.load(
|
||||
url,
|
||||
(group) => {
|
||||
// Adjust materials for shadow casting
|
||||
group.traverse((child) => {
|
||||
if ((child as THREE.Mesh).isMesh) {
|
||||
const mesh = child as THREE.Mesh;
|
||||
mesh.castShadow = true;
|
||||
mesh.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
setModel(group);
|
||||
onLoad();
|
||||
},
|
||||
undefined,
|
||||
(err) => {
|
||||
onError(err);
|
||||
}
|
||||
);
|
||||
}, [url, onLoad, onError]);
|
||||
|
||||
if (!model) return null;
|
||||
return <primitive object={model} />;
|
||||
}
|
||||
|
||||
export default function ThreeMfPreview({ url }: ThreeMfPreviewProps) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
return (
|
||||
<div className="w-full h-full relative" style={{ backgroundColor: 'var(--color-bg-primary)' }}>
|
||||
{loading && !error && (
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center z-10" style={{ backgroundColor: 'var(--color-bg-primary)' }}>
|
||||
<Loader2 className="w-8 h-8 animate-spin mb-4" style={{ color: 'var(--color-accent)' }} />
|
||||
<span className="text-sm font-medium" style={{ color: 'var(--color-text-secondary)' }}>Loading 3D Model...</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center z-10" style={{ backgroundColor: 'var(--color-bg-primary)' }}>
|
||||
<svg className="w-12 h-12 mb-4 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium text-red-500">Failed to load 3MF file</span>
|
||||
<span className="text-xs mt-2" style={{ color: 'var(--color-text-tertiary)' }}>{error.message}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={`w-full h-full transition-opacity duration-300 ${loading ? 'opacity-0' : 'opacity-100'}`}>
|
||||
<Canvas shadows dpr={[1, 2]} camera={{ position: [0, 0, 150], fov: 50 }}>
|
||||
<React.Suspense fallback={null}>
|
||||
<Stage environment="city" intensity={0.6} adjustCamera>
|
||||
<Model
|
||||
url={url}
|
||||
onLoad={() => setLoading(false)}
|
||||
onError={(err) => {
|
||||
console.error('3MF Load Error:', err);
|
||||
setError(err);
|
||||
setLoading(false);
|
||||
}}
|
||||
/>
|
||||
</Stage>
|
||||
</React.Suspense>
|
||||
<OrbitControls makeDefault />
|
||||
</Canvas>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in a new issue