From 2d8a6e3c8411b9ece40f12e64722c3f46e565391 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Thu, 26 Oct 2023 08:18:23 +1100 Subject: [PATCH] Various changes --- adapter-warthog-wasm/src/core/templates.ts | 26 ++-- .../src/core/templates.ts | 26 ++-- client/main.js | 1 + client/src/components/Editor.tsx | 3 + client/src/components/app-bar/Input.tsx | 116 ++++-------------- client/src/components/app-bar/Playback.tsx | 74 ++++++----- client/src/components/app-bar/upload.tsx | 84 ++++++------- client/src/components/generic/Property.tsx | 9 +- .../components/inspector/EventInspector.tsx | 34 +++-- .../inspector/FullscreenProgress.tsx | 33 +++++ .../src/components/inspector/Placeholder.tsx | 4 +- .../src/components/inspector/PropertyList.tsx | 21 ++-- .../components/inspector/SelectionMenu.tsx | 11 +- .../components/inspector/TraceRenderer.tsx | 14 ++- client/src/components/inspector/index.tsx | 2 + .../components/layer-editor/LayerEditor.tsx | 14 ++- .../layer-editor/layers/LayerSource.tsx | 11 +- .../layer-editor/layers/mapLayerSource.tsx | 49 +------- .../layer-editor/layers/queryLayerSource.tsx | 103 +++++++++++++++- .../layer-editor/layers/traceLayerSource.tsx | 83 +++++++------ .../components/renderer/parser/normalize.ts | 6 +- .../renderer/parser/parseProperty.ts | 2 +- .../components/renderer/parser/parseString.ts | 35 +++--- .../components/renderer/parser/parseToken.ts | 26 ++-- .../components/renderer/parser/parseTrace.ts | 19 +-- .../renderer/parser/parseTrace.worker.ts | 17 +-- client/src/components/title-bar/TitleBar.tsx | 2 +- client/src/hooks/useParsedMap.tsx | 5 +- client/src/hooks/usePlaybackState.tsx | 4 +- client/src/hooks/useWorkspace.tsx | 20 +-- client/src/index.css | 7 +- client/src/index.tsx | 2 + client/src/produce.ts | 12 +- client/src/public-dev/coi.js | 102 +++++++++++++++ client/src/public-dev/favicon.png | Bin 0 -> 403337 bytes client/src/public-dev/manifest.json | 22 ++++ client/src/public-dev/robots.txt | 3 + .../src/public/previews/snip_grid_astar.png | Bin 8179 -> 0 bytes client/src/public/previews/snip_tile_tree.png | Bin 27137 -> 0 bytes client/src/services/ConnectionsService.tsx | 1 + client/src/slices/UIState.ts | 16 ++- client/src/slices/busy.ts | 38 ++++++ client/src/slices/layers.ts | 4 +- client/src/theme.tsx | 15 ++- client/src/workers/async.ts | 8 +- client/src/workers/index.ts | 6 + client/src/workers/parseYaml.worker.ts | 3 + client/vite.config.ts | 12 +- .../src/d2-renderer/D2Renderer.ts | 23 ++-- .../src/d2-renderer/D2RendererOptions.ts | 4 +- 50 files changed, 715 insertions(+), 417 deletions(-) create mode 100644 client/src/components/inspector/FullscreenProgress.tsx create mode 100644 client/src/public-dev/coi.js create mode 100644 client/src/public-dev/favicon.png create mode 100644 client/src/public-dev/manifest.json create mode 100644 client/src/public-dev/robots.txt delete mode 100644 client/src/public/previews/snip_grid_astar.png delete mode 100644 client/src/public/previews/snip_tile_tree.png create mode 100644 client/src/slices/busy.ts create mode 100644 client/src/workers/parseYaml.worker.ts diff --git a/adapter-warthog-wasm/src/core/templates.ts b/adapter-warthog-wasm/src/core/templates.ts index 939250ad..60ddf189 100644 --- a/adapter-warthog-wasm/src/core/templates.ts +++ b/adapter-warthog-wasm/src/core/templates.ts @@ -10,9 +10,9 @@ export const gridTemplate: Partial = { $: "rect", width: 1, height: 1, - x: "{{ctx.x}}", - y: "{{ctx.y}}", - fill: "{{ctx.color[ctx.type]}}", + x: "{{$.event.x}}", + y: "{{$.event.y}}", + fill: "{{$.color[$.event.type]}}", }, ], }, @@ -26,7 +26,7 @@ export const gridTemplate: Partial = { }, }, path: { - pivot: { x: "{{ctx.x + 0.5}}", y: "{{ctx.y + 0.5}}" }, + pivot: { x: "{{$.event.x + 0.5}}", y: "{{$.event.y + 0.5}}" }, scale: 0.3, }, }, @@ -39,10 +39,10 @@ export const xyTemplate: Partial = { node: [ { $: "circle", - fill: "{{ctx.color[ctx.type]}}", + fill: "{{$.color[$.event.type]}}", radius: 120, - x: "{{ctx.x}}", - y: "{{ctx.y}}", + x: "{{$.event.x}}", + y: "{{$.event.y}}", }, ], line: [ @@ -50,15 +50,15 @@ export const xyTemplate: Partial = { $: "path", points: [ { - x: "{{ctx.parent ? ctx.parent.x: ctx.x}}", - y: "{{ctx.parent ? ctx.parent.y: ctx.y}}", + x: "{{$.parent ? $.parent.x: $.event.x}}", + y: "{{$.parent ? $.parent.y: $.event.y}}", }, { - x: "{{ctx.x}}", - y: "{{ctx.y}}", + x: "{{$.event.x}}", + y: "{{$.event.y}}", }, ], - fill: "{{ctx.color[ctx.type]}}", + fill: "{{$.color[$.event.type]}}", lineWidth: 90, }, ], @@ -78,7 +78,7 @@ export const xyTemplate: Partial = { }, }, path: { - pivot: { x: "{{ctx.x}}", y: "{{ctx.y}}" }, + pivot: { x: "{{$.event.x}}", y: "{{$.event.y}}" }, scale: 120, }, }, diff --git a/adapter-warthog-websocket/src/core/templates.ts b/adapter-warthog-websocket/src/core/templates.ts index 939250ad..60ddf189 100644 --- a/adapter-warthog-websocket/src/core/templates.ts +++ b/adapter-warthog-websocket/src/core/templates.ts @@ -10,9 +10,9 @@ export const gridTemplate: Partial = { $: "rect", width: 1, height: 1, - x: "{{ctx.x}}", - y: "{{ctx.y}}", - fill: "{{ctx.color[ctx.type]}}", + x: "{{$.event.x}}", + y: "{{$.event.y}}", + fill: "{{$.color[$.event.type]}}", }, ], }, @@ -26,7 +26,7 @@ export const gridTemplate: Partial = { }, }, path: { - pivot: { x: "{{ctx.x + 0.5}}", y: "{{ctx.y + 0.5}}" }, + pivot: { x: "{{$.event.x + 0.5}}", y: "{{$.event.y + 0.5}}" }, scale: 0.3, }, }, @@ -39,10 +39,10 @@ export const xyTemplate: Partial = { node: [ { $: "circle", - fill: "{{ctx.color[ctx.type]}}", + fill: "{{$.color[$.event.type]}}", radius: 120, - x: "{{ctx.x}}", - y: "{{ctx.y}}", + x: "{{$.event.x}}", + y: "{{$.event.y}}", }, ], line: [ @@ -50,15 +50,15 @@ export const xyTemplate: Partial = { $: "path", points: [ { - x: "{{ctx.parent ? ctx.parent.x: ctx.x}}", - y: "{{ctx.parent ? ctx.parent.y: ctx.y}}", + x: "{{$.parent ? $.parent.x: $.event.x}}", + y: "{{$.parent ? $.parent.y: $.event.y}}", }, { - x: "{{ctx.x}}", - y: "{{ctx.y}}", + x: "{{$.event.x}}", + y: "{{$.event.y}}", }, ], - fill: "{{ctx.color[ctx.type]}}", + fill: "{{$.color[$.event.type]}}", lineWidth: 90, }, ], @@ -78,7 +78,7 @@ export const xyTemplate: Partial = { }, }, path: { - pivot: { x: "{{ctx.x}}", y: "{{ctx.y}}" }, + pivot: { x: "{{$.event.x}}", y: "{{$.event.y}}" }, scale: 120, }, }, diff --git a/client/main.js b/client/main.js index 0e28247b..1ace9a83 100644 --- a/client/main.js +++ b/client/main.js @@ -56,6 +56,7 @@ server.listen(0, () => { show: false, titleBarStyle: "hidden", titleBarOverlay: { + height: 32, color: "#00000000", symbolColor: "#00000000", }, diff --git a/client/src/components/Editor.tsx b/client/src/components/Editor.tsx index d4748a7c..f60f42f8 100644 --- a/client/src/components/Editor.tsx +++ b/client/src/components/Editor.tsx @@ -1,3 +1,5 @@ +import { ReactNode } from "react"; + export type EditorProps = { value?: T; onChange?: (key: T) => void; @@ -5,4 +7,5 @@ export type EditorProps = { export type EditorSetterProps = { value?: T; onChange?: (key: (value: T) => T) => void; + children?: ReactNode; }; diff --git a/client/src/components/app-bar/Input.tsx b/client/src/components/app-bar/Input.tsx index ecac9e28..40c1be96 100644 --- a/client/src/components/app-bar/Input.tsx +++ b/client/src/components/app-bar/Input.tsx @@ -9,12 +9,14 @@ import { EditorProps } from "../Editor"; import { FeaturePicker } from "./FeaturePicker"; import { FeaturePickerButton } from "./FeaturePickerButton"; import { custom as customMap, uploadMap, uploadTrace } from "./upload"; +import { LARGE_FILE_B, formatByte, useBusyState } from "slices/busy"; export const mapDefaults = { start: undefined, end: undefined }; export function MapPicker({ onChange, value }: EditorProps) { const notify = useSnackbar(); - const usingLoadingState = useLoadingState("specimen"); + const usingLoadingState = useLoadingState("map"); + const usingBusyState = useBusyState("map"); const [connections] = useConnections(); const [{ maps, formats }] = useFeatures(); return ( @@ -37,8 +39,17 @@ export function MapPicker({ onChange, value }: EditorProps) { const f = await uploadMap(formats); if (f) { usingLoadingState(async () => { - notify("Reading map..."); - onChange?.(await f()); + notify("Opening map..."); + const output = + f.file.size > LARGE_FILE_B + ? await usingBusyState( + f.read, + `Opening map (${formatByte(f.file.size)})` + ) + : await f.read(); + if (output) { + onChange?.(output); + } }); } } catch (e) { @@ -57,6 +68,7 @@ export function MapPicker({ onChange, value }: EditorProps) { export function TracePicker({ onChange, value }: EditorProps) { const notify = useSnackbar(); const usingLoadingState = useLoadingState("specimen"); + const usingBusyState = useBusyState("specimen"); return ( } @@ -65,10 +77,16 @@ export function TracePicker({ onChange, value }: EditorProps) { const f = await uploadTrace(); if (f) usingLoadingState(async () => { - notify("Reading trace..."); - const g = await f(); - if (g) { - onChange?.(g); + notify("Opening trace..."); + const output = + f.file.size > LARGE_FILE_B + ? await usingBusyState( + f.read, + `Opening trace (${formatByte(f.file.size)})` + ) + : await f.read(); + if (output) { + onChange?.(output); } }); } catch (e) { @@ -80,87 +98,3 @@ export function TracePicker({ onChange, value }: EditorProps) { ); } - -// export function Input() { -// const notify = useSnackbar(); -// const [connections] = useConnections(); -// const [{ algorithms, maps, formats }] = useFeatures(); -// const [{ algorithm, map, parameters }, setUIState] = useUIState(); - -// return ( -// <> -// } -// label="Map" -// value={map?.id} -// items={[ -// customTrace(parameters), -// customMap(map), -// ...maps.map((c) => ({ -// ...c, -// description: find(connections, { url: c.source })?.name, -// })), -// ]} -// onChange={async (v) => { -// switch (v) { -// case customMap().id: -// try { -// const f = await uploadMap(formats); -// if (f) { -// setUIState({ -// ...mapDefaults, -// map: f, -// algorithm: algorithm ?? "identity", -// parameters: {}, -// }); -// notify("Solution was cleared because the map changed."); -// } -// } catch (e) { -// notify(`${e}`); -// } -// break; -// case customTrace().id: -// try { -// const f2 = await uploadTrace(); -// if (f2) { -// setUIState({ -// parameters: f2, -// algorithm: "identity", -// start: 0, -// end: 0, -// map: { -// format: f2.format, -// content: map?.format === f2.format ? map?.content : " ", -// id: "internal/upload", -// }, -// }); -// } -// } catch (e) { -// notify(`${e}`); -// } -// break; -// default: -// setUIState({ -// ...mapDefaults, -// map: find(maps, { id: v }), -// parameters: {}, -// }); -// notify("Solution was cleared because the map changed."); -// break; -// } -// }} -// /> -// -// } -// label="Algorithm" -// value={algorithm} -// items={algorithms.map((c) => ({ -// ...c, -// description: find(connections, { url: c.source })?.name, -// }))} -// onChange={async (v) => setUIState({ algorithm: v, parameters: {} })} -// /> -// -// ); -// } diff --git a/client/src/components/app-bar/Playback.tsx b/client/src/components/app-bar/Playback.tsx index 05f36719..2b996bf6 100644 --- a/client/src/components/app-bar/Playback.tsx +++ b/client/src/components/app-bar/Playback.tsx @@ -1,13 +1,3 @@ -import { range, trimEnd } from "lodash"; -import { useRaf } from "react-use"; -import { ReactNode, useCallback, useEffect } from "react"; -import { IconButtonWithTooltip as Button } from "components/generic/IconButtonWithTooltip"; -import { Label } from "components/generic/Label"; -import { useSnackbar } from "components/generic/Snackbar"; -import { useBreakpoints } from "hooks/useBreakpoints"; -import { usePlaybackState } from "hooks/usePlaybackState"; -import { useSettings } from "slices/settings"; -import { UploadedTrace } from "slices/UIState"; import { SkipNextOutlined as ForwardIcon, PauseOutlined as PauseIcon, @@ -15,7 +5,18 @@ import { SkipPreviousOutlined as PreviousIcon, StopOutlined as StopIcon, } from "@mui/icons-material"; +import { EditorSetterProps } from "components/Editor"; +import { IconButtonWithTooltip as Button } from "components/generic/IconButtonWithTooltip"; +import { Label } from "components/generic/Label"; +import { useSnackbar } from "components/generic/Snackbar"; +import { useBreakpoints } from "hooks/useBreakpoints"; +import { usePlaybackState } from "hooks/usePlaybackState"; +import { range, trimEnd } from "lodash"; +import { ReactNode, useCallback, useEffect } from "react"; +import { useRaf } from "react-use"; +import { UploadedTrace } from "slices/UIState"; import { Layer } from "slices/layers"; +import { useSettings } from "slices/settings"; function cancellable(f: () => Promise, g: (result: T) => void) { let cancelled = false; @@ -27,28 +28,17 @@ function cancellable(f: () => Promise, g: (result: T) => void) { cancelled = true; }; } +export type PlaybackLayerData = { + step?: number; + playback?: "playing" | "paused"; + playbackTo?: number; +}; -export function Playback({ - layer, -}: { - layer?: Layer<{ trace?: UploadedTrace }>; -}) { - const { - step, - tick, - end, - playing, - canPause, - canPlay, - canStepBackward, - canStepForward, - canStop, - pause, - play, - stepBackward, - stepForward, - stop, - } = usePlaybackState(layer?.key); +export function PlaybackService({ + children, + value, +}: EditorSetterProps>) { + const { step, tick, end, playing, pause } = usePlaybackState(value?.key); useRaf(); const notify = useSnackbar(); @@ -98,6 +88,28 @@ export function Playback({ shouldBreak, playbackRate, ]); + return <>{children}; +} + +export function Playback({ + layer, +}: { + layer?: Layer<{ trace?: UploadedTrace }>; +}) { + const { + playing, + canPause, + canPlay, + canStepBackward, + canStepForward, + canStop, + pause, + play, + stepBackward, + stepForward, + stop, + } = usePlaybackState(layer?.key); + useRaf(); return ( <>