diff --git a/cypress/e2e/diagramUpdate.spec.ts b/cypress/e2e/diagramUpdate.spec.ts index d2ca433c..b8326bc3 100644 --- a/cypress/e2e/diagramUpdate.spec.ts +++ b/cypress/e2e/diagramUpdate.spec.ts @@ -50,6 +50,24 @@ describe('Auto sync tests', () => { cy.getLocalStorage('codeStore').snapshot(); }); + it('should automatically defer rendering when complex diagrams are edited', () => { + cy.get('#view').should('not.have.class', 'outOfSync'); + typeInEditor(` +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i +A & B & C & D & E --> F & G & K & Z & i`); + cy.get('#view').should('have.class', 'outOfSync'); + cy.get('#errorContainer').should('contain.text', 'It will be updated automatically.'); + // The class should be removed automatically after 1 second. + cy.get('#view').should('not.have.class', 'outOfSync'); + }); + it('supports commenting code out/in', () => { cy.get('#editor').contains('Car').click(); cy.get('#editor').get('textarea').type(`${cmd}/`, { force: true }); diff --git a/src/lib/components/Editor.svelte b/src/lib/components/Editor.svelte index 77652eca..9118a3a7 100644 --- a/src/lib/components/Editor.svelte +++ b/src/lib/components/Editor.svelte @@ -88,7 +88,7 @@ } // eslint-disable-next-line @typescript-eslint/no-unsafe-call initEditor(monaco); - errorDebug(100); + errorDebug(); editor = monaco.editor.create(divElement, editorOptions); editor.onDidChangeModelContent(({ isFlush }) => { const newText = editor?.getValue(); diff --git a/src/lib/components/View.svelte b/src/lib/components/View.svelte index 4fc22983..55fa898e 100644 --- a/src/lib/components/View.svelte +++ b/src/lib/components/View.svelte @@ -3,7 +3,7 @@ import { onMount } from 'svelte'; import panzoom from 'svg-pan-zoom'; import type { State, ValidatedState } from '$lib/types'; - import { logEvent } from '$lib/util/stats'; + import { logEvent, saveStatistics } from '$lib/util/stats'; import { cmdKey } from '$lib/util/util'; import { render as renderDiagram } from '$lib/util/mermaid'; import type { MermaidConfig } from 'mermaid'; @@ -123,6 +123,8 @@ error = true; } const timeTaken = Date.now() - startTime; + console.log({ timeTaken }); + saveStatistics(code, timeTaken); recordRenderTime(timeTaken, () => { $inputStateStore.updateDiagram = true; }); diff --git a/src/lib/util/autoSync.ts b/src/lib/util/autoSync.ts index 336f4a0b..0927ddb3 100644 --- a/src/lib/util/autoSync.ts +++ b/src/lib/util/autoSync.ts @@ -5,7 +5,7 @@ import { stateStore } from './state'; let shouldSync = true; let updater: () => void; const renderDelay = 1000; -const slowRenderThreshold = 250; +const slowRenderThreshold = 150; const debouncedRender = debounce(() => { shouldSync = true; diff --git a/src/lib/util/state.ts b/src/lib/util/state.ts index 77e03755..3c719e06 100644 --- a/src/lib/util/state.ts +++ b/src/lib/util/state.ts @@ -5,7 +5,6 @@ import { derived, get, writable, type Readable } from 'svelte/store'; import { parse } from './mermaid'; import { localStorage, persist } from './persist'; import { deserializeState, serializeState } from './serde'; -import { saveStatistics } from './stats'; import { errorDebug, formatJSON } from './util'; export const defaultState: State = { @@ -141,7 +140,6 @@ export const updateCode = ( resetPanZoom = false }: { updateDiagram?: boolean; resetPanZoom?: boolean } = {} ): void => { - saveStatistics(code); errorDebug(); inputStateStore.update((state) => { diff --git a/src/lib/util/stats.ts b/src/lib/util/stats.ts index 82d1c5fc..04183c90 100644 --- a/src/lib/util/stats.ts +++ b/src/lib/util/stats.ts @@ -47,33 +47,45 @@ export const countLines = (code: string): number => { return (code.match(/\n/g)?.length ?? 0) + 1; }; -export const saveStatistics = (graph: string): void => { +export const saveStatistics = (graph: string, renderTime: number): void => { const graphType = detectType(graph); if (!graphType) { return; } const length = countLines(graph); - const lengthBucket = - length < 10 - ? '0-10' - : length < 25 - ? '10-25' - : length < 50 - ? '25-50' - : length < 100 - ? '50-100' - : length < 200 - ? '100-200' - : length < 500 - ? '200-500' - : length < 700 - ? '500-700' - : length < 1000 - ? '700-1000' - : length < 1500 - ? '1000-1500' - : '1500+'; - logEvent('render', { graphType, length, lengthBucket }); + const lengthBucket = getBucket(length); + const renderTimeMsBucket = getBucket(renderTime); + logEvent('render', { graphType, length, lengthBucket, renderTimeMsBucket }); +}; + +const getBucket = (length: number): string => { + return length < 10 + ? '0-10' + : length < 25 + ? '10-25' + : length < 50 + ? '25-50' + : length < 100 + ? '50-100' + : length < 200 + ? '100-200' + : length < 500 + ? '200-500' + : length < 700 + ? '500-700' + : length < 1000 + ? '700-1000' + : length < 1500 + ? '1000-1500' + : length < 2500 + ? '1500-2500' + : length < 4500 + ? '2500-4500' + : length < 7000 + ? '4500-7000' + : length < 10_000 + ? '7000-10000' + : '10000+'; }; const minutesToMilliSeconds = (minutes: number): number => { diff --git a/src/lib/util/util.ts b/src/lib/util/util.ts index d082a703..65769ff5 100644 --- a/src/lib/util/util.ts +++ b/src/lib/util/util.ts @@ -28,7 +28,7 @@ export const isMac = navigator.platform.toUpperCase().includes('MAC'); export const cmdKey = isMac ? 'Cmd' : 'Ctrl'; let count = 0; -export const errorDebug = (limit = 100) => { +export const errorDebug = (limit = 1000) => { count += 1; if (count > limit) { console.log(count, limit);