import { LazyUndoRedoAction, UndoRedoAction } from "@/stores/undoRedoStore"; import type { BaseWorkflowComment, WorkflowComment, WorkflowCommentColor, WorkflowCommentStore, WorkflowCommentType, } from "@/stores/workflowEditorCommentStore"; function getCommentName(comment: { color: WorkflowCommentColor; type: WorkflowCommentType }) { if (comment.color !== "none") { return `${comment.color} ${comment.type} comment`; } else { return `${comment.type} comment`; } } class CommentAction extends UndoRedoAction { protected store: WorkflowCommentStore; protected comment: WorkflowComment; constructor(store: WorkflowCommentStore, comment: BaseWorkflowComment) { super(); this.store = store; this.comment = structuredClone(comment) as WorkflowComment; } protected get commentName() { return getCommentName(this.comment); } } export class AddCommentAction extends CommentAction { get name() { return `add ${this.commentName}`; } undo() { this.store.deleteComment(this.comment.id); } redo() { this.store.addComments([this.comment]); } } export class DeleteCommentAction extends CommentAction { get name() { return `delete ${this.commentName}`; } run() { this.store.deleteComment(this.comment.id); } undo() { this.store.addComments([this.comment]); } } export class ChangeColorAction extends UndoRedoAction { private commentId: number; private toColor: WorkflowCommentColor; private fromColor: WorkflowCommentColor; private store: WorkflowCommentStore; protected type; constructor(store: WorkflowCommentStore, comment: WorkflowComment, color: WorkflowCommentColor) { super(); this.store = store; this.commentId = comment.id; this.fromColor = comment.color; this.toColor = color; this.type = comment.type; } get name() { return `change ${this.type} comment color to ${this.toColor}`; } run() { this.store.changeColor(this.commentId, this.toColor); } undo() { this.store.changeColor(this.commentId, this.fromColor); } } class LazyMutateCommentAction extends LazyUndoRedoAction { protected commentId: number; protected startData: WorkflowComment[K]; protected endData: WorkflowComment[K]; protected type; protected color: WorkflowCommentColor; protected applyDataCallback: (commentId: number, data: WorkflowComment[K]) => void; constructor( comment: WorkflowComment, key: K, data: WorkflowComment[K], applyDataCallback: (commentId: number, data: WorkflowComment[K]) => void, ) { super(); this.commentId = comment.id; this.startData = structuredClone(comment[key]); this.endData = structuredClone(data); this.applyDataCallback = applyDataCallback; this.type = comment.type; this.color = comment.color; } queued() { this.applyDataCallback(this.commentId, this.endData); } protected get commentName() { return getCommentName({ type: this.type, color: this.color }); } get name() { return `change ${this.commentName}`; } updateData(data: WorkflowComment[K]) { this.endData = data; this.applyDataCallback(this.commentId, this.endData); } redo() { this.applyDataCallback(this.commentId, this.endData); } undo() { this.applyDataCallback(this.commentId, this.startData); } } export class LazyChangeDataAction extends LazyMutateCommentAction<"data"> { constructor(store: WorkflowCommentStore, comment: WorkflowComment, data: WorkflowComment["data"]) { const callback = store.changeData; super(comment, "data", data, callback); } get name() { type TitleData = { title: string }; type TextData = { text: string }; type SizeData = { size: number }; type FormatData = { bold?: true; italic?: true }; if ((this.startData as TitleData).title !== (this.endData as TitleData).title) { return `edit title of ${this.commentName}`; } if ((this.startData as TextData).text !== (this.endData as TextData).text) { return `edit text of ${this.commentName}`; } if ((this.startData as SizeData).size !== (this.endData as SizeData).size) { return `change text size of ${this.commentName}`; } if ((this.startData as FormatData).bold !== (this.endData as FormatData).bold) { return `toggle bold of ${this.commentName}`; } if ((this.startData as FormatData).italic !== (this.endData as FormatData).italic) { return `toggle italic of ${this.commentName}`; } return super.name; } } export class LazyChangePositionAction extends LazyMutateCommentAction<"position"> { constructor(store: WorkflowCommentStore, comment: WorkflowComment, position: [number, number]) { const callback = store.changePosition; super(comment, "position", position, callback); } get name() { return `move ${this.commentName}`; } } export class LazyChangeSizeAction extends LazyMutateCommentAction<"size"> { constructor(store: WorkflowCommentStore, comment: WorkflowComment, size: [number, number]) { const callback = store.changeSize; super(comment, "size", size, callback); } get name() { return `resize ${this.commentName}`; } } export class ToggleCommentSelectedAction extends UndoRedoAction { store; commentId; type; toggleTo: boolean; constructor(store: WorkflowCommentStore, comment: WorkflowComment) { super(); this.store = store; this.commentId = comment.id; this.type = comment.type; this.toggleTo = !store.getCommentMultiSelected(this.commentId); } get name() { if (this.toggleTo === true) { return `add ${this.type} comment to selection`; } else { return `remove ${this.type} comment from selection`; } } run() { this.store.setCommentMultiSelected(this.commentId, this.toggleTo); } undo() { this.store.setCommentMultiSelected(this.commentId, !this.toggleTo); } } export class RemoveAllFreehandCommentsAction extends UndoRedoAction { store; comments; constructor(store: WorkflowCommentStore) { super(); this.store = store; const freehandComments = store.comments.filter((comment) => comment.type === "freehand"); this.comments = structuredClone(freehandComments); } get name() { return "remove all freehand comments"; } run() { this.store.deleteFreehandComments(); } undo() { this.store.addComments(structuredClone(this.comments)); } }