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:
@ -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 && (
|
||||
<>
|
||||
|
51
src/components/diff/Legend.tsx
Normal file
51
src/components/diff/Legend.tsx
Normal 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>
|
||||
)
|
||||
}
|
@ -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} />
|
Reference in New Issue
Block a user