refactor: replace text-specific update command with generic

This commit is contained in:
Maze Winther
2026-02-08 18:01:45 +01:00
parent a218a52d2d
commit dc0b57cd6a
4 changed files with 24 additions and 55 deletions
@@ -59,7 +59,7 @@ export function TextProperties({
const fontSize = Number.isNaN(parsed) const fontSize = Number.isNaN(parsed)
? element.fontSize ? element.fontSize
: clamp({ value: parsed, min: MIN_FONT_SIZE, max: MAX_FONT_SIZE }); : clamp({ value: parsed, min: MIN_FONT_SIZE, max: MAX_FONT_SIZE });
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { fontSize }, updates: { fontSize },
@@ -73,7 +73,7 @@ export function TextProperties({
? element.fontSize ? element.fontSize
: clamp({ value: parsed, min: MIN_FONT_SIZE, max: MAX_FONT_SIZE }); : clamp({ value: parsed, min: MIN_FONT_SIZE, max: MAX_FONT_SIZE });
setFontSizeInput(fontSize.toString()); setFontSizeInput(fontSize.toString());
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { fontSize }, updates: { fontSize },
@@ -88,7 +88,7 @@ export function TextProperties({
const opacityPercent = Number.isNaN(parsed) const opacityPercent = Number.isNaN(parsed)
? Math.round(element.opacity * 100) ? Math.round(element.opacity * 100)
: clamp({ value: parsed, min: 0, max: 100 }); : clamp({ value: parsed, min: 0, max: 100 });
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { opacity: opacityPercent / 100 }, updates: { opacity: opacityPercent / 100 },
@@ -102,7 +102,7 @@ export function TextProperties({
? Math.round(element.opacity * 100) ? Math.round(element.opacity * 100)
: clamp({ value: parsed, min: 0, max: 100 }); : clamp({ value: parsed, min: 0, max: 100 });
setOpacityInput(opacityPercent.toString()); setOpacityInput(opacityPercent.toString());
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { opacity: opacityPercent / 100 }, updates: { opacity: opacityPercent / 100 },
@@ -113,7 +113,7 @@ export function TextProperties({
if (color !== "transparent") { if (color !== "transparent") {
lastSelectedColor.current = color; lastSelectedColor.current = color;
} }
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { backgroundColor: color }, updates: { backgroundColor: color },
@@ -126,7 +126,7 @@ export function TextProperties({
isTransparent: boolean; isTransparent: boolean;
}) => { }) => {
const newColor = isTransparent ? "transparent" : lastSelectedColor.current; const newColor = isTransparent ? "transparent" : lastSelectedColor.current;
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { backgroundColor: newColor }, updates: { backgroundColor: newColor },
@@ -154,7 +154,7 @@ export function TextProperties({
defaultValue={element.content} defaultValue={element.content}
className="bg-panel-accent min-h-20" className="bg-panel-accent min-h-20"
onChange={(e) => onChange={(e) =>
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { content: e.target.value }, updates: { content: e.target.value },
@@ -167,7 +167,7 @@ export function TextProperties({
<FontPicker <FontPicker
defaultValue={element.fontFamily} defaultValue={element.fontFamily}
onValueChange={(value: FontFamily) => onValueChange={(value: FontFamily) =>
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { fontFamily: value }, updates: { fontFamily: value },
@@ -186,7 +186,7 @@ export function TextProperties({
} }
size="sm" size="sm"
onClick={() => onClick={() =>
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { updates: {
@@ -205,7 +205,7 @@ export function TextProperties({
} }
size="sm" size="sm"
onClick={() => onClick={() =>
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { updates: {
@@ -228,7 +228,7 @@ export function TextProperties({
} }
size="sm" size="sm"
onClick={() => onClick={() =>
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { updates: {
@@ -251,7 +251,7 @@ export function TextProperties({
} }
size="sm" size="sm"
onClick={() => onClick={() =>
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { updates: {
@@ -279,7 +279,7 @@ export function TextProperties({
max={MAX_FONT_SIZE} max={MAX_FONT_SIZE}
step={1} step={1}
onValueChange={([value]) => { onValueChange={([value]) => {
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { fontSize: value }, updates: { fontSize: value },
@@ -310,7 +310,7 @@ export function TextProperties({
string: (element.color || "FFFFFF").replace("#", ""), string: (element.color || "FFFFFF").replace("#", ""),
})} })}
onChange={(color) => { onChange={(color) => {
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { color: `#${color}` }, updates: { color: `#${color}` },
@@ -330,7 +330,7 @@ export function TextProperties({
max={100} max={100}
step={1} step={1}
onValueChange={([value]) => { onValueChange={([value]) => {
editor.timeline.updateTextElement({ editor.timeline.updateElement({
trackId, trackId,
elementId: element.id, elementId: element.id,
updates: { opacity: value / 100 }, updates: { opacity: value / 100 },
+4 -20
View File
@@ -2,7 +2,6 @@ import type { EditorCore } from "@/core";
import type { import type {
TrackType, TrackType,
TimelineTrack, TimelineTrack,
TextElement,
TimelineElement, TimelineElement,
ClipboardItem, ClipboardItem,
} from "@/types/timeline"; } from "@/types/timeline";
@@ -19,7 +18,7 @@ import {
DuplicateElementsCommand, DuplicateElementsCommand,
ToggleElementsVisibilityCommand, ToggleElementsVisibilityCommand,
ToggleElementsMutedCommand, ToggleElementsMutedCommand,
UpdateTextElementCommand, UpdateElementCommand,
SplitElementsCommand, SplitElementsCommand,
PasteCommand, PasteCommand,
UpdateElementStartTimeCommand, UpdateElementStartTimeCommand,
@@ -199,31 +198,16 @@ export class TimelineManager {
this.editor.command.execute({ command }); this.editor.command.execute({ command });
} }
updateTextElement({ updateElement({
trackId, trackId,
elementId, elementId,
updates, updates,
}: { }: {
trackId: string; trackId: string;
elementId: string; elementId: string;
updates: Partial< updates: Partial<Record<string, unknown>>;
Pick<
TextElement,
| "content"
| "fontSize"
| "fontFamily"
| "color"
| "backgroundColor"
| "textAlign"
| "fontWeight"
| "fontStyle"
| "textDecoration"
| "transform"
| "opacity"
>
>;
}): void { }): void {
const command = new UpdateTextElementCommand(trackId, elementId, updates); const command = new UpdateElementCommand(trackId, elementId, updates);
this.editor.command.execute({ command }); this.editor.command.execute({ command });
} }
@@ -5,7 +5,7 @@ export { UpdateElementTrimCommand } from "./update-element-trim";
export { UpdateElementDurationCommand } from "./update-element-duration"; export { UpdateElementDurationCommand } from "./update-element-duration";
export { UpdateElementStartTimeCommand } from "./update-element-start-time"; export { UpdateElementStartTimeCommand } from "./update-element-start-time";
export { SplitElementsCommand } from "./split-elements"; export { SplitElementsCommand } from "./split-elements";
export { UpdateTextElementCommand } from "./update-text-element"; export { UpdateElementCommand } from "./update-element";
export { ToggleElementsVisibilityCommand } from "./toggle-elements-visibility"; export { ToggleElementsVisibilityCommand } from "./toggle-elements-visibility";
export { ToggleElementsMutedCommand } from "./toggle-elements-muted"; export { ToggleElementsMutedCommand } from "./toggle-elements-muted";
export { MoveElementCommand } from "./move-elements"; export { MoveElementCommand } from "./move-elements";
@@ -1,27 +1,14 @@
import { Command } from "@/lib/commands/base-command"; import { Command } from "@/lib/commands/base-command";
import type { TextElement, TimelineTrack } from "@/types/timeline"; import type { TimelineTrack } from "@/types/timeline";
import { EditorCore } from "@/core"; import { EditorCore } from "@/core";
export class UpdateTextElementCommand extends Command { export class UpdateElementCommand extends Command {
private savedState: TimelineTrack[] | null = null; private savedState: TimelineTrack[] | null = null;
constructor( constructor(
private trackId: string, private trackId: string,
private elementId: string, private elementId: string,
private updates: Partial< private updates: Partial<Record<string, unknown>>,
Pick<
TextElement,
| "content"
| "fontSize"
| "fontFamily"
| "color"
| "backgroundColor"
| "textAlign"
| "fontWeight"
| "fontStyle"
| "textDecoration"
>
>,
) { ) {
super(); super();
} }
@@ -33,9 +20,7 @@ export class UpdateTextElementCommand extends Command {
const updatedTracks = this.savedState.map((t) => { const updatedTracks = this.savedState.map((t) => {
if (t.id !== this.trackId) return t; if (t.id !== this.trackId) return t;
const newElements = t.elements.map((el) => const newElements = t.elements.map((el) =>
el.id === this.elementId && el.type === "text" el.id === this.elementId ? { ...el, ...this.updates } : el,
? { ...el, ...this.updates }
: el,
); );
return { ...t, elements: newElements } as typeof t; return { ...t, elements: newElements } as typeof t;
}); });