| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  | import { t } from "../../services/i18n.js"; | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  | import utils from "../../services/utils.js"; | 
					
						
							|  |  |  | import server from "../../services/server.js"; | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | import toastService from "../../services/toast.js"; | 
					
						
							| 
									
										
										
										
											2022-12-01 13:07:23 +01:00
										 |  |  | import appContext from "../../components/app_context.js"; | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | import libraryLoader from "../../services/library_loader.js"; | 
					
						
							|  |  |  | import openService from "../../services/open.js"; | 
					
						
							|  |  |  | import protectedSessionHolder from "../../services/protected_session_holder.js"; | 
					
						
							|  |  |  | import BasicWidget from "../basic_widget.js"; | 
					
						
							| 
									
										
										
										
											2022-11-25 15:29:57 +01:00
										 |  |  | import dialogService from "../../services/dialog.js"; | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  | import options from "../../services/options.js"; | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  | import type FNote from "../../entities/fnote.js"; | 
					
						
							|  |  |  | import type { NoteType } from "../../entities/fnote.js"; | 
					
						
							| 
									
										
										
										
											2024-09-15 12:41:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | const TPL = `
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  | <div class="revisions-dialog modal fade mx-auto" tabindex="-1" role="dialog"> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |     <style> | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |         .revisions-dialog .revision-content-wrapper { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             flex-grow: 1; | 
					
						
							|  |  |  |             margin-left: 20px; | 
					
						
							|  |  |  |             display: flex; | 
					
						
							|  |  |  |             flex-direction: column; | 
					
						
							|  |  |  |             min-width: 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |         .revisions-dialog .revision-content { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             overflow: auto; | 
					
						
							|  |  |  |             word-break: break-word; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |         .revisions-dialog .revision-content img { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             max-width: 100%; | 
					
						
							|  |  |  |             object-fit: contain; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |         .revisions-dialog .revision-content pre { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             max-width: 100%; | 
					
						
							|  |  |  |             word-break: break-all; | 
					
						
							|  |  |  |             white-space: pre-wrap; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     </style> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     <div class="modal-dialog modal-xl" role="document"> | 
					
						
							|  |  |  |         <div class="modal-content"> | 
					
						
							|  |  |  |             <div class="modal-header"> | 
					
						
							| 
									
										
										
										
											2024-09-03 11:28:50 +02:00
										 |  |  |                 <h5 class="modal-title flex-grow-1">${t("revisions.note_revisions")}</h5> | 
					
						
							| 
									
										
										
										
											2023-06-14 00:31:15 +02:00
										 |  |  |                 <button class="revisions-erase-all-revisions-button btn btn-sm" | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |                         title="${t("revisions.delete_all_revisions")}" | 
					
						
							|  |  |  |                         style="padding: 0 10px 0 10px;" type="button">${t("revisions.delete_all_button")}</button> | 
					
						
							| 
									
										
										
										
											2024-08-11 06:26:32 +03:00
										 |  |  |                 <button class="help-button" type="button" data-help-page="note-revisions.html" title="${t("revisions.help_title")}">?</button> | 
					
						
							| 
									
										
										
										
											2024-12-16 20:46:54 +01:00
										 |  |  |                 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("revisions.close")}"></button> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             </div> | 
					
						
							|  |  |  |             <div class="modal-body" style="display: flex; height: 80vh;"> | 
					
						
							|  |  |  |                 <div class="dropdown"> | 
					
						
							| 
									
										
										
										
											2024-09-03 11:28:50 +02:00
										 |  |  |                     <button class="revision-list-dropdown" type="button" style="display: none;" | 
					
						
							|  |  |  |                             data-bs-toggle="dropdown" data-bs-display="static"> | 
					
						
							|  |  |  |                     </button> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-20 02:30:29 +02:00
										 |  |  |                     <div class="revision-list dropdown-menu static" style="position: static; height: 100%; overflow: auto;"></div> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                 </div> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |                 <div class="revision-content-wrapper"> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                     <div style="flex-grow: 0; display: flex; justify-content: space-between;"> | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |                         <h3 class="revision-title" style="margin: 3px; flex-grow: 100;"></h3> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |                         <div class="revision-title-buttons"></div> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                     </div> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-23 01:28:35 +02:00
										 |  |  |                     <div class="revision-content use-tn-links"></div> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                 </div> | 
					
						
							|  |  |  |             </div> | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  |             <div class="modal-footer py-0"> | 
					
						
							|  |  |  |                 <span class="revisions-snapshot-interval flex-grow-1 my-0 py-0"></span> | 
					
						
							|  |  |  |                 <span class="maximum-revisions-for-current-note flex-grow-1 my-0 py-0"></span> | 
					
						
							|  |  |  |                 <button class="revision-settings-button icon-action bx bx-cog my-0 py-0" title="${t("revisions.settings")}"></button> | 
					
						
							|  |  |  |             </div> | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         </div> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  | </div>`;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  | interface RevisionItem { | 
					
						
							|  |  |  |     noteId: string; | 
					
						
							|  |  |  |     revisionId: string; | 
					
						
							|  |  |  |     dateLastEdited: string; | 
					
						
							|  |  |  |     contentLength: number; | 
					
						
							|  |  |  |     type: NoteType; | 
					
						
							|  |  |  |     title: string; | 
					
						
							|  |  |  |     isProtected: boolean; | 
					
						
							|  |  |  |     mime: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface FullRevision { | 
					
						
							|  |  |  |     content: string; | 
					
						
							|  |  |  |     mime: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  | export default class RevisionsDialog extends BasicWidget { | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private revisionItems: RevisionItem[]; | 
					
						
							|  |  |  |     private note: FNote | null; | 
					
						
							|  |  |  |     private revisionId: string | null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //@ts-ignore
 | 
					
						
							|  |  |  |     private modal: bootstrap.Modal; | 
					
						
							|  |  |  |     //@ts-ignore
 | 
					
						
							|  |  |  |     private listDropdown: bootstrap.Dropdown; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private $list!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $listDropdown!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $content!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $title!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $titleButtons!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $eraseAllRevisionsButton!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $maximumRevisions!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $snapshotInterval!: JQuery<HTMLElement>; | 
					
						
							|  |  |  |     private $revisionSettingsButton!: JQuery<HTMLElement>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |     constructor() { | 
					
						
							|  |  |  |         super(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.revisionItems = []; | 
					
						
							|  |  |  |         this.note = null; | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |         this.revisionId = null; | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     doRender() { | 
					
						
							|  |  |  |         this.$widget = $(TPL); | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         //@ts-ignore
 | 
					
						
							| 
									
										
										
										
											2024-09-03 18:15:10 +02:00
										 |  |  |         this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); | 
					
						
							| 
									
										
										
										
											2024-09-02 19:37:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |         this.$list = this.$widget.find(".revision-list"); | 
					
						
							|  |  |  |         this.$listDropdown = this.$widget.find(".revision-list-dropdown"); | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         //@ts-ignore
 | 
					
						
							| 
									
										
										
										
											2024-09-15 12:41:45 +02:00
										 |  |  |         this.listDropdown = bootstrap.Dropdown.getOrCreateInstance(this.$listDropdown); | 
					
						
							| 
									
										
										
										
											2023-06-04 23:02:49 +02:00
										 |  |  |         this.$content = this.$widget.find(".revision-content"); | 
					
						
							|  |  |  |         this.$title = this.$widget.find(".revision-title"); | 
					
						
							|  |  |  |         this.$titleButtons = this.$widget.find(".revision-title-buttons"); | 
					
						
							|  |  |  |         this.$eraseAllRevisionsButton = this.$widget.find(".revisions-erase-all-revisions-button"); | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  |         this.$snapshotInterval = this.$widget.find(".revisions-snapshot-interval"); | 
					
						
							|  |  |  |         this.$maximumRevisions = this.$widget.find(".maximum-revisions-for-current-note"); | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$revisionSettingsButton = this.$widget.find(".revision-settings-button"); | 
					
						
							| 
									
										
										
										
											2024-09-15 12:41:45 +02:00
										 |  |  |         this.listDropdown.show(); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$listDropdown.parent().on("hide.bs.dropdown", (e) => { | 
					
						
							| 
									
										
										
										
											2024-09-15 12:41:45 +02:00
										 |  |  |             // Prevent closing dropdown by pressing ESC and clicking outside
 | 
					
						
							|  |  |  |             e.preventDefault(); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         document.addEventListener( | 
					
						
							|  |  |  |             "keydown", | 
					
						
							|  |  |  |             (e) => { | 
					
						
							|  |  |  |                 // Close the revision dialog when revision element is focused and ESC is pressed
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |                 // TODO: Is this corret?
 | 
					
						
							|  |  |  |                 // @ts-ignore
 | 
					
						
							|  |  |  |                 if (e.key === "Escape" || ((e.target as HTMLElement)?.classList?.contains(["dropdown-item", "active"]))) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |                     this.modal.hide(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             true | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.$widget.on("shown.bs.modal", () => { | 
					
						
							|  |  |  |             this.$list.find(`[data-revision-id="${this.revisionId}"]`).trigger("focus"); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$eraseAllRevisionsButton.on("click", async () => { | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |             if (!this.note) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |             const text = t("revisions.confirm_delete_all"); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 20:19:26 +02:00
										 |  |  |             if (await dialogService.confirm(text)) { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                 await server.remove(`notes/${this.note.noteId}/revisions`); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-03 18:15:10 +02:00
										 |  |  |                 this.modal.hide(); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |                 toastService.showMessage(t("revisions.revisions_deleted")); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$list.on("focus", ".dropdown-item", (e) => { | 
					
						
							|  |  |  |             this.$list.find(".dropdown-item").each((i, el) => { | 
					
						
							|  |  |  |                 $(el).toggleClass("active", el === e.target); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             this.setContentPane(); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$revisionSettingsButton.on("click", async () => { | 
					
						
							|  |  |  |             appContext.tabManager.openContextWithNote("_optionsOther", { activate: true }); | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-02 19:37:02 +02:00
										 |  |  |     async showRevisionsEvent({ noteId = appContext.tabManager.getActiveContextNoteId() }) { | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         if (!noteId) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         utils.openDialog(this.$widget); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |         await this.loadRevisions(noteId); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |     async loadRevisions(noteId: string) { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         this.$list.empty(); | 
					
						
							|  |  |  |         this.$content.empty(); | 
					
						
							|  |  |  |         this.$titleButtons.empty(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.note = appContext.tabManager.getActiveContextNote(); | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         this.revisionItems = await server.get<RevisionItem[]>(`notes/${noteId}/revisions`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (const item of this.revisionItems) { | 
					
						
							|  |  |  |             this.$list.append( | 
					
						
							|  |  |  |                 $('<a class="dropdown-item" tabindex="0">') | 
					
						
							| 
									
										
										
										
											2023-06-29 23:32:19 +02:00
										 |  |  |                     .text(`${item.dateLastEdited.substr(0, 16)} (${utils.formatSize(item.contentLength)})`) | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |                     .attr("data-revision-id", item.revisionId) | 
					
						
							|  |  |  |                     .attr("title", t("revisions.revision_last_edited", { date: item.dateLastEdited })) | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-15 12:41:45 +02:00
										 |  |  |         this.listDropdown.show(); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (this.revisionItems.length > 0) { | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |             if (!this.revisionId) { | 
					
						
							|  |  |  |                 this.revisionId = this.revisionItems[0].revisionId; | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |             this.$title.text(t("revisions.no_revisions")); | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |             this.revisionId = null; | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.$eraseAllRevisionsButton.toggle(this.revisionItems.length > 0); | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Show the footer of the revisions dialog
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$snapshotInterval.text(t("revisions.snapshot_interval", { seconds: options.getInt("revisionSnapshotTimeInterval") })); | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         let revisionsNumberLimit: number | string = parseInt(this.note?.getLabelValue("versioningLimit") ?? ""); | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  |         if (!Number.isInteger(revisionsNumberLimit)) { | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |             revisionsNumberLimit = options.getInt("revisionSnapshotNumberLimit") ?? 0; | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (revisionsNumberLimit === -1) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |             revisionsNumberLimit = "∞"; | 
					
						
							| 
									
										
										
										
											2024-09-14 14:32:43 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$maximumRevisions.text(t("revisions.maximum_revisions", { number: revisionsNumberLimit })); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async setContentPane() { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         const revisionId = this.$list.find(".active").attr("data-revision-id"); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         const revisionItem = this.revisionItems.find((r) => r.revisionId === revisionId); | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         if (!revisionItem) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.$title.html(revisionItem.title); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 22:58:02 +01:00
										 |  |  |         this.renderContentButtons(revisionItem); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await this.renderContent(revisionItem); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |     renderContentButtons(revisionItem: RevisionItem) { | 
					
						
							| 
									
										
										
										
											2023-02-27 22:58:02 +01:00
										 |  |  |         this.$titleButtons.empty(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |         const $restoreRevisionButton = $(`<button class="btn btn-sm" type="button">${t("revisions.restore_button")}</button>`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         $restoreRevisionButton.on("click", async () => { | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |             const text = t("revisions.confirm_restore"); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 20:19:26 +02:00
										 |  |  |             if (await dialogService.confirm(text)) { | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |                 await server.post(`revisions/${revisionItem.revisionId}/restore`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-03 18:15:10 +02:00
										 |  |  |                 this.modal.hide(); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |                 toastService.showMessage(t("revisions.revision_restored")); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |         const $eraseRevisionButton = $(`<button class="btn btn-sm" type="button">${t("revisions.delete_button")}</button>`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         $eraseRevisionButton.on("click", async () => { | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |             const text = t("revisions.confirm_delete"); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 20:19:26 +02:00
										 |  |  |             if (await dialogService.confirm(text)) { | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |                 await server.remove(`revisions/${revisionItem.revisionId}`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |                 this.loadRevisions(revisionItem.noteId); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |                 toastService.showMessage(t("revisions.revision_deleted")); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!revisionItem.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |             this.$titleButtons.append($restoreRevisionButton).append("   "); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         this.$titleButtons.append($eraseRevisionButton).append("   "); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |         const $downloadButton = $(`<button class="btn btn-sm btn-primary" type="button">${t("revisions.download_button")}</button>`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         $downloadButton.on("click", () => openService.downloadRevision(revisionItem.noteId, revisionItem.revisionId)); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!revisionItem.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) { | 
					
						
							|  |  |  |             this.$titleButtons.append($downloadButton); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-02-27 22:58:02 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |     async renderContent(revisionItem: RevisionItem) { | 
					
						
							| 
									
										
										
										
											2023-02-27 22:58:02 +01:00
										 |  |  |         this.$content.empty(); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |         const fullRevision = await server.get<FullRevision>(`revisions/${revisionItem.revisionId}`); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         if (revisionItem.type === "text") { | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |             this.$content.html(fullRevision.content); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |             if (this.$content.find("span.math-tex").length > 0) { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                 await libraryLoader.requireLibrary(libraryLoader.KATEX); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-02 19:37:02 +02:00
										 |  |  |                 renderMathInElement(this.$content[0], { trust: true }); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         } else if (revisionItem.type === "code") { | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |             this.$content.html($("<pre>") | 
					
						
							|  |  |  |                 .text(fullRevision.content).html()); | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         } else if (revisionItem.type === "image") { | 
					
						
							| 
									
										
										
										
											2024-09-14 19:37:25 +08:00
										 |  |  |             if (fullRevision.mime === "image/svg+xml") { | 
					
						
							| 
									
										
										
										
											2024-09-14 21:09:52 +08:00
										 |  |  |                 let encodedSVG = encodeURIComponent(fullRevision.content); //Base64 of other format images may be embedded in svg
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |                 this.$content.html($("<img>") | 
					
						
							|  |  |  |                     .attr("src", `data:${fullRevision.mime};utf8,${encodedSVG}`) | 
					
						
							|  |  |  |                     .css("max-width", "100%") | 
					
						
							|  |  |  |                     .css("max-height", "100%").html()); | 
					
						
							| 
									
										
										
										
											2024-09-14 19:37:25 +08:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |                 this.$content.html( | 
					
						
							|  |  |  |                     $("<img>") | 
					
						
							|  |  |  |                         // 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
 | 
					
						
							|  |  |  |                         .attr("src", `data:${fullRevision.mime};base64,${fullRevision.content}`) | 
					
						
							|  |  |  |                         .css("max-width", "100%") | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |                         .css("max-height", "100%").html() | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2024-09-14 19:37:25 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         } else if (revisionItem.type === "file") { | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             const $table = $("<table cellpadding='10'>") | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |                 .append($("<tr>") | 
					
						
							|  |  |  |                     .append( | 
					
						
							|  |  |  |                         $("<th>").text(t("revisions.mime")), | 
					
						
							|  |  |  |                         $("<td>").text(revisionItem.mime))) | 
					
						
							|  |  |  |                     .append($("<tr>").append($("<th>").text(t("revisions.file_size")), $("<td>").text(utils.formatSize(revisionItem.contentLength)))); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-04 23:01:40 +02:00
										 |  |  |             if (fullRevision.content) { | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |                 $table.append( | 
					
						
							|  |  |  |                     $("<tr>").append( | 
					
						
							|  |  |  |                         $('<td colspan="2">').append($('<div style="font-weight: bold;">').text(t("revisions.preview")), $('<pre class="file-preview-content"></pre>').text(fullRevision.content)) | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |             this.$content.html($table.html()); | 
					
						
							| 
									
										
										
										
											2024-09-03 11:28:50 +02:00
										 |  |  |         } else if (["canvas", "mindMap"].includes(revisionItem.type)) { | 
					
						
							| 
									
										
										
										
											2023-11-27 10:10:27 +01:00
										 |  |  |             const encodedTitle = encodeURIComponent(revisionItem.title); | 
					
						
							| 
									
										
										
										
											2023-10-02 15:24:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |             this.$content.html( | 
					
						
							|  |  |  |                 $("<img>") | 
					
						
							|  |  |  |                     .attr("src", `api/revisions/${revisionItem.revisionId}/image/${encodedTitle}?${Math.random()}`) | 
					
						
							|  |  |  |                     .css("max-width", "100%") | 
					
						
							|  |  |  |                 .html()); | 
					
						
							| 
									
										
										
										
											2025-01-09 18:07:02 +02:00
										 |  |  |         } else if (revisionItem.type === "mermaid") { | 
					
						
							| 
									
										
										
										
											2023-11-27 10:10:27 +01:00
										 |  |  |             const encodedTitle = encodeURIComponent(revisionItem.title); | 
					
						
							| 
									
										
										
										
											2023-10-21 00:23:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-13 20:25:13 +02:00
										 |  |  |             this.$content.html( | 
					
						
							|  |  |  |                 $("<img>") | 
					
						
							|  |  |  |                     .attr("src", `api/revisions/${revisionItem.revisionId}/image/${encodedTitle}?${Math.random()}`) | 
					
						
							|  |  |  |                     .css("max-width", "100%") | 
					
						
							|  |  |  |                 .html()); | 
					
						
							| 
									
										
										
										
											2023-10-21 00:23:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             this.$content.append($("<pre>").text(fullRevision.content)); | 
					
						
							| 
									
										
										
										
											2023-02-27 22:58:02 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2024-07-25 17:14:08 +08:00
										 |  |  |             this.$content.text(t("revisions.preview_not_available")); | 
					
						
							| 
									
										
										
										
											2022-06-16 19:29:18 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |