feat(split_editor): make the two panes resizable

This commit is contained in:
Elian Doran 2025-03-21 22:02:08 +02:00
parent 395d76a156
commit 8952ff512f
No known key found for this signature in database
2 changed files with 44 additions and 30 deletions

View File

@ -6,9 +6,6 @@ import utils from "../services/utils.js";
import { loadElkIfNeeded, postprocessMermaidSvg } from "../services/mermaid.js";
import type FNote from "../entities/fnote.js";
import type { EventData } from "../components/app_context.js";
import ScrollingContainer from "./containers/scrolling_container.js";
import Split from "split.js";
import { DEFAULT_GUTTER_SIZE } from "../services/resizer.js";
const TPL = `<div class="mermaid-widget">
<style>
@ -58,7 +55,6 @@ export default class MermaidWidget extends NoteContextAwareWidget {
private dirtyAttachment?: boolean;
private zoomHandler?: () => void;
private zoomInstance?: SvgPanZoom.Instance;
private splitInstance?: Split.Instance;
private lastNote?: FNote;
isEnabled() {
@ -126,7 +122,6 @@ export default class MermaidWidget extends NoteContextAwareWidget {
this.$errorContainer.show();
}
this.#setupResizer();
this.lastNote = note;
}
@ -206,28 +201,6 @@ export default class MermaidWidget extends NoteContextAwareWidget {
$(window).on("resize", this.zoomHandler);
}
#setupResizer() {
if (!utils.isDesktop()) {
return;
}
const selfEl = this.$widget;
const scrollingContainer = this.parent?.children.find((ch) => ch instanceof ScrollingContainer)?.$widget;
if (!selfEl.length || !scrollingContainer?.length) {
return;
}
if (!this.splitInstance) {
this.splitInstance = Split([ selfEl[0], scrollingContainer[0] ], {
sizes: [ 50, 50 ],
direction: "vertical",
gutterSize: DEFAULT_GUTTER_SIZE,
onDragEnd: () => this.zoomHandler?.()
});
}
}
async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
if (this.noteId && loadResults.isNoteContentReloaded(this.noteId)) {
this.dirtyAttachment = true;

View File

@ -1,6 +1,9 @@
import type FNote from "../../entities/fnote.js";
import utils from "../../services/utils.js";
import EditableCodeTypeWidget from "./editable_code.js";
import TypeWidget from "./type_widget.js";
import Split from "split.js";
import { DEFAULT_GUTTER_SIZE } from "../../services/resizer.js";
const TPL = `\
<div class="note-detail-split note-detail-printable split-horizontal">
@ -17,21 +20,39 @@ const TPL = `\
height: 100%;
}
.note-detail-split .note-detail-split-editor {
width: 100%;
}
/* Horizontal layout */
.note-detail-split.split-horizontal > .note-detail-split-editor {
border-left: 1px solid var(--main-border-color);
}
.note-detail-split.split-horizontal > div {
height: 100%;
width: 50%;
}
.note-detail-split .note-detail-split-editor {
width: 100%;
}
/* Vertical layout */
</style>
</div>
`;
/**
* Abstract `TypeWidget` which contains a preview and editor pane, each displayed on half of the available screen.
*
* Features:
*
* - The two panes are resizeable via a split, on desktop.
*/
export default class SplitTypeEditor extends TypeWidget {
private splitInstance?: Split.Instance;
private $preview!: JQuery<HTMLElement>;
private $editor!: JQuery<HTMLElement>;
private editorTypeWidget: EditableCodeTypeWidget;
@ -48,10 +69,16 @@ export default class SplitTypeEditor extends TypeWidget {
this.$preview = this.$widget.find(".note-detail-split-preview");
this.$editor = this.$widget.find(".note-detail-split-editor");
this.$editor.append(this.editorTypeWidget.render());
this.#setupResizer();
super.doRender();
}
cleanup(): void {
this.splitInstance?.destroy();
this.splitInstance = undefined;
}
async doRefresh(note: FNote | null | undefined) {
await this.editorTypeWidget.initialized;
@ -62,6 +89,20 @@ export default class SplitTypeEditor extends TypeWidget {
}
}
#setupResizer() {
if (!utils.isDesktop()) {
return;
}
this.splitInstance?.destroy();
this.splitInstance = Split([ this.$preview[0], this.$editor[0] ], {
sizes: [ 50, 50 ],
direction: "horizontal",
gutterSize: DEFAULT_GUTTER_SIZE,
// onDragEnd: () => this.zoomHandler?.()
});
}
getData() {
return this.editorTypeWidget.getData();
}