From 479feb991c674cf1e00cac9320f5f0f43b29e746 Mon Sep 17 00:00:00 2001 From: Hiren Kangad Date: Sat, 14 Mar 2026 16:49:34 +0530 Subject: [PATCH] fix: block flip/rotate in SelectionToolbar for sticky, text, markdown, pdf-page The toolbar buttons called ops directly without type filtering. Now filters NON_TRANSFORMABLE types before applying flip/rotate ops. --- frontend/src/pages/Editor.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/Editor.tsx b/frontend/src/pages/Editor.tsx index 3b79cfb..2bcad5c 100644 --- a/frontend/src/pages/Editor.tsx +++ b/frontend/src/pages/Editor.tsx @@ -42,6 +42,9 @@ import { TextSprite } from '../canvas/sprites/TextSprite'; import { StickySprite } from '../canvas/sprites/StickySprite'; import { MarkdownSprite } from '../canvas/sprites/MarkdownSprite'; import * as ops from '../canvas/operations'; + +/** Types that cannot be rotated, flipped, or cropped. */ +const NON_TRANSFORMABLE = new Set(['pdf-page', 'sticky', 'markdown', 'text']); import ReactDOM from 'react-dom'; import MarkdownReadView from '../components/MarkdownReadView'; import PasteChoicePopup from '../components/PasteChoicePopup'; @@ -1205,10 +1208,10 @@ export default function Editor({ isPublicView }: EditorProps) { onRow={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.arrangeRow(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} onColumn={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.arrangeColumn(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} onStack={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.stackObjects(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} - onFlipH={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.flipHorizontal(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} - onFlipV={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.flipVertical(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} - onRotateCW={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.rotate90(s, true); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} - onRotateCCW={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.rotate90(s, false); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} + onFlipH={() => { const s = selectionRef.current?.getSelectedItems()?.filter(i => !NON_TRANSFORMABLE.has(i.type)); if (s?.length) { ops.flipHorizontal(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} + onFlipV={() => { const s = selectionRef.current?.getSelectedItems()?.filter(i => !NON_TRANSFORMABLE.has(i.type)); if (s?.length) { ops.flipVertical(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} + onRotateCW={() => { const s = selectionRef.current?.getSelectedItems()?.filter(i => !NON_TRANSFORMABLE.has(i.type)); if (s?.length) { ops.rotate90(s, true); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} + onRotateCCW={() => { const s = selectionRef.current?.getSelectedItems()?.filter(i => !NON_TRANSFORMABLE.has(i.type)); if (s?.length) { ops.rotate90(s, false); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} onGroup={handleGroup} onNormSize={() => { const s = selectionRef.current?.getSelectedItems(); if (s) { ops.normalizeSize(s); selectionRef.current?.transformBox.update(s); onCanvasChange(s.map(i => i.id)); } }} />