Files
outline/app/models/Revision.ts
T
2025-12-28 08:56:32 -05:00

106 lines
2.9 KiB
TypeScript

import { computed, observable } from "mobx";
import { type ProsemirrorData } from "@shared/types";
import { isRTL } from "@shared/utils/rtl";
import Document from "./Document";
import User from "./User";
import ParanoidModel from "./base/ParanoidModel";
import Field from "./decorators/Field";
import Relation from "./decorators/Relation";
import type RevisionsStore from "~/stores/RevisionsStore";
import { ChangesetHelper } from "@shared/editor/lib/ChangesetHelper";
class Revision extends ParanoidModel {
static modelName = "Revision";
/** The document ID that the revision is related to */
documentId: string;
/** The document that the revision is related to */
@Relation(() => Document, { onDelete: "cascade" })
document: Document;
/** The document title when the revision was created */
@observable
title: string;
/** An optional name for the revision */
@Field
@observable
name: string | null;
/** Prosemirror data of the content when revision was created */
@observable.shallow
data: ProsemirrorData;
/** The icon (or) emoji of the document when the revision was created */
@observable
icon: string | null;
/** The color of the document icon when the revision was created */
@observable
color: string | null;
/** HTML string representing the revision as a diff from the previous version */
@observable
html: string;
/** @deprecated The ID of the user who created the revision */
createdById: string;
/** @deprecated Use collaborators instead*/
@Relation(() => User)
createdBy: User;
/** Array of user IDs who collaborated on this revision */
collaboratorIds: string[];
/** The user IDs who authored this revision */
@Relation(() => User, { multiple: true, onDelete: "ignore" })
collaborators: User[];
/**
* Returns the direction of the revision text, either "rtl" or "ltr"
*/
@computed
get dir(): "rtl" | "ltr" {
return this.rtl ? "rtl" : "ltr";
}
/**
* Returns true if the revision text is right-to-left
*/
@computed
get rtl() {
return isRTL(this.title);
}
/**
* Returns the previous revision (chronologically earlier) for comparison.
*
* Revisions are sorted by creation date (newest first), so the "previous" revision
* is the one that comes after the current revision in the sorted list.
*
* @returns The previous revision or null if this is the first revision.
*/
@computed
get before(): Revision | null {
const allRevisions = (this.store as RevisionsStore).getByDocumentId(
this.documentId
);
const currentIndex = allRevisions.findIndex(
(r: Revision) => r.id === this.id
);
return currentIndex >= 0 && currentIndex < allRevisions.length - 1
? allRevisions[currentIndex + 1]
: null;
}
@computed
get changeset() {
return ChangesetHelper.getChangeset(this.data, this.before?.data);
}
}
export default Revision;