From 33016bf6bf608d97640dfbce3e5a84f82defe044 Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Wed, 5 Feb 2020 22:47:10 +0400 Subject: [PATCH] Fix issues related to history (#701) * Separate UI from Canvas * Explicitly define history recording * ActionManager: Set syncActionState during construction instead of in every call * Add commit to history flag to necessary actions * Disable undoing during multiElement * Write custom equality function for UI component to render it only when specific props and elements change * Remove stale comments about history skipping * Stop undo/redoing when in resizing element mode * wip * correctly reset resizingElement & add undo check * Separate selection element from the rest of the array and stop redrawing the UI when dragging the selection * Remove selectionElement from local storage * Remove unnecessary readonly type casting in actionFinalize * Fix undo / redo for multi points * Fix an issue that did not update history when elements were locked * Disable committing to history for noops - deleteSelected without deleting anything - Basic selection * Use generateEntry only inside history and pass elements and appstate to history * Update component after every history resume * Remove last item from the history only if in multi mode * Resume recording when element type is not selection * ensure we prevent hotkeys only on writable elements * Remove selection clearing from history * Remove one point arrows as they are invisibly small * Remove shape of elements from local storage * Fix removing invisible element from the array * add missing history resuming cases & simplify slice * fix lint * don't regenerate elements if no elements deselected * regenerate elements array on selection * reset state.selectionElement unconditionally * Use getter instead of passing appState and scene data through functions to actions * fix import Co-authored-by: David Luzar --- src/actions/actionCanvas.tsx | 4 +- src/actions/actionDeleteSelected.tsx | 1 + src/actions/actionFinalize.tsx | 7 +- src/actions/actionProperties.tsx | 8 + src/actions/actionStyles.ts | 1 + src/actions/actionZindex.tsx | 4 + src/actions/manager.tsx | 77 ++-- src/actions/types.ts | 22 +- src/appState.ts | 19 + src/components/ExportDialog.tsx | 21 +- src/element/sizeHelpers.ts | 2 +- src/history.ts | 17 +- src/index.tsx | 646 +++++++++++++-------------- src/renderer/renderScene.ts | 13 + src/scene/data.ts | 7 +- src/scene/export.ts | 1 + src/scene/selection.ts | 12 +- src/types.ts | 1 + 18 files changed, 450 insertions(+), 413 deletions(-) diff --git a/src/actions/actionCanvas.tsx b/src/actions/actionCanvas.tsx index a09c0018..b7382066 100644 --- a/src/actions/actionCanvas.tsx +++ b/src/actions/actionCanvas.tsx @@ -8,7 +8,7 @@ import { t } from "../i18n"; export const actionChangeViewBackgroundColor: Action = { name: "changeViewBackgroundColor", - perform: (elements, appState, value) => { + perform: (_, appState, value) => { return { appState: { ...appState, viewBackgroundColor: value } }; }, PanelComponent: ({ appState, updateData }) => { @@ -23,10 +23,12 @@ export const actionChangeViewBackgroundColor: Action = { ); }, + commitToHistory: () => true, }; export const actionClearCanvas: Action = { name: "clearCanvas", + commitToHistory: () => true, perform: () => { return { elements: [], diff --git a/src/actions/actionDeleteSelected.tsx b/src/actions/actionDeleteSelected.tsx index e3a80917..a2c67dd3 100644 --- a/src/actions/actionDeleteSelected.tsx +++ b/src/actions/actionDeleteSelected.tsx @@ -12,5 +12,6 @@ export const actionDeleteSelected: Action = { }, contextItemLabel: "labels.delete", contextMenuOrder: 3, + commitToHistory: (_, elements) => elements.some(el => el.isSelected), keyTest: event => event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE, }; diff --git a/src/actions/actionFinalize.tsx b/src/actions/actionFinalize.tsx index a9d14fcb..fae31eb2 100644 --- a/src/actions/actionFinalize.tsx +++ b/src/actions/actionFinalize.tsx @@ -1,10 +1,12 @@ import { Action } from "./types"; import { KEYS } from "../keys"; import { clearSelection } from "../scene"; +import { isInvisiblySmallElement } from "../element"; export const actionFinalize: Action = { name: "finalize", perform: (elements, appState) => { + let newElements = clearSelection(elements); if (window.document.activeElement instanceof HTMLElement) { window.document.activeElement.blur(); } @@ -13,10 +15,13 @@ export const actionFinalize: Action = { 0, appState.multiElement.points.length - 1, ); + if (isInvisiblySmallElement(appState.multiElement)) { + newElements = newElements.slice(0, -1); + } appState.multiElement.shape = null; } return { - elements: clearSelection(elements), + elements: newElements, appState: { ...appState, elementType: "selection", diff --git a/src/actions/actionProperties.tsx b/src/actions/actionProperties.tsx index 5b92e90f..4c80906a 100644 --- a/src/actions/actionProperties.tsx +++ b/src/actions/actionProperties.tsx @@ -47,6 +47,7 @@ export const actionChangeStrokeColor: Action = { appState: { ...appState, currentItemStrokeColor: value }, }; }, + commitToHistory: () => true, PanelComponent: ({ elements, appState, updateData }) => ( <> @@ -77,6 +78,7 @@ export const actionChangeBackgroundColor: Action = { appState: { ...appState, currentItemBackgroundColor: value }, }; }, + commitToHistory: () => true, PanelComponent: ({ elements, appState, updateData }) => ( <> @@ -107,6 +109,7 @@ export const actionChangeFillStyle: Action = { appState: { ...appState, currentItemFillStyle: value }, }; }, + commitToHistory: () => true, PanelComponent: ({ elements, appState, updateData }) => (
{t("labels.fill")} @@ -143,6 +146,7 @@ export const actionChangeStrokeWidth: Action = { appState: { ...appState, currentItemStrokeWidth: value }, }; }, + commitToHistory: () => true, PanelComponent: ({ elements, appState, updateData }) => (
{t("labels.strokeWidth")} @@ -177,6 +181,7 @@ export const actionChangeSloppiness: Action = { appState: { ...appState, currentItemRoughness: value }, }; }, + commitToHistory: () => true, PanelComponent: ({ elements, appState, updateData }) => (
{t("labels.sloppiness")} @@ -211,6 +216,7 @@ export const actionChangeOpacity: Action = { appState: { ...appState, currentItemOpacity: value }, }; }, + commitToHistory: () => true, PanelComponent: ({ elements, appState, updateData }) => (