Debugging cleanup / misc cleanup (#2025)

This PR:
- removes feature flags for people menu, highlighter shape
- removes debugging for cursors
- adds a debug flag for hiding shapes
- changes Canvas to use `useValue` rather than `track`
- removes the default background color on `tl-background`
- in the editor components, makes `Background` null by default

### Change Type

- [x] `minor` — New feature
This commit is contained in:
Steve Ruiz 2023-10-06 09:57:46 +01:00 committed by GitHub
parent a9236bcbb0
commit 9c1dc00740
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 95 additions and 135 deletions

View file

@ -84,7 +84,7 @@ export const allExamples: Example[] = [
element: <ScrollExample />,
},
{
title: 'Custom config',
title: 'Custom shapes / tools',
path: '/custom-config',
element: <CustomConfigExample />,
},

View file

@ -282,9 +282,9 @@ export const CAMERA_SLIDE_FRICTION = 0.09;
export function canonicalizeRotation(a: number): number;
// @public (undocumented)
export const Canvas: React_2.MemoExoticComponent<({ className }: {
className?: string | undefined;
}) => JSX.Element>;
export function Canvas({ className }: {
className?: string;
}): JSX.Element;
// @public (undocumented)
export class Circle2d extends Geometry2d {
@ -411,11 +411,12 @@ export const debugFlags: {
elementRemovalLogging: DebugFlag<boolean>;
debugSvg: DebugFlag<boolean>;
throwToBlob: DebugFlag<boolean>;
logMessages: DebugFlag<never[]>;
logMessages: DebugFlag<any[]>;
resetConnectionEveryPing: DebugFlag<boolean>;
debugCursors: DebugFlag<boolean>;
forceSrgb: DebugFlag<boolean>;
debugGeometry: DebugFlag<boolean>;
hideShapes: DebugFlag<boolean>;
};
// @internal (undocumented)
@ -955,10 +956,7 @@ export const EVENT_NAME_MAP: Record<Exclude<TLEventName, TLPinchEventName>, keyo
export function extractSessionStateFromLegacySnapshot(store: Record<string, UnknownRecord>): null | TLSessionStateSnapshot;
// @internal (undocumented)
export const featureFlags: {
peopleMenu: DebugFlag<boolean>;
highlighterTool: DebugFlag<boolean>;
};
export const featureFlags: Record<string, DebugFlag<boolean>>;
// @public (undocumented)
export type GapsSnapLine = {

View file

@ -213,7 +213,6 @@ input,
left: 0px;
width: 100%;
height: 100%;
background-color: var(--color-background);
color: var(--color-text);
z-index: var(--layer-canvas);
cursor: var(--tl-cursor);
@ -275,7 +274,6 @@ input,
.tl-background {
position: absolute;
inset: 0px;
background-color: var(--color-background);
}
/* --------------------- Grid Layer --------------------- */

View file

@ -21,7 +21,7 @@ import { Shape } from './Shape'
import { ShapeIndicator } from './ShapeIndicator'
/** @public */
export const Canvas = track(function Canvas({ className }: { className?: string }) {
export function Canvas({ className }: { className?: string }) {
const editor = useEditor()
const { Background, SvgDefs } = useEditorComponents()
@ -81,9 +81,12 @@ export const Canvas = track(function Canvas({ className }: { className?: string
[editor]
)
React.useEffect(() => {
rCanvas.current?.focus()
}, [])
const hideShapes = useValue('debug_shapes', () => debugFlags.hideShapes.value, [debugFlags])
const debugSvg = useValue('debug_svg', () => debugFlags.debugSvg.value, [debugFlags])
const debugGeometry = useValue('debug_geometry', () => debugFlags.debugGeometry.value, [
debugFlags,
])
return (
<div
ref={rCanvas}
@ -107,11 +110,11 @@ export const Canvas = track(function Canvas({ className }: { className?: string
</svg>
<div ref={rHtmlLayer} className="tl-html-layer tl-shapes" draggable={false}>
<SelectionBackgroundWrapper />
<ShapesToDisplay />
{hideShapes ? null : debugSvg ? <ShapesWithSVGs /> : <ShapesToDisplay />}
</div>
<div className="tl-fixed-layer tl-overlays">
<div ref={rHtmlLayer2} className="tl-html-layer">
{debugFlags.debugGeometry.value && <GeometryDebuggingView />}
{debugGeometry ? <GeometryDebuggingView /> : null}
<HandlesWrapper />
<BrushWrapper />
<ScribbleWrapper />
@ -126,7 +129,7 @@ export const Canvas = track(function Canvas({ className }: { className?: string
</div>
</div>
)
})
}
function GridWrapper() {
const editor = useEditor()
@ -278,24 +281,27 @@ function HandleWrapper({
)
}
const ShapesToDisplay = track(function ShapesToDisplay() {
function ShapesWithSVGs() {
const editor = useEditor()
const { renderingShapes } = editor
const renderingShapes = useValue('rendering shapes', () => editor.renderingShapes, [editor])
const debugSvg = debugFlags.debugSvg.value
if (debugSvg) {
return (
<>
{renderingShapes.map((result) => (
<React.Fragment key={result.id + '_fragment'}>
<Shape {...result} />
<DebugSvgCopy id={result.id} />
</React.Fragment>
))}
</>
)
}
return (
<>
{renderingShapes.map((result) => (
<React.Fragment key={result.id + '_fragment'}>
<Shape {...result} />
<DebugSvgCopy id={result.id} />
</React.Fragment>
))}
</>
)
}
function ShapesToDisplay() {
const editor = useEditor()
const renderingShapes = useValue('rendering shapes', () => editor.renderingShapes, [editor])
return (
<>
@ -304,7 +310,7 @@ const ShapesToDisplay = track(function ShapesToDisplay() {
))}
</>
)
})
}
function SelectedIdIndicators() {
const editor = useEditor()
@ -455,12 +461,14 @@ const DebugSvgCopy = track(function DupSvg({ id }: { id: TLShapeId }) {
)
})
const UiLogger = track(() => {
const logMessages = debugFlags.logMessages.value
function UiLogger() {
const uiLog = useValue('debugging ui log', () => debugFlags.logMessages.value, [debugFlags])
if (!uiLog.length) return null
return (
<div className="debug__ui-logger">
{logMessages.map((message, messageIndex) => {
{uiLog.map((message, messageIndex) => {
const text = typeof message === 'string' ? message : JSON.stringify(message)
return (
@ -471,7 +479,7 @@ const UiLogger = track(() => {
})}
</div>
)
})
}
export function SelectionForegroundWrapper() {
const editor = useEditor()

View file

@ -1,7 +1,6 @@
import { track } from '@tldraw/state'
import { modulate } from '@tldraw/utils'
import { useEffect, useState } from 'react'
import { HIT_TEST_MARGIN } from '../constants'
import { useEditor } from '../hooks/useEditor'
function useTick(isEnabled = true) {
@ -27,6 +26,7 @@ export const GeometryDebuggingView = track(function GeometryDebuggingView({
showClosestPointOnOutline?: boolean
}) {
const editor = useEditor()
useTick(showClosestPointOnOutline)
const {
@ -56,18 +56,25 @@ export const GeometryDebuggingView = track(function GeometryDebuggingView({
const pointInShapeSpace = editor.getPointInShapeSpace(shape, currentPagePoint)
const nearestPointOnShape = geometry.nearestPoint(pointInShapeSpace)
const distanceToPoint = geometry.distanceToPoint(pointInShapeSpace)
const distanceToPoint = geometry.distanceToPoint(pointInShapeSpace, true)
const dist = Math.abs(distanceToPoint) * zoomLevel
const hitInside = distanceToPoint < 0
const { vertices } = geometry
return (
<g key={result.id + '_outline'} transform={pageTransform.toCssString()}>
<g
key={result.id + '_outline'}
transform={pageTransform.toCssString()}
strokeLinecap="round"
strokeLinejoin="round"
>
{showStroke && (
<path
stroke="red"
strokeWidth={2}
strokeWidth="2"
fill="none"
opacity={0.5}
opacity="1"
d={geometry.toSimpleSvgPath()}
/>
)}
@ -77,20 +84,21 @@ export const GeometryDebuggingView = track(function GeometryDebuggingView({
key={`v${i}`}
cx={v.x}
cy={v.y}
r={2}
fill={`hsl(${modulate(i, [0, vertices.length - 1], [120, 0])}, 100%, 50%)`}
r="2"
fill={`hsl(${modulate(i, [0, vertices.length - 1], [120, 200])}, 100%, 50%)`}
stroke="black"
strokeWidth="1"
/>
))}
{distanceToPoint > 0 && showClosestPointOnOutline && (
{showClosestPointOnOutline && dist < 150 && (
<line
x1={nearestPointOnShape.x}
y1={nearestPointOnShape.y}
x2={pointInShapeSpace.x}
y2={pointInShapeSpace.y}
strokeWidth={2}
stroke={distanceToPoint < HIT_TEST_MARGIN / zoomLevel ? 'red' : 'pink'}
opacity={1 - dist / 150}
stroke={hitInside ? 'goldenrod' : 'dodgerblue'}
strokeWidth="2"
/>
)}
</g>

View file

@ -1,9 +1,6 @@
import { createContext, useContext, useMemo } from 'react'
import { ShapeIndicator, TLShapeIndicatorComponent } from '../components/ShapeIndicator'
import {
DefaultBackground,
TLBackgroundComponent,
} from '../components/default-components/DefaultBackground'
import { TLBackgroundComponent } from '../components/default-components/DefaultBackground'
import { DefaultBrush, TLBrushComponent } from '../components/default-components/DefaultBrush'
import {
DefaultCollaboratorHint,
@ -91,7 +88,7 @@ export function EditorComponentsProvider({ overrides, children }: ComponentsCont
<EditorComponentsContext.Provider
value={useMemo(
() => ({
Background: DefaultBackground,
Background: null,
SvgDefs: DefaultSvgDefs,
Brush: DefaultBrush,
ZoomBrush: DefaultBrush,

View file

@ -7,12 +7,10 @@ import { Atom, atom, react } from '@tldraw/state'
// development. Use `createFeatureFlag` to create a boolean flag which will be
// `true` by default in development and staging, and `false` in production.
/** @internal */
export const featureFlags = {
export const featureFlags: Record<string, DebugFlag<boolean>> = {
// todo: remove this. it's not used, but we only have one feature flag and i
// wanted an example :(
peopleMenu: createFeatureFlag('peopleMenu'),
highlighterTool: createFeatureFlag('highlighterTool', { all: true }),
} satisfies Record<string, DebugFlag<boolean>>
}
/** @internal */
export const debugFlags = {
@ -44,7 +42,7 @@ export const debugFlags = {
throwToBlob: createDebugValue('throwToBlob', {
defaults: { all: false },
}),
logMessages: createDebugValue('uiLog', { defaults: { all: [] } }),
logMessages: createDebugValue('uiLog', { defaults: { all: [] as any[] } }),
resetConnectionEveryPing: createDebugValue('resetConnectionEveryPing', {
defaults: { all: false },
}),
@ -53,6 +51,7 @@ export const debugFlags = {
}),
forceSrgb: createDebugValue('forceSrgbColors', { defaults: { all: false } }),
debugGeometry: createDebugValue('debugGeometry', { defaults: { all: false } }),
hideShapes: createDebugValue('hideShapes', { defaults: { all: false } }),
}
declare global {
@ -109,16 +108,17 @@ function createDebugValue<T>(
shouldStoreForSession,
})
}
function createFeatureFlag(
name: string,
defaults: Defaults<boolean> = { all: true, production: false }
) {
return createDebugValueBase({
name,
defaults,
shouldStoreForSession: true,
})
}
// function createFeatureFlag(
// name: string,
// defaults: Defaults<boolean> = { all: true, production: false }
// ) {
// return createDebugValueBase({
// name,
// defaults,
// shouldStoreForSession: true,
// })
// }
function createDebugValueBase<T>(def: DebugFlagDef<T>): DebugFlag<T> {
const defaultValue = getDefaultValue(def)

View file

@ -184,30 +184,7 @@ const DebugMenuContent = track(function DebugMenuContent({
<DebugFlagToggle flag={debugFlags.debugSvg} />
<DebugFlagToggle flag={debugFlags.forceSrgb} />
<DebugFlagToggle flag={debugFlags.debugGeometry} />
<DebugFlagToggle
flag={debugFlags.debugCursors}
onChange={(enabled) => {
if (enabled) {
const MAX_COLUMNS = 5
const partials = CURSOR_NAMES.map((name, i) => {
return {
id: createShapeId(),
type: 'geo',
x: (i % MAX_COLUMNS) * 175,
y: Math.floor(i / MAX_COLUMNS) * 175,
props: {
text: name,
w: 150,
h: 150,
fill: 'semi',
},
}
})
editor.createShapes(partials)
}
}}
/>
<DebugFlagToggle flag={debugFlags.hideShapes} />
</DropdownMenu.Group>
<DropdownMenu.Group>
{Object.values(featureFlags).map((flag) => {
@ -256,27 +233,6 @@ const DebugFlagToggle = track(function DebugFlagToggle({
)
})
const CURSOR_NAMES = [
'none',
'default',
'pointer',
'cross',
'move',
'grab',
'grabbing',
'text',
'ew-resize',
'ns-resize',
'nesw-resize',
'nwse-resize',
'nwse-rotate',
'nesw-rotate',
'senw-rotate',
'swne-rotate',
'zoom-in',
'zoom-out',
]
function ExampleDialog({
title = 'title',
body = 'hello hello hello',

View file

@ -1,4 +1,4 @@
import { Editor, compact, featureFlags, useEditor, useValue } from '@tldraw/editor'
import { Editor, compact, useEditor } from '@tldraw/editor'
import React from 'react'
import { TLUiToolItem, TLUiToolsContextType, useTools } from './useTools'
@ -41,7 +41,6 @@ export function ToolbarSchemaProvider({ overrides, children }: TLUiToolbarSchema
const editor = useEditor()
const tools = useTools()
const highlighterEnabled = useValue(featureFlags.highlighterTool)
const toolbarSchema = React.useMemo<TLUiToolbarSchemaContextType>(() => {
const schema: TLUiToolbarSchemaContextType = compact([
@ -72,7 +71,7 @@ export function ToolbarSchemaProvider({ overrides, children }: TLUiToolbarSchema
toolbarItem(tools['arrow-right']),
toolbarItem(tools.frame),
toolbarItem(tools.line),
highlighterEnabled ? toolbarItem(tools.highlight) : null,
toolbarItem(tools.highlight),
toolbarItem(tools.laser),
])
@ -81,7 +80,7 @@ export function ToolbarSchemaProvider({ overrides, children }: TLUiToolbarSchema
}
return schema
}, [editor, highlighterEnabled, overrides, tools])
}, [editor, overrides, tools])
return (
<ToolbarSchemaContext.Provider value={toolbarSchema}>{children}</ToolbarSchemaContext.Provider>

View file

@ -1,4 +1,4 @@
import { Editor, GeoShapeGeoStyle, featureFlags, useEditor, useValue } from '@tldraw/editor'
import { Editor, GeoShapeGeoStyle, useEditor } from '@tldraw/editor'
import * as React from 'react'
import { EmbedDialog } from '../components/EmbedDialog'
import { TLUiIconType } from '../icon-types'
@ -45,8 +45,6 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
const { addDialog } = useDialogs()
const insertMedia = useInsertMedia()
const highlighterEnabled = useValue(featureFlags.highlighterTool)
const tools = React.useMemo<TLUiToolsContextType>(() => {
const toolsArray: TLUiToolItem[] = [
{
@ -207,20 +205,18 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
},
]
if (highlighterEnabled) {
toolsArray.push({
id: 'highlight',
label: 'tool.highlight',
readonlyOk: true,
icon: 'tool-highlight',
// TODO: pick a better shortcut
kbd: '!d',
onSelect(source) {
editor.setCurrentTool('highlight')
trackEvent('select-tool', { source, id: 'highlight' })
},
})
}
toolsArray.push({
id: 'highlight',
label: 'tool.highlight',
readonlyOk: true,
icon: 'tool-highlight',
// TODO: pick a better shortcut
kbd: '!d',
onSelect(source) {
editor.setCurrentTool('highlight')
trackEvent('select-tool', { source, id: 'highlight' })
},
})
const tools = Object.fromEntries(toolsArray.map((t) => [t.id, t]))
@ -229,7 +225,7 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
}
return tools
}, [highlighterEnabled, overrides, editor, trackEvent, insertMedia, addDialog])
}, [overrides, editor, trackEvent, insertMedia, addDialog])
return <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>
}