Unified diff mode improvements (#167)

* Bump to v0.2.0

* Better colors in unfied mode

* New legend (wip)

* Working prototype

* Clean up

* Consistency tweaks

* Clean up
This commit is contained in:
Pierre Jacquier
2023-05-24 10:41:51 +02:00
committed by GitHub
parent 32500a1104
commit a8398b1957
3 changed files with 120 additions and 26 deletions

View File

@ -8,8 +8,9 @@ import { BufferAttribute, BufferGeometry, Mesh } from 'three'
import { WireframeColors, WireframeModel } from './WireframeModel'
import { Buffer } from 'buffer'
import { useRef } from 'react'
import { BeforeAfterModel } from './BeforeAfterModel'
import { UnifiedModel } from './UnifiedModel'
import { BeakerIcon } from '@primer/octicons-react'
import { LegendBox, LegendLabel } from './Legend'
function loadGeometry(file: string, checkUV = false): BufferGeometry {
const loader = new OBJLoader()
@ -28,13 +29,10 @@ function loadGeometry(file: string, checkUV = false): BufferGeometry {
return geometry
}
function Loader3DBeforeAfter({
before,
after,
}: {
before: string
after: string
}) {
function Loader3DUnified({ before, after }: { before: string; after: string }) {
const [showUnchanged, setShowUnchanged] = useState(true)
const [showAdditions, setShowAdditions] = useState(true)
const [showDeletions, setShowDeletions] = useState(true)
const cameraRef = useRef<any>()
const [beforeGeometry, setBeforeGeometry] = useState<BufferGeometry>()
const [afterGeometry, setAfterGeometry] = useState<BufferGeometry>()
@ -45,13 +43,38 @@ function Loader3DBeforeAfter({
setAfterGeometry(loadGeometry(after, true))
}, [after])
return beforeGeometry && afterGeometry ? (
<Viewer3D cameraRef={cameraRef} geometry={beforeGeometry}>
<BeforeAfterModel
beforeGeometry={beforeGeometry}
afterGeometry={afterGeometry}
cameraRef={cameraRef}
/>
</Viewer3D>
<>
<Viewer3D cameraRef={cameraRef} geometry={beforeGeometry}>
<UnifiedModel
beforeGeometry={beforeGeometry}
afterGeometry={afterGeometry}
cameraRef={cameraRef}
showUnchanged={showUnchanged}
showAdditions={showAdditions}
showDeletions={showDeletions}
/>
</Viewer3D>
<LegendBox>
<LegendLabel
text="Unchanged"
color="neutral"
enabled={showUnchanged}
onChange={enabled => setShowUnchanged(enabled)}
/>
<LegendLabel
text="Additions"
color="success"
enabled={showAdditions}
onChange={enabled => setShowAdditions(enabled)}
/>
<LegendLabel
text="Deletions"
color="danger"
enabled={showDeletions}
onChange={enabled => setShowDeletions(enabled)}
/>
</LegendBox>
</>
) : (
<Box p={3}>
<Text>Sorry, the rich diff can't be displayed for this file.</Text>
@ -96,9 +119,15 @@ export function CadDiff({ before, after }: FileDiff): React.ReactElement {
}
return (
<>
<Box display="flex" height={300} overflow="hidden" minWidth={0}>
<Box
display="flex"
height={300}
overflow="hidden"
minWidth={0}
position="relative"
>
{canShowUnified && showUnified && (
<Loader3DBeforeAfter before={before} after={after} />
<Loader3DUnified before={before} after={after} />
)}
{!showUnified && (
<>

View File

@ -0,0 +1,51 @@
import { DotFillIcon } from '@primer/octicons-react'
import { Box, Label, Text } from '@primer/react'
import { PropsWithChildren } from 'react'
export type LegendLabelProps = {
text: string
color: 'neutral' | 'danger' | 'success'
enabled: boolean
onChange?: (enabled: boolean) => void
}
export function LegendLabel({
text,
color,
enabled,
onChange,
}: LegendLabelProps): React.ReactElement {
return (
<Box py={1}>
<Label
onClick={() => onChange && onChange(!enabled)}
sx={{
border: 'none',
backgroundColor: enabled
? `${color}.subtle`
: 'transparent',
color: `${color}.muted`,
cursor: 'pointer',
}}
>
<DotFillIcon size={16} />
<Text color="fg.default">{text}</Text>
</Label>
</Box>
)
}
export function LegendBox({ children }: PropsWithChildren): React.ReactElement {
return (
<Box
position="absolute"
top={2}
left={2}
p={2}
backgroundColor="canvas.default"
color="fg.muted"
>
{children}
</Box>
)
}

View File

@ -4,21 +4,27 @@ import { BufferGeometry } from 'three'
import { Geometry, Base, Subtraction, Intersection } from '@react-three/csg'
import { BaseModel } from './BaseModel'
type BeforeAfterModelProps = {
type UnifiedModelProps = {
beforeGeometry: BufferGeometry
afterGeometry: BufferGeometry
cameraRef: MutableRefObject<any>
showUnchanged: boolean
showAdditions: boolean
showDeletions: boolean
}
export function BeforeAfterModel({
export function UnifiedModel({
beforeGeometry,
afterGeometry,
cameraRef,
}: BeforeAfterModelProps) {
showUnchanged,
showAdditions,
showDeletions,
}: UnifiedModelProps) {
const { theme } = useTheme()
const commonColor = theme?.colors.fg.default
const additionsColor = theme?.colors.success.fg
const deletionsColor = theme?.colors.danger.fg
const commonColor = theme?.colors.fg.muted
const additionsColor = theme?.colors.success.muted
const deletionsColor = theme?.colors.danger.muted
return (
// TODO: here we give beforeGeometry for auto camera centering,
@ -29,7 +35,7 @@ export function BeforeAfterModel({
<meshPhongMaterial
color={commonColor}
transparent
opacity={0.95}
opacity={showUnchanged ? 0.8 : 0}
/>
<Geometry>
<Base geometry={beforeGeometry} />
@ -38,7 +44,11 @@ export function BeforeAfterModel({
</mesh>
{/* Additions */}
<mesh>
<meshPhongMaterial color={additionsColor} />
<meshPhongMaterial
color={additionsColor}
transparent
opacity={showAdditions ? 1 : 0}
/>
<Geometry>
<Base geometry={afterGeometry} />
<Subtraction geometry={beforeGeometry} />
@ -46,7 +56,11 @@ export function BeforeAfterModel({
</mesh>
{/* Deletions */}
<mesh>
<meshPhongMaterial color={deletionsColor} />
<meshPhongMaterial
color={deletionsColor}
transparent
opacity={showDeletions ? 1 : 0}
/>
<Geometry>
<Base geometry={beforeGeometry} />
<Subtraction geometry={afterGeometry} />