From dc0b57cd6a5517dc6b57c6ebd1d0f6f7c8ee5e40 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Sun, 8 Feb 2026 18:01:45 +0100 Subject: refactor: replace text-specific update command with generic --- .../editor/panels/properties/text-properties.tsx | 30 ++++++------- apps/web/src/core/managers/timeline-manager.ts | 24 ++-------- .../web/src/lib/commands/timeline/element/index.ts | 2 +- .../commands/timeline/element/update-element.ts | 37 +++++++++++++++ .../timeline/element/update-text-element.ts | 52 ---------------------- 5 files changed, 57 insertions(+), 88 deletions(-) create mode 100644 apps/web/src/lib/commands/timeline/element/update-element.ts delete mode 100644 apps/web/src/lib/commands/timeline/element/update-text-element.ts (limited to 'apps') diff --git a/apps/web/src/components/editor/panels/properties/text-properties.tsx b/apps/web/src/components/editor/panels/properties/text-properties.tsx index 8f40910b..43c1eb26 100644 --- a/apps/web/src/components/editor/panels/properties/text-properties.tsx +++ b/apps/web/src/components/editor/panels/properties/text-properties.tsx @@ -59,7 +59,7 @@ export function TextProperties({ const fontSize = Number.isNaN(parsed) ? element.fontSize : clamp({ value: parsed, min: MIN_FONT_SIZE, max: MAX_FONT_SIZE }); - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { fontSize }, @@ -73,7 +73,7 @@ export function TextProperties({ ? element.fontSize : clamp({ value: parsed, min: MIN_FONT_SIZE, max: MAX_FONT_SIZE }); setFontSizeInput(fontSize.toString()); - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { fontSize }, @@ -88,7 +88,7 @@ export function TextProperties({ const opacityPercent = Number.isNaN(parsed) ? Math.round(element.opacity * 100) : clamp({ value: parsed, min: 0, max: 100 }); - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { opacity: opacityPercent / 100 }, @@ -102,7 +102,7 @@ export function TextProperties({ ? Math.round(element.opacity * 100) : clamp({ value: parsed, min: 0, max: 100 }); setOpacityInput(opacityPercent.toString()); - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { opacity: opacityPercent / 100 }, @@ -113,7 +113,7 @@ export function TextProperties({ if (color !== "transparent") { lastSelectedColor.current = color; } - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { backgroundColor: color }, @@ -126,7 +126,7 @@ export function TextProperties({ isTransparent: boolean; }) => { const newColor = isTransparent ? "transparent" : lastSelectedColor.current; - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { backgroundColor: newColor }, @@ -154,7 +154,7 @@ export function TextProperties({ defaultValue={element.content} className="bg-panel-accent min-h-20" onChange={(e) => - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { content: e.target.value }, @@ -167,7 +167,7 @@ export function TextProperties({ - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { fontFamily: value }, @@ -186,7 +186,7 @@ export function TextProperties({ } size="sm" onClick={() => - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { @@ -205,7 +205,7 @@ export function TextProperties({ } size="sm" onClick={() => - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { @@ -228,7 +228,7 @@ export function TextProperties({ } size="sm" onClick={() => - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { @@ -251,7 +251,7 @@ export function TextProperties({ } size="sm" onClick={() => - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { @@ -279,7 +279,7 @@ export function TextProperties({ max={MAX_FONT_SIZE} step={1} onValueChange={([value]) => { - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { fontSize: value }, @@ -310,7 +310,7 @@ export function TextProperties({ string: (element.color || "FFFFFF").replace("#", ""), })} onChange={(color) => { - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { color: `#${color}` }, @@ -330,7 +330,7 @@ export function TextProperties({ max={100} step={1} onValueChange={([value]) => { - editor.timeline.updateTextElement({ + editor.timeline.updateElement({ trackId, elementId: element.id, updates: { opacity: value / 100 }, diff --git a/apps/web/src/core/managers/timeline-manager.ts b/apps/web/src/core/managers/timeline-manager.ts index 867df3a8..22cba52d 100644 --- a/apps/web/src/core/managers/timeline-manager.ts +++ b/apps/web/src/core/managers/timeline-manager.ts @@ -2,7 +2,6 @@ import type { EditorCore } from "@/core"; import type { TrackType, TimelineTrack, - TextElement, TimelineElement, ClipboardItem, } from "@/types/timeline"; @@ -19,7 +18,7 @@ import { DuplicateElementsCommand, ToggleElementsVisibilityCommand, ToggleElementsMutedCommand, - UpdateTextElementCommand, + UpdateElementCommand, SplitElementsCommand, PasteCommand, UpdateElementStartTimeCommand, @@ -199,31 +198,16 @@ export class TimelineManager { this.editor.command.execute({ command }); } - updateTextElement({ + updateElement({ trackId, elementId, updates, }: { trackId: string; elementId: string; - updates: Partial< - Pick< - TextElement, - | "content" - | "fontSize" - | "fontFamily" - | "color" - | "backgroundColor" - | "textAlign" - | "fontWeight" - | "fontStyle" - | "textDecoration" - | "transform" - | "opacity" - > - >; + updates: Partial>; }): void { - const command = new UpdateTextElementCommand(trackId, elementId, updates); + const command = new UpdateElementCommand(trackId, elementId, updates); this.editor.command.execute({ command }); } diff --git a/apps/web/src/lib/commands/timeline/element/index.ts b/apps/web/src/lib/commands/timeline/element/index.ts index 8b719afa..3f10baa4 100644 --- a/apps/web/src/lib/commands/timeline/element/index.ts +++ b/apps/web/src/lib/commands/timeline/element/index.ts @@ -5,7 +5,7 @@ export { UpdateElementTrimCommand } from "./update-element-trim"; export { UpdateElementDurationCommand } from "./update-element-duration"; export { UpdateElementStartTimeCommand } from "./update-element-start-time"; export { SplitElementsCommand } from "./split-elements"; -export { UpdateTextElementCommand } from "./update-text-element"; +export { UpdateElementCommand } from "./update-element"; export { ToggleElementsVisibilityCommand } from "./toggle-elements-visibility"; export { ToggleElementsMutedCommand } from "./toggle-elements-muted"; export { MoveElementCommand } from "./move-elements"; diff --git a/apps/web/src/lib/commands/timeline/element/update-element.ts b/apps/web/src/lib/commands/timeline/element/update-element.ts new file mode 100644 index 00000000..4ee54726 --- /dev/null +++ b/apps/web/src/lib/commands/timeline/element/update-element.ts @@ -0,0 +1,37 @@ +import { Command } from "@/lib/commands/base-command"; +import type { TimelineTrack } from "@/types/timeline"; +import { EditorCore } from "@/core"; + +export class UpdateElementCommand extends Command { + private savedState: TimelineTrack[] | null = null; + + constructor( + private trackId: string, + private elementId: string, + private updates: Partial>, + ) { + super(); + } + + execute(): void { + const editor = EditorCore.getInstance(); + this.savedState = editor.timeline.getTracks(); + + const updatedTracks = this.savedState.map((t) => { + if (t.id !== this.trackId) return t; + const newElements = t.elements.map((el) => + el.id === this.elementId ? { ...el, ...this.updates } : el, + ); + return { ...t, elements: newElements } as typeof t; + }); + + editor.timeline.updateTracks(updatedTracks); + } + + undo(): void { + if (this.savedState) { + const editor = EditorCore.getInstance(); + editor.timeline.updateTracks(this.savedState); + } + } +} diff --git a/apps/web/src/lib/commands/timeline/element/update-text-element.ts b/apps/web/src/lib/commands/timeline/element/update-text-element.ts deleted file mode 100644 index e3cc4a32..00000000 --- a/apps/web/src/lib/commands/timeline/element/update-text-element.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Command } from "@/lib/commands/base-command"; -import type { TextElement, TimelineTrack } from "@/types/timeline"; -import { EditorCore } from "@/core"; - -export class UpdateTextElementCommand extends Command { - private savedState: TimelineTrack[] | null = null; - - constructor( - private trackId: string, - private elementId: string, - private updates: Partial< - Pick< - TextElement, - | "content" - | "fontSize" - | "fontFamily" - | "color" - | "backgroundColor" - | "textAlign" - | "fontWeight" - | "fontStyle" - | "textDecoration" - > - >, - ) { - super(); - } - - execute(): void { - const editor = EditorCore.getInstance(); - this.savedState = editor.timeline.getTracks(); - - const updatedTracks = this.savedState.map((t) => { - if (t.id !== this.trackId) return t; - const newElements = t.elements.map((el) => - el.id === this.elementId && el.type === "text" - ? { ...el, ...this.updates } - : el, - ); - return { ...t, elements: newElements } as typeof t; - }); - - editor.timeline.updateTracks(updatedTracks); - } - - undo(): void { - if (this.savedState) { - const editor = EditorCore.getInstance(); - editor.timeline.updateTracks(this.savedState); - } - } -} -- cgit v1.3.1