wip preview/minimap window

pull/5775/head
Peng Xiao 2022-06-10 18:25:39 +08:00
parent 3ae4daaa8d
commit 7def1f4d2c
10 changed files with 126 additions and 47 deletions

View File

@ -5,29 +5,14 @@ import {
AppCanvas,
AppProvider,
TLReactCallbacks,
TLReactComponents,
TLReactShapeConstructor,
TLReactToolConstructor,
TLReactComponents, TLReactToolConstructor
} from '@tldraw/react'
import * as React from 'react'
import { AppUI } from '~components/AppUI'
import { ContextBar } from '~components/ContextBar/ContextBar'
import { useFileDrop } from '~hooks/useFileDrop'
import { LogseqContext } from '~lib/logseq-context'
import {
BoxShape,
DotShape,
EllipseShape,
HighlighterShape,
ImageShape,
LineShape,
LogseqPortalShape,
PenShape,
PolygonShape,
Shape,
TextShape,
YouTubeShape,
} from '~lib/shapes'
import { Shape, shapes } from '~lib/shapes'
import {
BoxTool,
DotTool,
@ -39,27 +24,13 @@ import {
PenTool,
PolygonTool,
TextTool,
YouTubeTool,
YouTubeTool
} from '~lib/tools'
const components: TLReactComponents<Shape> = {
ContextBar: ContextBar,
}
const shapes: TLReactShapeConstructor<Shape>[] = [
BoxShape,
DotShape,
EllipseShape,
HighlighterShape,
ImageShape,
LineShape,
PenShape,
PolygonShape,
TextShape,
YouTubeShape,
LogseqPortalShape,
]
const tools: TLReactToolConstructor<Shape>[] = [
BoxTool,
DotTool,

View File

@ -4,13 +4,23 @@ import { ToolBar } from './Toolbar'
import { StatusBar } from './StatusBar'
import { PrimaryTools } from './PrimaryTools'
import { DevTools } from './Devtools'
import { useApp } from '@tldraw/react'
import { WhiteboardPreview } from '~lib'
const isDev = process.env.NODE_ENV === 'development'
export const AppUI = observer(function AppUI() {
const app = useApp()
const preview = React.useMemo(() => {
const WP = new WhiteboardPreview(app.serialized)
return WP.getPreview()
}, [app.serialized])
return (
<>
{/* <ToolBar /> */}
{preview}
{isDev && <StatusBar />}
{isDev && <DevTools />}
<PrimaryTools />

View File

@ -1,2 +1,3 @@
export * from './shapes'
export * from './tools'
export * from './preview'

View File

@ -0,0 +1,63 @@
import type { TLDocumentModel, TLShapeConstructor } from '@tldraw/core'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { Shape, shapes } from './shapes'
const ShapesMap = new Map(shapes.map(shape => [shape.id, shape]))
const getShapeClass = (type: string): TLShapeConstructor<Shape> => {
if (!type) throw Error('No shape type provided.')
const Shape = ShapesMap.get(type)
if (!Shape) throw Error(`Could not find shape class for ${type}`)
return Shape
}
export class WhiteboardPreview {
shapes: Shape[] | undefined
constructor(serializedApp?: TLDocumentModel<Shape>) {
if (serializedApp) {
this.deserialize(serializedApp)
}
}
deserialize(snapshot: TLDocumentModel) {
const page = snapshot.pages.find(p => snapshot.currentPageId === p.id)
this.shapes = page?.shapes.map(s => {
const ShapeClass = getShapeClass(s.type)
return new ShapeClass(s)
})
}
getPreview() {
// TODO: translate each shape to where it should be
return (
<svg
style={{
pointerEvents: 'none',
height: '100%',
width: '100%',
bottom: 0,
right: 0,
position: 'fixed',
border: '1px solid black',
transformOrigin: 'bottom right',
transform: 'scale(0.2)',
}}
>
{this.shapes?.map(s => {
const {
bounds,
props: { rotation },
} = s
const transformStr = `translate(${bounds.minX}px, ${bounds.minY}px)
rotate(${(rotation ?? 0) + (bounds.rotation ?? 0)}rad)`
return (
<g style={{ transform: transformStr }} key={s.id}>
{s.getShapeSVGJsx()}
</g>
)
})}
</svg>
)
}
}

View File

@ -128,7 +128,7 @@ export class LineShape extends TLLineShape<LineShapeProps> {
return offset
}, [bounds, scale, midPoint])
return (
<>
<g>
<LabelMask id={id} bounds={bounds} labelSize={labelSize} offset={offset} scale={scale} />
<path
mask={label ? `url(#${id}_clip)` : ``}
@ -151,7 +151,7 @@ export class LineShape extends TLLineShape<LineShapeProps> {
fill="transparent"
/>
)}
</>
</g>
)
})

View File

@ -32,9 +32,11 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
pageId: '',
}
hideRotateHandle = true
canChangeAspectRatio = true
canFlip = true
canActivate = true
canEdit = true
ReactContextBar = observer(() => {
const { pageId } = this.props

View File

@ -1,14 +1,15 @@
import type { BoxShape } from './BoxShape'
import type { DotShape } from './DotShape'
import type { EllipseShape } from './EllipseShape'
import type { HighlighterShape } from './HighlighterShape'
import type { ImageShape } from './ImageShape'
import type { LineShape } from './LineShape'
import type { PenShape } from './PenShape'
import type { PolygonShape } from './PolygonShape'
import type { TextShape } from './TextShape'
import type { YouTubeShape } from './YouTubeShape'
import type { LogseqPortalShape } from './LogseqPortalShape';
import { BoxShape } from './BoxShape'
import { DotShape } from './DotShape'
import { EllipseShape } from './EllipseShape'
import { HighlighterShape } from './HighlighterShape'
import { ImageShape } from './ImageShape'
import { LineShape } from './LineShape'
import { PenShape } from './PenShape'
import { PolygonShape } from './PolygonShape'
import { TextShape } from './TextShape'
import { YouTubeShape } from './YouTubeShape'
import { LogseqPortalShape } from './LogseqPortalShape'
import type { TLReactShapeConstructor } from '@tldraw/react'
export type Shape =
| BoxShape
@ -35,3 +36,17 @@ export * from './PolygonShape'
export * from './TextShape'
export * from './YouTubeShape'
export * from './LogseqPortalShape'
export const shapes: TLReactShapeConstructor<Shape>[] = [
BoxShape,
DotShape,
EllipseShape,
HighlighterShape,
ImageShape,
LineShape,
PenShape,
PolygonShape,
TextShape,
YouTubeShape,
LogseqPortalShape,
]

View File

@ -67,6 +67,7 @@
.logseq-tldraw .statusbar {
position: absolute;
font-family: monospace;
font-size: 10px;
bottom: 0;
grid-row: 3;
width: 100%;

View File

@ -31,8 +31,6 @@ export interface TLShapeProps {
scale?: number[]
rotation?: number
handles?: Record<string, TLHandle>
label?: string
labelPosition?: number[]
clipping?: number | number[]
assetId?: string
children?: string[]
@ -330,4 +328,21 @@ export abstract class TLShape<P extends TLShapeProps = TLShapeProps, M = any> {
handles: nextHandles,
})
}
/**
* Get a svg group element that can be used to render the shape with only the props data. In the
* base, draw any shape as a box. Can be overridden by subclasses.
*/
getShapeSVGJsx() {
// Do not need to consider the original point here
const bounds = this.getBounds()
return (
<rect
fill="var(--tl-foreground)"
fillOpacity={0.2}
width={bounds.width}
height={bounds.height}
/>
)
}
}

View File

@ -114,6 +114,7 @@ export class TranslatingState<
onExit = () => {
// Resume the history when we exit
this.app.history.resume()
this.app.persist()
// Reset initial data
this.didClone = false