Adds provisional logger
This commit is contained in:
parent
48c659a68a
commit
8180146eb3
14 changed files with 3583 additions and 204 deletions
|
@ -120,16 +120,16 @@ Array [
|
||||||
"id": "bend",
|
"id": "bend",
|
||||||
"index": 2,
|
"index": 2,
|
||||||
"point": Array [
|
"point": Array [
|
||||||
0,
|
50,
|
||||||
0,
|
50,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"end": Object {
|
"end": Object {
|
||||||
"id": "end",
|
"id": "end",
|
||||||
"index": 1,
|
"index": 1,
|
||||||
"point": Array [
|
"point": Array [
|
||||||
0,
|
100,
|
||||||
0,
|
100,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"start": Object {
|
"start": Object {
|
||||||
|
|
|
@ -7,9 +7,14 @@ import { CodeError, CodeFile, CodeResult } from 'types'
|
||||||
import CodeDocs from './code-docs'
|
import CodeDocs from './code-docs'
|
||||||
import { generateFromCode } from 'state/code/generate'
|
import { generateFromCode } from 'state/code/generate'
|
||||||
import * as Panel from '../panel'
|
import * as Panel from '../panel'
|
||||||
import { IconButton } from '../shared'
|
import { breakpoints, IconButton } from '../shared'
|
||||||
import { Code, PlayCircle, ChevronUp, ChevronDown } from 'react-feather'
|
import {
|
||||||
import { Cross2Icon } from '@radix-ui/react-icons'
|
Cross2Icon,
|
||||||
|
CodeIcon,
|
||||||
|
PlayIcon,
|
||||||
|
ChevronUpIcon,
|
||||||
|
ChevronDownIcon,
|
||||||
|
} from '@radix-ui/react-icons'
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
import { ReaderIcon } from '@radix-ui/react-icons'
|
import { ReaderIcon } from '@radix-ui/react-icons'
|
||||||
const CodeEditor = dynamic(() => import('./code-editor'))
|
const CodeEditor = dynamic(() => import('./code-editor'))
|
||||||
|
@ -17,6 +22,7 @@ const CodeEditor = dynamic(() => import('./code-editor'))
|
||||||
const increaseCodeSize = () => state.send('INCREASED_CODE_FONT_SIZE')
|
const increaseCodeSize = () => state.send('INCREASED_CODE_FONT_SIZE')
|
||||||
const decreaseCodeSize = () => state.send('DECREASED_CODE_FONT_SIZE')
|
const decreaseCodeSize = () => state.send('DECREASED_CODE_FONT_SIZE')
|
||||||
const toggleCodePanel = () => state.send('TOGGLED_CODE_PANEL_OPEN')
|
const toggleCodePanel = () => state.send('TOGGLED_CODE_PANEL_OPEN')
|
||||||
|
const handleWheel = (e: React.WheelEvent) => e.stopPropagation()
|
||||||
|
|
||||||
export default function CodePanel(): JSX.Element {
|
export default function CodePanel(): JSX.Element {
|
||||||
const rContainer = useRef<HTMLDivElement>(null)
|
const rContainer = useRef<HTMLDivElement>(null)
|
||||||
|
@ -132,56 +138,48 @@ export default function CodePanel(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Panel.Root
|
<Panel.Root
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
bp={breakpoints}
|
||||||
data-bp-desktop
|
data-bp-desktop
|
||||||
ref={rContainer}
|
ref={rContainer}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
variant="code"
|
variant="code"
|
||||||
onWheel={(e) => e.stopPropagation()}
|
onWheel={handleWheel}
|
||||||
>
|
>
|
||||||
{isOpen ? (
|
{isOpen ? (
|
||||||
<Panel.Layout>
|
<Panel.Layout>
|
||||||
<Panel.Header side="left">
|
<Panel.Header side="left">
|
||||||
<IconButton
|
<IconButton bp={breakpoints} size="small" onClick={toggleCodePanel}>
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
|
||||||
size="small"
|
|
||||||
onClick={toggleCodePanel}
|
|
||||||
>
|
|
||||||
<Cross2Icon />
|
<Cross2Icon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<h3>Code</h3>
|
<h3>Code</h3>
|
||||||
<ButtonsGroup>
|
<ButtonsGroup>
|
||||||
<FontSizeButtons>
|
<FontSizeButtons>
|
||||||
<IconButton
|
<IconButton
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
bp={breakpoints}
|
||||||
size="small"
|
size="small"
|
||||||
disabled={!local.isIn('editingCode')}
|
disabled={!local.isIn('editingCode')}
|
||||||
onClick={increaseCodeSize}
|
onClick={increaseCodeSize}
|
||||||
>
|
>
|
||||||
<ChevronUp />
|
<ChevronUpIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
size="small"
|
size="small"
|
||||||
disabled={!local.isIn('editingCode')}
|
disabled={!local.isIn('editingCode')}
|
||||||
onClick={decreaseCodeSize}
|
onClick={decreaseCodeSize}
|
||||||
>
|
>
|
||||||
<ChevronDown />
|
<ChevronDownIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</FontSizeButtons>
|
</FontSizeButtons>
|
||||||
<IconButton
|
<IconButton bp={breakpoints} size="small" onClick={toggleDocs}>
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
|
||||||
size="small"
|
|
||||||
onClick={toggleDocs}
|
|
||||||
>
|
|
||||||
<ReaderIcon />
|
<ReaderIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
bp={breakpoints}
|
||||||
size="small"
|
size="small"
|
||||||
disabled={!local.isIn('editingCode')}
|
disabled={!local.isIn('editingCode')}
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
>
|
>
|
||||||
<PlayCircle />
|
<PlayIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</ButtonsGroup>
|
</ButtonsGroup>
|
||||||
</Panel.Header>
|
</Panel.Header>
|
||||||
|
@ -201,12 +199,8 @@ export default function CodePanel(): JSX.Element {
|
||||||
{error && <Panel.Footer>{error.message}</Panel.Footer>}
|
{error && <Panel.Footer>{error.message}</Panel.Footer>}
|
||||||
</Panel.Layout>
|
</Panel.Layout>
|
||||||
) : (
|
) : (
|
||||||
<IconButton
|
<IconButton bp={breakpoints} size="small" onClick={toggleCodePanel}>
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
<CodeIcon />
|
||||||
size="small"
|
|
||||||
onClick={toggleCodePanel}
|
|
||||||
>
|
|
||||||
<Code />
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
</Panel.Root>
|
</Panel.Root>
|
||||||
|
|
200
components/debug-panel/debug-panel.tsx
Normal file
200
components/debug-panel/debug-panel.tsx
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
|
import styled from 'styles'
|
||||||
|
import React, { useRef } from 'react'
|
||||||
|
import state, { useSelector } from 'state'
|
||||||
|
import * as Panel from '../panel'
|
||||||
|
import { breakpoints, IconButton, RowButton, IconWrapper } from '../shared'
|
||||||
|
import {
|
||||||
|
Cross2Icon,
|
||||||
|
PlayIcon,
|
||||||
|
CrumpledPaperIcon,
|
||||||
|
StopIcon,
|
||||||
|
ClipboardCopyIcon,
|
||||||
|
} from '@radix-ui/react-icons'
|
||||||
|
import logger from 'state/logger'
|
||||||
|
import { useStateDesigner } from '@state-designer/react'
|
||||||
|
|
||||||
|
const stopPropagation = (e: React.KeyboardEvent) => e.stopPropagation()
|
||||||
|
const toggleDebugPanel = () => state.send('TOGGLED_DEBUG_PANEL')
|
||||||
|
|
||||||
|
export default function CodePanel(): JSX.Element {
|
||||||
|
const rContainer = useRef<HTMLDivElement>(null)
|
||||||
|
const isDebugging = useSelector((s) => s.data.settings.isDebugMode)
|
||||||
|
const isOpen = useSelector((s) => s.data.settings.isDebugOpen)
|
||||||
|
|
||||||
|
const rTextArea = useRef<HTMLTextAreaElement>(null)
|
||||||
|
|
||||||
|
const local = useStateDesigner({
|
||||||
|
initial: 'stopped',
|
||||||
|
data: {
|
||||||
|
log: '',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
stopped: {
|
||||||
|
on: {
|
||||||
|
CHANGED_LOG: 'setLog',
|
||||||
|
COPIED_LOG: { if: 'hasLog', do: 'copyLog' },
|
||||||
|
PLAYED_BACK_LOG: { if: 'hasLog', do: 'playbackLog' },
|
||||||
|
STARTED_LOGGING: { do: 'startLogger', to: 'logging' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
logging: {
|
||||||
|
on: {
|
||||||
|
STOPPED_LOGGING: { do: 'stopLogger', to: 'stopped' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
conditions: {
|
||||||
|
hasLog(data) {
|
||||||
|
return data.log !== ''
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setLog(data, payload: { value: string }) {
|
||||||
|
data.log = payload.value
|
||||||
|
},
|
||||||
|
startLogger(data) {
|
||||||
|
logger.start(state.data)
|
||||||
|
data.log = ''
|
||||||
|
},
|
||||||
|
stopLogger(data) {
|
||||||
|
logger.stop(state.data)
|
||||||
|
data.log = logger.copyToJson()
|
||||||
|
},
|
||||||
|
playbackLog(data) {
|
||||||
|
logger.playback(state.data, data.log)
|
||||||
|
},
|
||||||
|
copyLog() {
|
||||||
|
logger.copyToJson()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!isDebugging) return null
|
||||||
|
|
||||||
|
const handleLoggingStop = () => local.send('STOPPED_LOGGING')
|
||||||
|
|
||||||
|
const handlePlayback = () =>
|
||||||
|
local.send('PLAYED_BACK_LOG', { log: rTextArea.current?.value })
|
||||||
|
|
||||||
|
const handleLoggingStart = () => local.send('STARTED_LOGGING')
|
||||||
|
|
||||||
|
const handleLoggingCopy = () => local.send('COPIED_DEBUG_LOG')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StylePanelRoot
|
||||||
|
dir="ltr"
|
||||||
|
bp={breakpoints}
|
||||||
|
data-bp-desktop
|
||||||
|
ref={rContainer}
|
||||||
|
variant="code"
|
||||||
|
onWheel={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{isOpen ? (
|
||||||
|
<Panel.Layout onKeyDown={stopPropagation}>
|
||||||
|
<Panel.Header side="left">
|
||||||
|
<IconButton
|
||||||
|
bp={breakpoints}
|
||||||
|
size="small"
|
||||||
|
onClick={toggleDebugPanel}
|
||||||
|
>
|
||||||
|
<Cross2Icon />
|
||||||
|
</IconButton>
|
||||||
|
<span>Debugging</span>
|
||||||
|
<div />
|
||||||
|
</Panel.Header>
|
||||||
|
<Panel.Content>
|
||||||
|
<hr />
|
||||||
|
{local.isIn('stopped') ? (
|
||||||
|
<RowButton bp={breakpoints} onClick={handleLoggingStart}>
|
||||||
|
<span>Start Logger</span>
|
||||||
|
<IconWrapper size="small">
|
||||||
|
<PlayIcon />
|
||||||
|
</IconWrapper>
|
||||||
|
</RowButton>
|
||||||
|
) : (
|
||||||
|
<RowButton bp={breakpoints} onClick={handleLoggingStop}>
|
||||||
|
<span>Stop Logger</span>
|
||||||
|
<IconWrapper size="small">
|
||||||
|
<StopIcon />
|
||||||
|
</IconWrapper>
|
||||||
|
</RowButton>
|
||||||
|
)}
|
||||||
|
{
|
||||||
|
<RowButton
|
||||||
|
bp={breakpoints}
|
||||||
|
onClick={handleLoggingCopy}
|
||||||
|
disabled={!local.can('COPIED_LOG')}
|
||||||
|
>
|
||||||
|
<span>Copy Log</span>
|
||||||
|
<IconWrapper size="small">
|
||||||
|
<ClipboardCopyIcon />
|
||||||
|
</IconWrapper>
|
||||||
|
</RowButton>
|
||||||
|
}
|
||||||
|
<JSONTextAreaWrapper>
|
||||||
|
<JSONTextArea
|
||||||
|
ref={rTextArea}
|
||||||
|
value={local.data.log}
|
||||||
|
onChange={(e) =>
|
||||||
|
local.send('CHANGED_LOG', { value: e.currentTarget.value })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</JSONTextAreaWrapper>
|
||||||
|
<RowButton
|
||||||
|
bp={breakpoints}
|
||||||
|
onClick={handlePlayback}
|
||||||
|
disabled={!local.can('PLAYED_BACK_LOG')}
|
||||||
|
>
|
||||||
|
<span>Play Back Log</span>
|
||||||
|
</RowButton>
|
||||||
|
</Panel.Content>
|
||||||
|
</Panel.Layout>
|
||||||
|
) : (
|
||||||
|
<IconButton bp={breakpoints} size="small" onClick={toggleDebugPanel}>
|
||||||
|
<CrumpledPaperIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</StylePanelRoot>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const StylePanelRoot = styled(Panel.Root, {
|
||||||
|
marginRight: '8px',
|
||||||
|
width: 'fit-content',
|
||||||
|
maxWidth: 'fit-content',
|
||||||
|
overflow: 'hidden',
|
||||||
|
position: 'relative',
|
||||||
|
border: '1px solid $panel',
|
||||||
|
boxShadow: '0px 2px 4px rgba(0,0,0,.2)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
pointerEvents: 'all',
|
||||||
|
padding: 2,
|
||||||
|
|
||||||
|
'& hr': {
|
||||||
|
marginTop: 2,
|
||||||
|
marginBottom: 2,
|
||||||
|
marginLeft: '-2px',
|
||||||
|
border: 'none',
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: '$brushFill',
|
||||||
|
width: 'calc(100% + 4px)',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const JSONTextAreaWrapper = styled('div', {
|
||||||
|
padding: '4px',
|
||||||
|
})
|
||||||
|
|
||||||
|
const JSONTextArea = styled('textarea', {
|
||||||
|
minHeight: '100px',
|
||||||
|
width: '100%',
|
||||||
|
font: '$mono',
|
||||||
|
backgroundColor: '$panel',
|
||||||
|
border: '1px solid $border',
|
||||||
|
borderRadius: '4px',
|
||||||
|
padding: '4px',
|
||||||
|
outline: 'none',
|
||||||
|
})
|
|
@ -7,6 +7,7 @@ import StylePanel from './style-panel/style-panel'
|
||||||
import styled from 'styles'
|
import styled from 'styles'
|
||||||
import PagePanel from './page-panel/page-panel'
|
import PagePanel from './page-panel/page-panel'
|
||||||
import CodePanel from './code-panel/code-panel'
|
import CodePanel from './code-panel/code-panel'
|
||||||
|
import DebugPanel from './debug-panel/debug-panel'
|
||||||
import ControlsPanel from './controls-panel/controls-panel'
|
import ControlsPanel from './controls-panel/controls-panel'
|
||||||
|
|
||||||
export default function Editor({ roomId }: { roomId?: string }): JSX.Element {
|
export default function Editor({ roomId }: { roomId?: string }): JSX.Element {
|
||||||
|
@ -15,6 +16,7 @@ export default function Editor({ roomId }: { roomId?: string }): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
|
<DebugPanel />
|
||||||
<CodePanel />
|
<CodePanel />
|
||||||
<PagePanel />
|
<PagePanel />
|
||||||
<ControlsPanel />
|
<ControlsPanel />
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
IconWrapper,
|
IconWrapper,
|
||||||
ButtonsRow,
|
ButtonsRow,
|
||||||
RowButton,
|
RowButton,
|
||||||
|
breakpoints,
|
||||||
} from 'components/shared'
|
} from 'components/shared'
|
||||||
import ShapesFunctions from './shapes-functions'
|
import ShapesFunctions from './shapes-functions'
|
||||||
import AlignDistribute from './align-distribute'
|
import AlignDistribute from './align-distribute'
|
||||||
|
@ -24,9 +25,12 @@ import {
|
||||||
Cross2Icon,
|
Cross2Icon,
|
||||||
} from '@radix-ui/react-icons'
|
} from '@radix-ui/react-icons'
|
||||||
|
|
||||||
const breakpoints = { '@initial': 'mobile', '@sm': 'small' } as any
|
|
||||||
|
|
||||||
const handleStylePanelOpen = () => state.send('TOGGLED_STYLE_PANEL_OPEN')
|
const handleStylePanelOpen = () => state.send('TOGGLED_STYLE_PANEL_OPEN')
|
||||||
|
const handleCopy = () => state.send('COPIED')
|
||||||
|
const handlePaste = () => state.send('PASTED')
|
||||||
|
const handleCopyToSvg = () => state.send('COPIED_TO_SVG')
|
||||||
|
const handleSave = () => state.send('SAVED')
|
||||||
|
const handleLoad = () => state.send('LOADED_FROM_FILE_STSTEM')
|
||||||
|
|
||||||
export default function StylePanel(): JSX.Element {
|
export default function StylePanel(): JSX.Element {
|
||||||
const rContainer = useRef<HTMLDivElement>(null)
|
const rContainer = useRef<HTMLDivElement>(null)
|
||||||
|
@ -72,14 +76,14 @@ function SelectedShapeContent(): JSX.Element {
|
||||||
<RowButton
|
<RowButton
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
disabled={selectedShapesCount === 0}
|
disabled={selectedShapesCount === 0}
|
||||||
onClick={() => state.send('COPIED')}
|
onClick={handleCopy}
|
||||||
>
|
>
|
||||||
<span>Copy</span>
|
<span>Copy</span>
|
||||||
<IconWrapper size="small">
|
<IconWrapper size="small">
|
||||||
<ClipboardCopyIcon />
|
<ClipboardCopyIcon />
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
<RowButton bp={breakpoints} onClick={() => state.send('PASTED')}>
|
<RowButton bp={breakpoints} onClick={handlePaste}>
|
||||||
<span>Paste</span>
|
<span>Paste</span>
|
||||||
<IconWrapper size="small">
|
<IconWrapper size="small">
|
||||||
<ClipboardIcon />
|
<ClipboardIcon />
|
||||||
|
@ -88,7 +92,7 @@ function SelectedShapeContent(): JSX.Element {
|
||||||
<RowButton
|
<RowButton
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
disabled={selectedShapesCount === 0}
|
disabled={selectedShapesCount === 0}
|
||||||
onClick={() => state.send('COPIED_TO_SVG')}
|
onClick={handleCopyToSvg}
|
||||||
>
|
>
|
||||||
<span>Copy to SVG</span>
|
<span>Copy to SVG</span>
|
||||||
<IconWrapper size="small">
|
<IconWrapper size="small">
|
||||||
|
@ -96,13 +100,10 @@ function SelectedShapeContent(): JSX.Element {
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
<hr />
|
<hr />
|
||||||
<RowButton bp={breakpoints} onClick={() => state.send('SAVED')}>
|
<RowButton bp={breakpoints} onClick={handleSave}>
|
||||||
<span>Save</span>
|
<span>Save</span>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
<RowButton
|
<RowButton bp={breakpoints} onClick={handleLoad}>
|
||||||
bp={breakpoints}
|
|
||||||
onClick={() => state.send('LOADED_FROM_FILE_STSTEM')}
|
|
||||||
>
|
|
||||||
<span>Load</span>
|
<span>Load</span>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -195,7 +195,11 @@ export default function useKeyboardEvents() {
|
||||||
}
|
}
|
||||||
case 'd': {
|
case 'd': {
|
||||||
if (metaKey(e)) {
|
if (metaKey(e)) {
|
||||||
state.send('DUPLICATED', info)
|
if (e.shiftKey) {
|
||||||
|
state.send('TOGGLED_DEBUG_MODE')
|
||||||
|
} else {
|
||||||
|
state.send('DUPLICATED', info)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_DRAW_TOOL', info)
|
state.send('SELECTED_DRAW_TOOL', info)
|
||||||
}
|
}
|
||||||
|
@ -228,6 +232,8 @@ export default function useKeyboardEvents() {
|
||||||
case 'l': {
|
case 'l': {
|
||||||
if (metaKey(e)) {
|
if (metaKey(e)) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
|
state.send('TOGGLED_LOGGER')
|
||||||
|
} else {
|
||||||
state.send('LOADED_FROM_FILE_STSTEM', info)
|
state.send('LOADED_FROM_FILE_STSTEM', info)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,16 +5,19 @@ import coopState from 'state/coop/coop-state'
|
||||||
|
|
||||||
export default function useLoadOnMount(roomId: string = undefined) {
|
export default function useLoadOnMount(roomId: string = undefined) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fonts = (document as any).fonts
|
if ('fonts' in document) {
|
||||||
|
const fonts = (document as any).fonts
|
||||||
|
fonts.load('12px Verveine Regular', 'Fonts are loaded!').then(() => {
|
||||||
|
state.send('MOUNTED')
|
||||||
|
|
||||||
fonts.load('12px Verveine Regular', 'Fonts are loaded!').then(() => {
|
if (roomId !== undefined) {
|
||||||
state.send('MOUNTED')
|
state.send('RT_LOADED_ROOM', { id: roomId })
|
||||||
|
coopState.send('JOINED_ROOM', { id: roomId })
|
||||||
if (roomId !== undefined) {
|
}
|
||||||
state.send('RT_LOADED_ROOM', { id: roomId })
|
})
|
||||||
coopState.send('JOINED_ROOM', { id: roomId })
|
} else {
|
||||||
}
|
setTimeout(() => state.send('MOUNTED'), 1000)
|
||||||
})
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
state.send('UNMOUNTED').send('RT_UNLOADED_ROOM', { id: roomId })
|
state.send('UNMOUNTED').send('RT_UNLOADED_ROOM', { id: roomId })
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
"@sentry/react": "^6.7.2",
|
"@sentry/react": "^6.7.2",
|
||||||
"@sentry/tracing": "^6.7.2",
|
"@sentry/tracing": "^6.7.2",
|
||||||
"@sentry/webpack-plugin": "^1.15.1",
|
"@sentry/webpack-plugin": "^1.15.1",
|
||||||
"@state-designer/react": "^1.7.32",
|
"@state-designer/react": "^1.7.4",
|
||||||
"@stitches/react": "^0.2.2",
|
"@stitches/react": "^0.2.2",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
"browser-fs-access": "^0.17.3",
|
"browser-fs-access": "^0.17.3",
|
||||||
|
|
|
@ -15,10 +15,36 @@ import * as Session from './sessions'
|
||||||
* directly to the state using `forceData`.
|
* directly to the state using `forceData`.
|
||||||
* @param info
|
* @param info
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export function fastTranslate(info: PointerInfo): void {
|
||||||
|
const data = { ...state.data }
|
||||||
|
|
||||||
|
session.update<Session.TranslateSession>(
|
||||||
|
data,
|
||||||
|
tld.screenToWorld(info.point, data),
|
||||||
|
info.shiftKey,
|
||||||
|
info.altKey
|
||||||
|
)
|
||||||
|
|
||||||
|
state.forceData(freeze(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fastTransform(info: PointerInfo): void {
|
||||||
|
const data = { ...state.data }
|
||||||
|
|
||||||
|
session.update<Session.TransformSession | Session.TransformSingleSession>(
|
||||||
|
data,
|
||||||
|
tld.screenToWorld(info.point, data),
|
||||||
|
info.shiftKey
|
||||||
|
)
|
||||||
|
|
||||||
|
state.forceData(freeze(data))
|
||||||
|
}
|
||||||
|
|
||||||
export function fastDrawUpdate(info: PointerInfo): void {
|
export function fastDrawUpdate(info: PointerInfo): void {
|
||||||
const data = { ...state.data }
|
const data = { ...state.data }
|
||||||
|
|
||||||
coopState.send('MOVED_CURSOSR', {
|
coopState.send('MOVED_CURSOR', {
|
||||||
pageId: data.currentPageId,
|
pageId: data.currentPageId,
|
||||||
point: info.point,
|
point: info.point,
|
||||||
})
|
})
|
||||||
|
@ -102,28 +128,3 @@ export function fastBrushSelect(point: number[]): void {
|
||||||
|
|
||||||
state.forceData(freeze(data))
|
state.forceData(freeze(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fastTranslate(info: PointerInfo): void {
|
|
||||||
const data = { ...state.data }
|
|
||||||
|
|
||||||
session.update<Session.TranslateSession>(
|
|
||||||
data,
|
|
||||||
tld.screenToWorld(info.point, data),
|
|
||||||
info.shiftKey,
|
|
||||||
info.altKey
|
|
||||||
)
|
|
||||||
|
|
||||||
state.forceData(freeze(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fastTransform(info: PointerInfo): void {
|
|
||||||
const data = { ...state.data }
|
|
||||||
|
|
||||||
session.update<Session.TransformSession | Session.TransformSingleSession>(
|
|
||||||
data,
|
|
||||||
tld.screenToWorld(info.point, data),
|
|
||||||
info.shiftKey
|
|
||||||
)
|
|
||||||
|
|
||||||
state.forceData(freeze(data))
|
|
||||||
}
|
|
||||||
|
|
|
@ -84,8 +84,8 @@ class Inputs {
|
||||||
|
|
||||||
this.points[e.pointerId] = info
|
this.points[e.pointerId] = info
|
||||||
this.activePointerId = e.pointerId
|
this.activePointerId = e.pointerId
|
||||||
|
|
||||||
this.pointer = info
|
this.pointer = info
|
||||||
|
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,12 +169,17 @@ class Inputs {
|
||||||
return { point: getPoint(e), shiftKey, ctrlKey, metaKey, altKey }
|
return { point: getPoint(e), shiftKey, ctrlKey, metaKey, altKey }
|
||||||
}
|
}
|
||||||
|
|
||||||
canAccept = (pointerId: PointerEvent['pointerId']) => {
|
canAccept = (pointerId: PointerEvent['pointerId']): boolean => {
|
||||||
return (
|
pointerId
|
||||||
this.activePointerId === undefined || this.activePointerId === pointerId
|
return true
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// canAccept = (pointerId: PointerEvent['pointerId']) => {
|
||||||
|
// return (
|
||||||
|
// this.activePointerId === undefined || this.activePointerId === pointerId
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
isDoubleClick() {
|
isDoubleClick() {
|
||||||
if (!this.pointer) return
|
if (!this.pointer) return
|
||||||
|
|
||||||
|
@ -225,6 +230,17 @@ class Inputs {
|
||||||
altKey,
|
altKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.activePointerId = undefined
|
||||||
|
this.pointerUpTime = 0
|
||||||
|
|
||||||
|
this.pointer = undefined
|
||||||
|
this.points = {}
|
||||||
|
|
||||||
|
this.keyboard = undefined
|
||||||
|
this.keys = {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Inputs()
|
export default new Inputs()
|
||||||
|
|
272
state/logger.ts
Normal file
272
state/logger.ts
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
import { Data } from 'types'
|
||||||
|
import clipboard from './clipboard'
|
||||||
|
import state from './state'
|
||||||
|
import { isDraft, current } from 'immer'
|
||||||
|
import { setToArray } from 'utils'
|
||||||
|
import tld from 'utils/tld'
|
||||||
|
import inputs from './inputs'
|
||||||
|
|
||||||
|
interface LogEntry {
|
||||||
|
eventName: string
|
||||||
|
payload: any
|
||||||
|
time: number
|
||||||
|
didCauseUpdate: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
filters = new Set([
|
||||||
|
// 'MOVED_OVER_SHAPE',
|
||||||
|
// 'RESIZED_WINDOW',
|
||||||
|
// 'HOVERED_SHAPE',
|
||||||
|
// 'UNHOVERED_SHAPE',
|
||||||
|
// 'PANNED_CAMERA',
|
||||||
|
'STARTED_LOGGING',
|
||||||
|
'STOPPED_LOGGING',
|
||||||
|
])
|
||||||
|
|
||||||
|
snapshotStart: Data
|
||||||
|
snapshotEnd: Data
|
||||||
|
|
||||||
|
log: LogEntry[] = []
|
||||||
|
|
||||||
|
isSimulating = false
|
||||||
|
|
||||||
|
isRunning = false
|
||||||
|
|
||||||
|
speed = 0
|
||||||
|
|
||||||
|
startTime = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the logger.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.start()
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
start = (data: Data): Logger => {
|
||||||
|
if (this.isRunning) return
|
||||||
|
|
||||||
|
this.isRunning = true
|
||||||
|
|
||||||
|
this.snapshotStart = isDraft(data) ? current(data) : data
|
||||||
|
|
||||||
|
this.log = []
|
||||||
|
|
||||||
|
this.startTime = Date.now()
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
this.snapshotStart.pageStates[data.currentPageId].selectedIds = setToArray(
|
||||||
|
tld.getSelectedIds(data)
|
||||||
|
)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the logger.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.stop()
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
stop = (data: Data): Logger => {
|
||||||
|
if (!this.isRunning) return
|
||||||
|
|
||||||
|
this.isRunning = false
|
||||||
|
|
||||||
|
this.snapshotEnd = isDraft(data) ? current(data) : data
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
this.snapshotEnd.pageStates[data.currentPageId].selectedIds = setToArray(
|
||||||
|
tld.getSelectedIds(data)
|
||||||
|
)
|
||||||
|
|
||||||
|
// if (window.confirm('Stopped logging. Copy to clipboard?')) {
|
||||||
|
// this.copyToJson()
|
||||||
|
// }
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an event and payload to the log.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.addToLog(eventName, payload)
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
addToLog(event: string, payload: any, didCauseUpdate = false) {
|
||||||
|
if (!this.isRunning) return
|
||||||
|
|
||||||
|
if (this.filters.has(event)) return
|
||||||
|
|
||||||
|
didCauseUpdate
|
||||||
|
// if (!didCauseUpdate) return
|
||||||
|
|
||||||
|
this.log.push({
|
||||||
|
eventName: event,
|
||||||
|
payload: payload,
|
||||||
|
time: Date.now() - this.startTime,
|
||||||
|
didCauseUpdate: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play back a log entry.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.playback(log)
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
playback = (data: Data, log: string): Logger => {
|
||||||
|
const parsed: { start: Data; end: Data; events: LogEntry[] } =
|
||||||
|
JSON.parse(log)
|
||||||
|
|
||||||
|
const { start, events } = parsed
|
||||||
|
|
||||||
|
this.isSimulating = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
data.pageStates[data.currentPageId].selectedIds = new Set(
|
||||||
|
start.pageStates[start.currentPageId].selectedIds
|
||||||
|
)
|
||||||
|
|
||||||
|
state.send('RESET_DOCUMENT_STATE').forceData(start)
|
||||||
|
|
||||||
|
const pointerDowns = [
|
||||||
|
'POINTED_CANVAS',
|
||||||
|
'POINTED_SHAPE',
|
||||||
|
'POINTED_BOUNDS',
|
||||||
|
'DOUBLE_POINTED_SHAPE',
|
||||||
|
'POINTED_HANDLE',
|
||||||
|
'RIGHT_POINTED',
|
||||||
|
]
|
||||||
|
|
||||||
|
const pointerChanges = [
|
||||||
|
...pointerDowns,
|
||||||
|
'MOVED_POINTER',
|
||||||
|
'MOVED_OVER_SHAPE',
|
||||||
|
'STOPPED_POINTING',
|
||||||
|
'DOUBLE_POINTED_CANVAS',
|
||||||
|
]
|
||||||
|
|
||||||
|
const pointerUps = ['STOPPED_POINTING']
|
||||||
|
|
||||||
|
for (const event of events) {
|
||||||
|
if (pointerDowns.includes(event.eventName)) {
|
||||||
|
inputs.pointer.origin = event.payload.point
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointerChanges.includes(event.eventName)) {
|
||||||
|
inputs.activePointerId = event.payload.pointerId
|
||||||
|
inputs.pointer = { ...inputs.pointer, ...event.payload }
|
||||||
|
inputs.points[event.payload.pointerId] = inputs.pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointerUps.includes(event.eventName)) {
|
||||||
|
delete inputs.points[event.payload.pointerId]
|
||||||
|
delete inputs.activePointerId
|
||||||
|
|
||||||
|
// TODO: Double pointing
|
||||||
|
}
|
||||||
|
|
||||||
|
state.send(event.eventName, event.payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(
|
||||||
|
() => (this.isSimulating = false),
|
||||||
|
events[events.length - 1].time + 1
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Could not play back that state.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export the log as JSON.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.toJson()
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
copyToJson = () => {
|
||||||
|
const logAsString = JSON.stringify({
|
||||||
|
start: this.snapshotStart,
|
||||||
|
end: this.snapshotEnd,
|
||||||
|
events: this.log,
|
||||||
|
})
|
||||||
|
|
||||||
|
clipboard.copyStringToClipboard(logAsString)
|
||||||
|
|
||||||
|
return logAsString
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new event filter. Filtered events will not be logged.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.addFilter("SOME_EVENT")
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
addFilter(eventName: string) {
|
||||||
|
this.filters.add(eventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an event from the filters. Filtered events will not be logged.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.removeFilter("SOME_EVENT")
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
removeFilter(eventName: string) {
|
||||||
|
this.filters.delete(eventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace all of the filtered events.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.setFilters(["SOME_EVENT", "SOME_OTHER_EVENT"])
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
setFilters(eventNames: string[]) {
|
||||||
|
this.filters = new Set(eventNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the current set of event filters.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
*
|
||||||
|
*```ts
|
||||||
|
* logger.clear()
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
clearFilters() {
|
||||||
|
this.filters.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Logger()
|
|
@ -37,6 +37,7 @@ import {
|
||||||
ColorStyle,
|
ColorStyle,
|
||||||
} from 'types'
|
} from 'types'
|
||||||
import { getFontSize } from './shape-styles'
|
import { getFontSize } from './shape-styles'
|
||||||
|
import logger from './logger'
|
||||||
|
|
||||||
const initialData: Data = {
|
const initialData: Data = {
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -44,6 +45,8 @@ const initialData: Data = {
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
isDarkMode: false,
|
isDarkMode: false,
|
||||||
isCodeOpen: false,
|
isCodeOpen: false,
|
||||||
|
isDebugMode: false,
|
||||||
|
isDebugOpen: false,
|
||||||
isStyleOpen: false,
|
isStyleOpen: false,
|
||||||
isToolLocked: false,
|
isToolLocked: false,
|
||||||
isPenLocked: false,
|
isPenLocked: false,
|
||||||
|
@ -141,12 +144,22 @@ for (let i = 0; i < count; i++) {
|
||||||
|
|
||||||
const state = createState({
|
const state = createState({
|
||||||
data: initialData,
|
data: initialData,
|
||||||
|
on: {
|
||||||
|
TOGGLED_DEBUG_PANEL: 'toggleDebugPanel',
|
||||||
|
TOGGLED_DEBUG_MODE: 'toggleDebugMode',
|
||||||
|
TOGGLED_LOGGER: 'toggleLogger',
|
||||||
|
COPIED_DEBUG_LOG: 'copyDebugLog',
|
||||||
|
LOADED_FROM_SNAPSHOT: {
|
||||||
|
unless: 'isInSession',
|
||||||
|
do: ['loadDocumentFromJson', 'resetHistory'],
|
||||||
|
},
|
||||||
|
},
|
||||||
initial: 'loading',
|
initial: 'loading',
|
||||||
states: {
|
states: {
|
||||||
loading: {
|
loading: {
|
||||||
on: {
|
on: {
|
||||||
MOUNTED: {
|
MOUNTED: {
|
||||||
do: 'restoredPreviousDocument',
|
do: ['resetHistory', 'restoredPreviousDocument'],
|
||||||
to: 'ready',
|
to: 'ready',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -160,13 +173,18 @@ const state = createState({
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
UNMOUNTED: {
|
UNMOUNTED: {
|
||||||
do: ['saveAppState', 'saveDocumentState', 'resetDocumentState'],
|
do: [
|
||||||
|
'saveAppState',
|
||||||
|
'saveDocumentState',
|
||||||
|
'resetDocumentState',
|
||||||
|
'resetHistory',
|
||||||
|
],
|
||||||
to: 'loading',
|
to: 'loading',
|
||||||
},
|
},
|
||||||
// Network-Related
|
// Network-Related
|
||||||
RT_LOADED_ROOM: [
|
RT_LOADED_ROOM: [
|
||||||
'clearRoom',
|
'clearRoom',
|
||||||
{ if: 'hasRoom', do: 'resetDocumentState' },
|
{ if: 'hasRoom', do: ['resetDocumentState', 'resetHistory'] },
|
||||||
],
|
],
|
||||||
// RT_UNLOADED_ROOM: ['clearRoom', 'resetDocumentState'],
|
// RT_UNLOADED_ROOM: ['clearRoom', 'resetDocumentState'],
|
||||||
// RT_DISCONNECTED_ROOM: ['clearRoom', 'resetDocumentState'],
|
// RT_DISCONNECTED_ROOM: ['clearRoom', 'resetDocumentState'],
|
||||||
|
@ -176,7 +194,11 @@ const state = createState({
|
||||||
// RT_EDITED_SHAPE: 'editRtShape',
|
// RT_EDITED_SHAPE: 'editRtShape',
|
||||||
// Client
|
// Client
|
||||||
RESIZED_WINDOW: 'resetPageState',
|
RESIZED_WINDOW: 'resetPageState',
|
||||||
RESET_DOCUMENT_STATE: 'resetDocumentState',
|
RESET_DOCUMENT_STATE: [
|
||||||
|
'resetHistory',
|
||||||
|
'resetDocumentState',
|
||||||
|
{ to: 'selecting' },
|
||||||
|
],
|
||||||
TOGGLED_READ_ONLY: 'toggleReadOnly',
|
TOGGLED_READ_ONLY: 'toggleReadOnly',
|
||||||
LOADED_FONTS: 'resetShapes',
|
LOADED_FONTS: 'resetShapes',
|
||||||
USED_PEN_DEVICE: 'enablePenLock',
|
USED_PEN_DEVICE: 'enablePenLock',
|
||||||
|
@ -729,6 +751,9 @@ const state = createState({
|
||||||
do: 'createShape',
|
do: 'createShape',
|
||||||
to: 'draw.editing',
|
to: 'draw.editing',
|
||||||
},
|
},
|
||||||
|
STOPPED_POINTING: {
|
||||||
|
to: 'draw.creating',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
editing: {
|
editing: {
|
||||||
|
@ -745,8 +770,11 @@ const state = createState({
|
||||||
},
|
},
|
||||||
PRESSED_SHIFT: 'keyUpdateDrawSession',
|
PRESSED_SHIFT: 'keyUpdateDrawSession',
|
||||||
RELEASED_SHIFT: 'keyUpdateDrawSession',
|
RELEASED_SHIFT: 'keyUpdateDrawSession',
|
||||||
// MOVED_POINTER: 'updateDrawSession',
|
|
||||||
PANNED_CAMERA: 'updateDrawSession',
|
PANNED_CAMERA: 'updateDrawSession',
|
||||||
|
MOVED_POINTER: {
|
||||||
|
if: 'isSimulating',
|
||||||
|
do: 'updateDrawSession',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1041,7 +1069,7 @@ const state = createState({
|
||||||
to: 'selecting',
|
to: 'selecting',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initial: 'drawingShapeBounds',
|
initial: 'bounds',
|
||||||
states: {
|
states: {
|
||||||
bounds: {
|
bounds: {
|
||||||
onEnter: 'startDrawTransformSession',
|
onEnter: 'startDrawTransformSession',
|
||||||
|
@ -1096,6 +1124,9 @@ const state = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
conditions: {
|
conditions: {
|
||||||
|
isSimulating() {
|
||||||
|
return logger.isSimulating
|
||||||
|
},
|
||||||
hasRoom(_, payload: { id?: string }) {
|
hasRoom(_, payload: { id?: string }) {
|
||||||
return payload.id !== undefined
|
return payload.id !== undefined
|
||||||
},
|
},
|
||||||
|
@ -1203,6 +1234,30 @@ const state = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
/* ---------------------- Debug --------------------- */
|
||||||
|
|
||||||
|
closeDebugPanel(data) {
|
||||||
|
data.settings.isDebugOpen = false
|
||||||
|
},
|
||||||
|
openDebugPanel(data) {
|
||||||
|
data.settings.isDebugOpen = true
|
||||||
|
},
|
||||||
|
toggleDebugMode(data) {
|
||||||
|
data.settings.isDebugMode = !data.settings.isDebugMode
|
||||||
|
},
|
||||||
|
toggleDebugPanel(data) {
|
||||||
|
data.settings.isDebugOpen = !data.settings.isDebugOpen
|
||||||
|
},
|
||||||
|
toggleLogger(data) {
|
||||||
|
if (logger.isRunning) {
|
||||||
|
logger.stop(data)
|
||||||
|
} else {
|
||||||
|
logger.start(data)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
copyDebugLog() {
|
||||||
|
logger.copyToJson()
|
||||||
|
},
|
||||||
// Networked Room
|
// Networked Room
|
||||||
addRtShape(data, payload: { pageId: string; shape: Shape }) {
|
addRtShape(data, payload: { pageId: string; shape: Shape }) {
|
||||||
const { pageId, shape } = payload
|
const { pageId, shape } = payload
|
||||||
|
@ -1227,6 +1282,8 @@ const state = createState({
|
||||||
|
|
||||||
session.cancel(data)
|
session.cancel(data)
|
||||||
|
|
||||||
|
inputs.reset()
|
||||||
|
|
||||||
const newId = 'page1'
|
const newId = 'page1'
|
||||||
|
|
||||||
data.currentPageId = newId
|
data.currentPageId = newId
|
||||||
|
@ -1315,6 +1372,7 @@ const state = createState({
|
||||||
|
|
||||||
tld.setSelectedIds(data, [shape.id])
|
tld.setSelectedIds(data, [shape.id])
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------- Sessions -------------------- */
|
/* -------------------- Sessions -------------------- */
|
||||||
|
|
||||||
// Shared
|
// Shared
|
||||||
|
@ -2091,6 +2149,11 @@ const state = createState({
|
||||||
return commonStyle
|
return commonStyle
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
options: {
|
||||||
|
onSend(eventName, payload, didCauseUpdate) {
|
||||||
|
logger.addToLog(eventName, payload, didCauseUpdate)
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default state
|
export default state
|
||||||
|
|
2
types.ts
2
types.ts
|
@ -8,6 +8,8 @@ export interface Data {
|
||||||
fontSize: number
|
fontSize: number
|
||||||
isDarkMode: boolean
|
isDarkMode: boolean
|
||||||
isCodeOpen: boolean
|
isCodeOpen: boolean
|
||||||
|
isDebugOpen: boolean
|
||||||
|
isDebugMode: boolean
|
||||||
isStyleOpen: boolean
|
isStyleOpen: boolean
|
||||||
nudgeDistanceSmall: number
|
nudgeDistanceSmall: number
|
||||||
nudgeDistanceLarge: number
|
nudgeDistanceLarge: number
|
||||||
|
|
Loading…
Reference in a new issue