Re-enable STL support (#61)
* OBJ as the new default viewer format * Replace deprecated btoa * Clean up * Hide existing STL toggle * No Box if no before/after * Adds error message when no geometry
This commit is contained in:
@ -22,6 +22,7 @@
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/three": "^0.149.0",
|
||||
"buffer": "^6.0.3",
|
||||
"github-injection": "^1.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -4,8 +4,8 @@ import { downloadFile, isFilenameSupported } from './diff'
|
||||
it('checks if the filename has a supported extension', () => {
|
||||
expect(isFilenameSupported('noextension')).toBe(false)
|
||||
expect(isFilenameSupported('unsupported.txt')).toBe(false)
|
||||
expect(isFilenameSupported('unsupported.stl')).toBe(false)
|
||||
expect(isFilenameSupported('supported.obj')).toBe(true)
|
||||
expect(isFilenameSupported('supported.stl')).toBe(true)
|
||||
expect(isFilenameSupported('supported.stp')).toBe(true)
|
||||
expect(isFilenameSupported('supported.step')).toBe(true)
|
||||
})
|
||||
|
@ -5,18 +5,19 @@ import {
|
||||
FileExportFormat_type,
|
||||
FileImportFormat_type,
|
||||
} from '@kittycad/lib/dist/types/src/models'
|
||||
import { Buffer } from 'buffer'
|
||||
|
||||
export const extensionToSrcFormat: {
|
||||
[extension: string]: FileImportFormat_type
|
||||
} = {
|
||||
'dae': 'dae',
|
||||
'dxf': 'dxf',
|
||||
'fbx': 'fbx',
|
||||
'obj': 'obj',
|
||||
'stp': 'step',
|
||||
'step': 'step',
|
||||
'svg': 'svg',
|
||||
// stl disabled for now as there's some GitHub support for them already, see #40
|
||||
dae: 'dae',
|
||||
dxf: 'dxf',
|
||||
fbx: 'fbx',
|
||||
obj: 'obj',
|
||||
stl: 'stl',
|
||||
stp: 'step',
|
||||
step: 'step',
|
||||
svg: 'svg',
|
||||
}
|
||||
|
||||
export function isFilenameSupported(filename: string): boolean {
|
||||
@ -56,9 +57,14 @@ async function convert(
|
||||
client: Client,
|
||||
body: string,
|
||||
extension: string,
|
||||
outputFormat = 'stl'
|
||||
outputFormat = 'obj'
|
||||
) {
|
||||
// TODO: think about the best output format for visual diff injection, now defaults to STL
|
||||
if (extension === outputFormat) {
|
||||
console.log(
|
||||
'Skipping conversion, as extension is equal to outputFormat'
|
||||
)
|
||||
return Buffer.from(body).toString('base64')
|
||||
}
|
||||
const response = await file.create_file_conversion({
|
||||
client,
|
||||
body,
|
||||
@ -86,7 +92,9 @@ export async function getFileDiff(
|
||||
const extension = filename.split('.').pop()
|
||||
if (!extension || !extensionToSrcFormat[extension]) {
|
||||
throw Error(
|
||||
`Unsupported extension. Given ${extension}, was expecting ${Object.keys(extensionToSrcFormat)}`
|
||||
`Unsupported extension. Given ${extension}, was expecting ${Object.keys(
|
||||
extensionToSrcFormat
|
||||
)}`
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,27 +1,31 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import '@react-three/fiber'
|
||||
import { Box, useTheme } from '@primer/react'
|
||||
import { Box, useTheme, Text } from '@primer/react'
|
||||
import { FileDiff } from '../../chrome/types'
|
||||
import { Viewer3D } from './Viewer3D'
|
||||
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
|
||||
import { BufferGeometry } from 'three'
|
||||
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
|
||||
import { BufferGeometry, Mesh } from 'three'
|
||||
import { WireframeColors } from './WireframeModel'
|
||||
import { Buffer } from 'buffer'
|
||||
|
||||
type ViewerSTLProps = {
|
||||
file: string
|
||||
colors: WireframeColors
|
||||
}
|
||||
|
||||
function ViewerSTL({ file, colors }: ViewerSTLProps) {
|
||||
const [geomety, setGeometry] = useState<BufferGeometry>()
|
||||
function Loader3D({ file, colors }: { file: string; colors: WireframeColors }) {
|
||||
const [geometry, setGeometry] = useState<BufferGeometry>()
|
||||
useEffect(() => {
|
||||
const loader = new STLLoader()
|
||||
const buffer = window.atob(file)
|
||||
const geometry = loader.parse(buffer)
|
||||
console.log(`Model ${geometry.id} loaded`)
|
||||
const loader = new OBJLoader()
|
||||
const buffer = Buffer.from(file, 'base64').toString()
|
||||
const group = loader.parse(buffer)
|
||||
console.log(`Model ${group.id} loaded`)
|
||||
console.log(group)
|
||||
const geometry = (group.children[0] as Mesh)?.geometry
|
||||
setGeometry(geometry)
|
||||
}, [file])
|
||||
return geomety ? <Viewer3D geometry={geomety} colors={colors} /> : null
|
||||
return geometry ? (
|
||||
<Viewer3D geometry={geometry} colors={colors} />
|
||||
) : (
|
||||
<Box p={3}>
|
||||
<Text>Sorry, the rich diff can't be displayed for this file.</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export function CadDiff({ before, after }: FileDiff): React.ReactElement {
|
||||
@ -38,9 +42,12 @@ export function CadDiff({ before, after }: FileDiff): React.ReactElement {
|
||||
}
|
||||
return (
|
||||
<Box display="flex" height={300} overflow="hidden" minWidth={0}>
|
||||
{before && (
|
||||
<Box flexGrow={1} minWidth={0} backgroundColor="danger.subtle">
|
||||
{before && <ViewerSTL file={before} colors={beforeColors} />}
|
||||
<Loader3D file={before} colors={beforeColors} />
|
||||
</Box>
|
||||
)}
|
||||
{after && (
|
||||
<Box
|
||||
flexGrow={1}
|
||||
minWidth={0}
|
||||
@ -49,8 +56,9 @@ export function CadDiff({ before, after }: FileDiff): React.ReactElement {
|
||||
borderLeftColor="border.default"
|
||||
borderLeftStyle="solid"
|
||||
>
|
||||
{after && <ViewerSTL file={after} colors={afterColors} />}
|
||||
<Loader3D file={after} colors={afterColors} />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
@ -32,6 +32,14 @@ function CadDiffPortal({
|
||||
const toolbar = element.querySelector<HTMLElement>('.file-info')
|
||||
if (toolbar != null) {
|
||||
setToolbarContainer(toolbar)
|
||||
|
||||
// STL files might have a toggle already
|
||||
const existingToggle = element.querySelector<HTMLElement>(
|
||||
'.js-prose-diff-toggle-form'
|
||||
)
|
||||
if (existingToggle) {
|
||||
existingToggle.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
const diff = element.querySelector<HTMLElement>('.js-file-content')
|
||||
|
35
yarn.lock
35
yarn.lock
@ -4814,6 +4814,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"base64-js@npm:^1.3.1":
|
||||
version: 1.5.1
|
||||
resolution: "base64-js@npm:1.5.1"
|
||||
checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"batch@npm:0.6.1":
|
||||
version: 0.6.1
|
||||
resolution: "batch@npm:0.6.1"
|
||||
@ -4974,6 +4981,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"buffer@npm:^6.0.3":
|
||||
version: 6.0.3
|
||||
resolution: "buffer@npm:6.0.3"
|
||||
dependencies:
|
||||
base64-js: ^1.3.1
|
||||
ieee754: ^1.2.1
|
||||
checksum: 5ad23293d9a731e4318e420025800b42bf0d264004c0286c8cc010af7a270c7a0f6522e84f54b9ad65cbd6db20b8badbfd8d2ebf4f80fa03dab093b89e68c3f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"builtin-modules@npm:^3.1.0":
|
||||
version: 3.3.0
|
||||
resolution: "builtin-modules@npm:3.3.0"
|
||||
@ -6164,6 +6181,7 @@ __metadata:
|
||||
"@types/react-dom": ^18.0.11
|
||||
"@types/testing-library__jest-dom": ^5.14.5
|
||||
"@types/three": ^0.149.0
|
||||
buffer: ^6.0.3
|
||||
dotenv: ^16.0.3
|
||||
eslint: ^8.37.0
|
||||
eslint-config-prettier: ^8.6.0
|
||||
@ -7528,7 +7546,7 @@ __metadata:
|
||||
|
||||
"fsevents@patch:fsevents@2.3.2#~builtin<compat/fsevents>, fsevents@patch:fsevents@^2.3.2#~builtin<compat/fsevents>, fsevents@patch:fsevents@~2.3.2#~builtin<compat/fsevents>":
|
||||
version: 2.3.2
|
||||
resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::version=2.3.2&hash=18f3a7"
|
||||
resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::version=2.3.2&hash=df0bf1"
|
||||
dependencies:
|
||||
node-gyp: latest
|
||||
conditions: os=darwin
|
||||
@ -8159,6 +8177,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ieee754@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "ieee754@npm:1.2.1"
|
||||
checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ignore@npm:^5.2.0":
|
||||
version: 5.2.4
|
||||
resolution: "ignore@npm:5.2.4"
|
||||
@ -12363,7 +12388,7 @@ __metadata:
|
||||
|
||||
"resolve@patch:resolve@^1.1.7#~builtin<compat/resolve>, resolve@patch:resolve@^1.14.2#~builtin<compat/resolve>, resolve@patch:resolve@^1.19.0#~builtin<compat/resolve>, resolve@patch:resolve@^1.20.0#~builtin<compat/resolve>, resolve@patch:resolve@^1.22.1#~builtin<compat/resolve>":
|
||||
version: 1.22.1
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin<compat/resolve>::version=1.22.1&hash=07638b"
|
||||
resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin<compat/resolve>::version=1.22.1&hash=c3c19d"
|
||||
dependencies:
|
||||
is-core-module: ^2.9.0
|
||||
path-parse: ^1.0.7
|
||||
@ -12376,7 +12401,7 @@ __metadata:
|
||||
|
||||
"resolve@patch:resolve@^2.0.0-next.4#~builtin<compat/resolve>":
|
||||
version: 2.0.0-next.4
|
||||
resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin<compat/resolve>::version=2.0.0-next.4&hash=07638b"
|
||||
resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin<compat/resolve>::version=2.0.0-next.4&hash=c3c19d"
|
||||
dependencies:
|
||||
is-core-module: ^2.9.0
|
||||
path-parse: ^1.0.7
|
||||
@ -13826,11 +13851,11 @@ __metadata:
|
||||
|
||||
"typescript@patch:typescript@^4.4.2#~builtin<compat/typescript>":
|
||||
version: 4.9.5
|
||||
resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::version=4.9.5&hash=a1c5e5"
|
||||
resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::version=4.9.5&hash=23ec76"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20
|
||||
checksum: ab417a2f398380c90a6cf5a5f74badd17866adf57f1165617d6a551f059c3ba0a3e4da0d147b3ac5681db9ac76a303c5876394b13b3de75fdd5b1eaa06181c9d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Reference in New Issue
Block a user