| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  | import type { RevisionPojo, RevisionItem } from "@triliumnext/commons"; | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  | import appContext from "../../components/app_context"; | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | import FNote from "../../entities/fnote"; | 
					
						
							| 
									
										
										
										
											2025-08-10 12:22:11 +03:00
										 |  |  | import dialog from "../../services/dialog"; | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | import froca from "../../services/froca"; | 
					
						
							|  |  |  | import { t } from "../../services/i18n"; | 
					
						
							|  |  |  | import server from "../../services/server"; | 
					
						
							|  |  |  | import toast from "../../services/toast"; | 
					
						
							|  |  |  | import Button from "../react/Button"; | 
					
						
							|  |  |  | import Modal from "../react/Modal"; | 
					
						
							|  |  |  | import ReactBasicWidget from "../react/ReactBasicWidget"; | 
					
						
							|  |  |  | import FormList, { FormListItem } from "../react/FormList"; | 
					
						
							|  |  |  | import utils from "../../services/utils"; | 
					
						
							| 
									
										
										
										
											2025-08-10 12:22:11 +03:00
										 |  |  | import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks"; | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | import protected_session_holder from "../../services/protected_session_holder"; | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  | import { renderMathInElement } from "../../services/math"; | 
					
						
							| 
									
										
										
										
											2025-08-10 15:21:49 +03:00
										 |  |  | import type { CSSProperties } from "preact/compat"; | 
					
						
							| 
									
										
										
										
											2025-08-06 17:01:32 +03:00
										 |  |  | import open from "../../services/open"; | 
					
						
							| 
									
										
										
										
											2025-08-06 18:01:26 +03:00
										 |  |  | import ActionButton from "../react/ActionButton"; | 
					
						
							|  |  |  | import options from "../../services/options"; | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  | import useTriliumEvent from "../react/hooks"; | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  | function RevisionsDialogComponent() { | 
					
						
							|  |  |  |     const [ note, setNote ] = useState<FNote>(); | 
					
						
							|  |  |  |     const [ revisions, setRevisions ] = useState<RevisionItem[]>(); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |     const [ currentRevision, setCurrentRevision ] = useState<RevisionItem>(); | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |     const [ shown, setShown ] = useState(false); | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  |     const [ refreshCounter, setRefreshCounter ] = useState(0); | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     useTriliumEvent("showRevisions", async ({ noteId }) => { | 
					
						
							|  |  |  |         const note = await getNote(noteId); | 
					
						
							|  |  |  |         if (note) { | 
					
						
							|  |  |  |             setNote(note); | 
					
						
							|  |  |  |             setShown(true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |     useEffect(() => { | 
					
						
							|  |  |  |         if (note?.noteId) { | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |             server.get<RevisionItem[]>(`notes/${note.noteId}/revisions`).then(setRevisions); | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             setRevisions(undefined); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  |     }, [ note?.noteId, refreshCounter ]); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (revisions?.length && !currentRevision) { | 
					
						
							|  |  |  |         setCurrentRevision(revisions[0]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |         <Modal | 
					
						
							|  |  |  |             className="revisions-dialog" | 
					
						
							|  |  |  |             size="xl" | 
					
						
							|  |  |  |             title={t("revisions.note_revisions")} | 
					
						
							|  |  |  |             helpPageId="vZWERwf8U3nx" | 
					
						
							|  |  |  |             bodyStyle={{ display: "flex", height: "80vh" }} | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |             header={ | 
					
						
							|  |  |  |                 (!!revisions?.length && <Button text={t("revisions.delete_all_revisions")} small style={{ padding: "0 10px" }} | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                     onClick={async () => { | 
					
						
							|  |  |  |                         const text = t("revisions.confirm_delete_all"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |                         if (note && await dialog.confirm(text)) { | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                             await server.remove(`notes/${note.noteId}/revisions`); | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  |                             setRevisions([]); | 
					
						
							|  |  |  |                             setCurrentRevision(undefined); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                             toast.showMessage(t("revisions.revisions_deleted")); | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |                     }}/>) | 
					
						
							| 
									
										
										
										
											2025-08-06 18:01:26 +03:00
										 |  |  |             } | 
					
						
							|  |  |  |             footer={<RevisionFooter note={note} />}  | 
					
						
							|  |  |  |             footerStyle={{ paddingTop: 0, paddingBottom: 0 }} | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |             onHidden={() => { | 
					
						
							|  |  |  |                 setShown(false); | 
					
						
							|  |  |  |                 setNote(undefined); | 
					
						
							|  |  |  |             }} | 
					
						
							|  |  |  |             show={shown} | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |             > | 
					
						
							|  |  |  |                 <RevisionsList | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |                     revisions={revisions ?? []} | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                     onSelect={(revisionId) => { | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |                         const correspondingRevision = (revisions ?? []).find((r) => r.revisionId === revisionId); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                         if (correspondingRevision) { | 
					
						
							|  |  |  |                             setCurrentRevision(correspondingRevision); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     }} | 
					
						
							| 
									
										
										
										
											2025-08-10 17:53:45 +03:00
										 |  |  |                     currentRevision={currentRevision} | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                 /> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |                 <div className="revision-content-wrapper" style={{ | 
					
						
							|  |  |  |                     flexGrow: "1", | 
					
						
							|  |  |  |                     marginLeft: "20px", | 
					
						
							|  |  |  |                     display: "flex", | 
					
						
							|  |  |  |                     flexDirection: "column", | 
					
						
							|  |  |  |                     minWidth: 0                     | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                 }}> | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  |                     <RevisionPreview  | 
					
						
							|  |  |  |                         revisionItem={currentRevision}  | 
					
						
							|  |  |  |                         setShown={setShown} | 
					
						
							|  |  |  |                         onRevisionDeleted={() => { | 
					
						
							|  |  |  |                             setRefreshCounter(c => c + 1); | 
					
						
							|  |  |  |                             setCurrentRevision(undefined); | 
					
						
							|  |  |  |                         }} /> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                 </div> | 
					
						
							|  |  |  |         </Modal> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 17:53:45 +03:00
										 |  |  | function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: RevisionItem[], onSelect: (val: string) => void, currentRevision?: RevisionItem }) { | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2025-08-10 20:24:20 +03:00
										 |  |  |         <FormList onSelect={onSelect} fullHeight> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |             {revisions.map((item) =>  | 
					
						
							|  |  |  |                 <FormListItem | 
					
						
							|  |  |  |                     title={t("revisions.revision_last_edited", { date: item.dateLastEdited })} | 
					
						
							|  |  |  |                     value={item.revisionId} | 
					
						
							| 
									
										
										
										
											2025-08-10 17:53:45 +03:00
										 |  |  |                     active={currentRevision && item.revisionId === currentRevision.revisionId} | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                 > | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |                     {item.dateLastEdited && item.dateLastEdited.substr(0, 16)} ({item.contentLength && utils.formatSize(item.contentLength)}) | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                 </FormListItem> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |         </FormList>); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  | function RevisionPreview({ revisionItem, setShown, onRevisionDeleted }: {  | 
					
						
							|  |  |  |     revisionItem?: RevisionItem,  | 
					
						
							|  |  |  |     setShown: Dispatch<StateUpdater<boolean>>, | 
					
						
							|  |  |  |     onRevisionDeleted?: () => void | 
					
						
							|  |  |  | }) { | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |     const [ fullRevision, setFullRevision ] = useState<RevisionPojo>(); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     useEffect(() => { | 
					
						
							|  |  |  |         if (revisionItem) { | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |             server.get<RevisionPojo>(`revisions/${revisionItem.revisionId}`).then(setFullRevision); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2025-08-06 17:01:32 +03:00
										 |  |  |             setFullRevision(undefined);             | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  |     }, [revisionItem]); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |         <> | 
					
						
							|  |  |  |             <div style="flex-grow: 0; display: flex; justify-content: space-between;"> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |                 <h3 className="revision-title" style="margin: 3px; flex-grow: 100;">{revisionItem?.title ?? t("revisions.no_revisions")}</h3> | 
					
						
							|  |  |  |                 {(revisionItem && <div className="revision-title-buttons"> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                     {(!revisionItem.isProtected || protected_session_holder.isProtectedSessionAvailable()) && | 
					
						
							| 
									
										
										
										
											2025-08-06 17:01:32 +03:00
										 |  |  |                         <> | 
					
						
							|  |  |  |                             <Button | 
					
						
							|  |  |  |                                 icon="bx bx-history" | 
					
						
							|  |  |  |                                 text={t("revisions.restore_button")} | 
					
						
							|  |  |  |                                 onClick={async () => { | 
					
						
							|  |  |  |                                     if (await dialog.confirm(t("revisions.confirm_restore"))) { | 
					
						
							|  |  |  |                                         await server.post(`revisions/${revisionItem.revisionId}/restore`); | 
					
						
							| 
									
										
										
										
											2025-08-10 12:22:11 +03:00
										 |  |  |                                         setShown(false); | 
					
						
							| 
									
										
										
										
											2025-08-06 17:01:32 +03:00
										 |  |  |                                         toast.showMessage(t("revisions.revision_restored")); | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 }}/> | 
					
						
							|  |  |  |                               | 
					
						
							|  |  |  |                             <Button | 
					
						
							|  |  |  |                                 icon="bx bx-trash" | 
					
						
							|  |  |  |                                 text={t("revisions.delete_button")} | 
					
						
							|  |  |  |                                 onClick={async () => { | 
					
						
							|  |  |  |                                     if (await dialog.confirm(t("revisions.confirm_delete"))) { | 
					
						
							|  |  |  |                                         await server.remove(`revisions/${revisionItem.revisionId}`); | 
					
						
							|  |  |  |                                         toast.showMessage(t("revisions.revision_deleted")); | 
					
						
							| 
									
										
										
										
											2025-08-10 17:48:17 +03:00
										 |  |  |                                         onRevisionDeleted?.(); | 
					
						
							| 
									
										
										
										
											2025-08-06 17:01:32 +03:00
										 |  |  |                                     } | 
					
						
							|  |  |  |                                 }} /> | 
					
						
							|  |  |  |                               | 
					
						
							|  |  |  |                             <Button | 
					
						
							|  |  |  |                                 primary | 
					
						
							|  |  |  |                                 icon="bx bx-download" | 
					
						
							|  |  |  |                                 text={t("revisions.download_button")} | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |                                 onClick={() => { | 
					
						
							|  |  |  |                                     if (revisionItem.revisionId) { | 
					
						
							|  |  |  |                                         open.downloadRevision(revisionItem.noteId, revisionItem.revisionId)} | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 }/> | 
					
						
							| 
									
										
										
										
											2025-08-06 17:01:32 +03:00
										 |  |  |                         </> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |                 </div>)} | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |             <div className="revision-content use-tn-links" style={{ overflow: "auto", wordBreak: "break-word" }}> | 
					
						
							|  |  |  |                 <RevisionContent revisionItem={revisionItem} fullRevision={fullRevision} /> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |             </div> | 
					
						
							|  |  |  |         </> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  | const IMAGE_STYLE: CSSProperties = { | 
					
						
							|  |  |  |     maxWidth: "100%", | 
					
						
							|  |  |  |     maxHeight: "90%", | 
					
						
							|  |  |  |     objectFit: "contain" | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const CODE_STYLE: CSSProperties = { | 
					
						
							|  |  |  |     maxWidth: "100%", | 
					
						
							|  |  |  |     wordBreak: "break-all", | 
					
						
							|  |  |  |     whiteSpace: "pre-wrap" | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  | function RevisionContent({ revisionItem, fullRevision }: { revisionItem?: RevisionItem, fullRevision?: RevisionPojo }) { | 
					
						
							|  |  |  |     const content = fullRevision?.content; | 
					
						
							|  |  |  |     if (!revisionItem || !content) { | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |         return <></>; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |     switch (revisionItem.type) { | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |         case "text": { | 
					
						
							| 
									
										
										
										
											2025-08-06 18:38:52 +03:00
										 |  |  |             const contentRef = useRef<HTMLDivElement>(null); | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |             useEffect(() => { | 
					
						
							|  |  |  |                 if (contentRef.current?.querySelector("span.math-tex")) { | 
					
						
							|  |  |  |                     renderMathInElement(contentRef.current, { trust: true }); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |             return <div ref={contentRef} className="ck-content" dangerouslySetInnerHTML={{ __html: content as string }}></div> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |         } | 
					
						
							|  |  |  |         case "code": | 
					
						
							|  |  |  |             return <pre style={CODE_STYLE}>{content}</pre>; | 
					
						
							|  |  |  |         case "image":             | 
					
						
							|  |  |  |             switch (revisionItem.mime) { | 
					
						
							|  |  |  |                 case "image/svg+xml": { | 
					
						
							|  |  |  |                     //Base64 of other format images may be embedded in svg
 | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |                     const encodedSVG = encodeURIComponent(content as string);  | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |                     return <img | 
					
						
							|  |  |  |                         src={`data:${fullRevision.mime};utf8,${encodedSVG}`} | 
					
						
							|  |  |  |                         style={IMAGE_STYLE} />; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 default: { | 
					
						
							|  |  |  |                     // the reason why we put this inline as base64 is that we do not want to let user copy this
 | 
					
						
							|  |  |  |                     // as a URL to be used in a note. Instead, if they copy and paste it into a note, it will be uploaded as a new note
 | 
					
						
							|  |  |  |                     return <img | 
					
						
							|  |  |  |                         src={`data:${fullRevision.mime};base64,${fullRevision.content}`} | 
					
						
							|  |  |  |                         style={IMAGE_STYLE} /> | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         case "file": | 
					
						
							|  |  |  |             return <table cellPadding="10"> | 
					
						
							|  |  |  |                 <tr> | 
					
						
							|  |  |  |                     <th>{t("revisions.mime")}</th> | 
					
						
							|  |  |  |                     <td>{revisionItem.mime}</td> | 
					
						
							|  |  |  |                 </tr> | 
					
						
							|  |  |  |                 <tr> | 
					
						
							|  |  |  |                     <th>{t("revisions.file_size")}</th> | 
					
						
							| 
									
										
										
										
											2025-08-06 18:10:02 +03:00
										 |  |  |                     <td>{revisionItem.contentLength && utils.formatSize(revisionItem.contentLength)}</td> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:43:26 +03:00
										 |  |  |                 </tr> | 
					
						
							|  |  |  |                 {fullRevision.content && | 
					
						
							|  |  |  |                     <tr> | 
					
						
							|  |  |  |                         <td colspan={2}> | 
					
						
							|  |  |  |                             <strong>{t("revisions.preview")}</strong> | 
					
						
							|  |  |  |                             <pre className="file-preview-content" style={CODE_STYLE}>{fullRevision.content}</pre> | 
					
						
							|  |  |  |                         </td> | 
					
						
							|  |  |  |                     </tr> | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             </table>; | 
					
						
							|  |  |  |         case "canvas": | 
					
						
							|  |  |  |         case "mindMap": | 
					
						
							|  |  |  |         case "mermaid": { | 
					
						
							|  |  |  |             const encodedTitle = encodeURIComponent(revisionItem.title); | 
					
						
							|  |  |  |             return <img | 
					
						
							|  |  |  |                 src={`api/revisions/${revisionItem.revisionId}/image/${encodedTitle}?${Math.random()}`} | 
					
						
							|  |  |  |                 style={IMAGE_STYLE} />; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             return <>{t("revisions.preview_not_available")}</> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  | function RevisionFooter({ note }: { note?: FNote }) { | 
					
						
							| 
									
										
										
										
											2025-08-06 18:01:26 +03:00
										 |  |  |     if (!note) { | 
					
						
							|  |  |  |         return <></>; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let revisionsNumberLimit: number | string = parseInt(note?.getLabelValue("versioningLimit") ?? ""); | 
					
						
							|  |  |  |     if (!Number.isInteger(revisionsNumberLimit)) { | 
					
						
							|  |  |  |         revisionsNumberLimit = options.getInt("revisionSnapshotNumberLimit") ?? 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (revisionsNumberLimit === -1) { | 
					
						
							|  |  |  |         revisionsNumberLimit = "∞"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     return <> | 
					
						
							|  |  |  |         <span class="revisions-snapshot-interval flex-grow-1 my-0 py-0"> | 
					
						
							|  |  |  |             {t("revisions.snapshot_interval", { seconds: options.getInt("revisionSnapshotTimeInterval") })} | 
					
						
							|  |  |  |         </span> | 
					
						
							|  |  |  |         <span class="maximum-revisions-for-current-note flex-grow-1 my-0 py-0"> | 
					
						
							|  |  |  |             {t("revisions.maximum_revisions", { number: revisionsNumberLimit })} | 
					
						
							|  |  |  |         </span> | 
					
						
							|  |  |  |         <ActionButton | 
					
						
							|  |  |  |             icon="bx bx-cog" text={t("revisions.settings")} | 
					
						
							|  |  |  |             onClick={() => appContext.tabManager.openContextWithNote("_optionsOther", { activate: true })} | 
					
						
							|  |  |  |         /> | 
					
						
							|  |  |  |     </>; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  | export default class RevisionsDialog extends ReactBasicWidget  { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get component() { | 
					
						
							| 
									
										
										
										
											2025-08-10 00:32:26 +03:00
										 |  |  |         return <RevisionsDialogComponent /> | 
					
						
							| 
									
										
										
										
											2025-08-06 16:16:30 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function getNote(noteId?: string | null) { | 
					
						
							|  |  |  |     if (noteId) { | 
					
						
							|  |  |  |         return await froca.getNote(noteId); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return appContext.tabManager.getActiveContextNote(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |