mirror of
https://github.com/TriliumNext/Trilium.git
synced 2025-12-11 05:45:26 -06:00
chore(react/type_widget): classic editor & inspector
This commit is contained in:
parent
2eab8b92d5
commit
efaa1815ec
@ -11,9 +11,11 @@ interface CKEditorWithWatchdogProps extends Pick<HTMLProps<HTMLDivElement>, "cla
|
|||||||
onNotificationWarning?: (evt: any, data: any) => void;
|
onNotificationWarning?: (evt: any, data: any) => void;
|
||||||
onWatchdogStateChange?: (watchdog: EditorWatchdog<any>) => void;
|
onWatchdogStateChange?: (watchdog: EditorWatchdog<any>) => void;
|
||||||
onChange: () => void;
|
onChange: () => void;
|
||||||
|
/** Called upon whenever a new CKEditor instance is initialized, whether it's the first initialization, after a crash or after a config change that requires it (e.g. content language). */
|
||||||
|
onEditorInitialized?: (editor: CKTextEditor) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CKEditorWithWatchdog({ content, contentLanguage, className, tabIndex, isClassicEditor, watchdogRef: externalWatchdogRef, watchdogConfig, buildEditorOpts, onNotificationWarning, onWatchdogStateChange, onChange }: CKEditorWithWatchdogProps) {
|
export default function CKEditorWithWatchdog({ content, contentLanguage, className, tabIndex, isClassicEditor, watchdogRef: externalWatchdogRef, watchdogConfig, onNotificationWarning, onWatchdogStateChange, onChange, onEditorInitialized }: CKEditorWithWatchdogProps) {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const watchdogRef = useRef<EditorWatchdog>(null);
|
const watchdogRef = useRef<EditorWatchdog>(null);
|
||||||
const [ editor, setEditor ] = useState<CKTextEditor>();
|
const [ editor, setEditor ] = useState<CKTextEditor>();
|
||||||
@ -33,6 +35,14 @@ export default function CKEditorWithWatchdog({ content, contentLanguage, classNa
|
|||||||
|
|
||||||
setEditor(editor);
|
setEditor(editor);
|
||||||
|
|
||||||
|
// Inspector integration.
|
||||||
|
if (import.meta.env.VITE_CKEDITOR_ENABLE_INSPECTOR === "true") {
|
||||||
|
const CKEditorInspector = (await import("@ckeditor/ckeditor5-inspector")).default;
|
||||||
|
CKEditorInspector.attach(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditorInitialized?.(editor);
|
||||||
|
|
||||||
return editor;
|
return editor;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import { useEditorSpacedUpdate, useNoteLabel, useTriliumOption } from "../../rea
|
|||||||
import { TypeWidgetProps } from "../type_widget";
|
import { TypeWidgetProps } from "../type_widget";
|
||||||
import CKEditorWithWatchdog from "./CKEditorWithWatchdog";
|
import CKEditorWithWatchdog from "./CKEditorWithWatchdog";
|
||||||
import "./EditableText.css";
|
import "./EditableText.css";
|
||||||
import { EditorWatchdog } from "@triliumnext/ckeditor5";
|
import { CKTextEditor, ClassicEditor, EditorWatchdog } from "@triliumnext/ckeditor5";
|
||||||
|
import Component from "../../../components/component";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The editor can operate into two distinct modes:
|
* The editor can operate into two distinct modes:
|
||||||
@ -14,7 +15,7 @@ import { EditorWatchdog } from "@triliumnext/ckeditor5";
|
|||||||
* - Ballon block mode, in which there is a floating toolbar for the selected text, but another floating button for the entire block (i.e. paragraph).
|
* - Ballon block mode, in which there is a floating toolbar for the selected text, but another floating button for the entire block (i.e. paragraph).
|
||||||
* - Decoupled mode, in which the editing toolbar is actually added on the client side (in {@link ClassicEditorToolbar}), see https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for an example on how the decoupled editor works.
|
* - Decoupled mode, in which the editing toolbar is actually added on the client side (in {@link ClassicEditorToolbar}), see https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for an example on how the decoupled editor works.
|
||||||
*/
|
*/
|
||||||
export default function EditableText({ note }: TypeWidgetProps) {
|
export default function EditableText({ note, parentComponent }: TypeWidgetProps) {
|
||||||
const [ content, setContent ] = useState<string>();
|
const [ content, setContent ] = useState<string>();
|
||||||
const watchdogRef = useRef<EditorWatchdog>(null);
|
const watchdogRef = useRef<EditorWatchdog>(null);
|
||||||
const [ language ] = useNoteLabel(note, "language");
|
const [ language ] = useNoteLabel(note, "language");
|
||||||
@ -61,6 +62,13 @@ export default function EditableText({ note }: TypeWidgetProps) {
|
|||||||
onNotificationWarning={onNotificationWarning}
|
onNotificationWarning={onNotificationWarning}
|
||||||
onWatchdogStateChange={onWatchdogStateChange}
|
onWatchdogStateChange={onWatchdogStateChange}
|
||||||
onChange={() => spacedUpdate.scheduleUpdate()}
|
onChange={() => spacedUpdate.scheduleUpdate()}
|
||||||
|
onEditorInitialized={(editor) => {
|
||||||
|
console.log("Editor has been initialized!", parentComponent, editor);
|
||||||
|
|
||||||
|
if (isClassicEditor) {
|
||||||
|
setupClassicEditor(editor, parentComponent);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>}
|
/>}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -94,3 +102,54 @@ function onNotificationWarning(data, evt) {
|
|||||||
|
|
||||||
evt.stop();
|
evt.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupClassicEditor(editor: CKTextEditor, parentComponent: Component | undefined) {
|
||||||
|
if (!parentComponent) return;
|
||||||
|
const $classicToolbarWidget = findClassicToolbar(parentComponent);
|
||||||
|
console.log("Found ", $classicToolbarWidget);
|
||||||
|
|
||||||
|
$classicToolbarWidget.empty();
|
||||||
|
if ($classicToolbarWidget.length) {
|
||||||
|
const toolbarView = (editor as ClassicEditor).ui.view.toolbar;
|
||||||
|
if (toolbarView.element) {
|
||||||
|
$classicToolbarWidget[0].appendChild(toolbarView.element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utils.isMobile()) {
|
||||||
|
$classicToolbarWidget.addClass("visible");
|
||||||
|
|
||||||
|
// Reposition all dropdowns to point upwards instead of downwards.
|
||||||
|
// See https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for more info.
|
||||||
|
const toolbarView = (editor as ClassicEditor).ui.view.toolbar;
|
||||||
|
for (const item of toolbarView.items) {
|
||||||
|
if (!("panelView" in item)) continue;
|
||||||
|
|
||||||
|
item.on("change:isOpen", () => {
|
||||||
|
if (!("isOpen" in item) || !item.isOpen) return;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
item.panelView.position = item.panelView.position.replace("s", "n");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findClassicToolbar(parentComponent: Component): JQuery<HTMLElement> {
|
||||||
|
const $widget = $(parentComponent.$widget);
|
||||||
|
|
||||||
|
if (!utils.isMobile()) {
|
||||||
|
const $parentSplit = $widget.parents(".note-split.type-text");
|
||||||
|
console.log("Got split ", $parentSplit)
|
||||||
|
|
||||||
|
if ($parentSplit.length) {
|
||||||
|
// The editor is in a normal tab.
|
||||||
|
return $parentSplit.find("> .ribbon-container .classic-toolbar-widget");
|
||||||
|
} else {
|
||||||
|
// The editor is in a popup.
|
||||||
|
return $widget.closest(".modal-body").find(".classic-toolbar-widget");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $("body").find(".classic-toolbar-widget");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -38,47 +38,6 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
|
|
||||||
async initEditor() {
|
async initEditor() {
|
||||||
this.watchdog.setCreator(async (_, editorConfig) => {
|
this.watchdog.setCreator(async (_, editorConfig) => {
|
||||||
logInfo("Creating new CKEditor");
|
|
||||||
|
|
||||||
if (isClassicEditor) {
|
|
||||||
const $classicToolbarWidget = this.findClassicToolbar();
|
|
||||||
|
|
||||||
$classicToolbarWidget.empty();
|
|
||||||
if ($classicToolbarWidget.length) {
|
|
||||||
const toolbarView = (editor as ClassicEditor).ui.view.toolbar;
|
|
||||||
if (toolbarView.element) {
|
|
||||||
$classicToolbarWidget[0].appendChild(toolbarView.element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utils.isMobile()) {
|
|
||||||
$classicToolbarWidget.addClass("visible");
|
|
||||||
|
|
||||||
// Reposition all dropdowns to point upwards instead of downwards.
|
|
||||||
// See https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for more info.
|
|
||||||
const toolbarView = (editor as ClassicEditor).ui.view.toolbar;
|
|
||||||
for (const item of toolbarView.items) {
|
|
||||||
if (!("panelView" in item)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.on("change:isOpen", () => {
|
|
||||||
if (!("isOpen" in item) || !item.isOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
item.panelView.position = item.panelView.position.replace("s", "n");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (import.meta.env.VITE_CKEDITOR_ENABLE_INSPECTOR === "true") {
|
|
||||||
const CKEditorInspector = (await import("@ckeditor/ckeditor5-inspector")).default;
|
|
||||||
CKEditorInspector.attach(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Touch bar integration
|
// Touch bar integration
|
||||||
if (hasTouchBar) {
|
if (hasTouchBar) {
|
||||||
for (const event of [ "bold", "italic", "underline", "paragraph", "heading" ]) {
|
for (const event of [ "bold", "italic", "underline", "paragraph", "heading" ]) {
|
||||||
@ -320,22 +279,6 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findClassicToolbar(): JQuery<HTMLElement> {
|
|
||||||
if (!utils.isMobile()) {
|
|
||||||
const $parentSplit = this.$widget.parents(".note-split.type-text");
|
|
||||||
|
|
||||||
if ($parentSplit.length) {
|
|
||||||
// The editor is in a normal tab.
|
|
||||||
return $parentSplit.find("> .ribbon-container .classic-toolbar-widget");
|
|
||||||
} else {
|
|
||||||
// The editor is in a popup.
|
|
||||||
return this.$widget.closest(".modal-body").find(".classic-toolbar-widget");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return $("body").find(".classic-toolbar-widget");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTouchBarCommand(data: CommandListenerData<"buildTouchBar">) {
|
buildTouchBarCommand(data: CommandListenerData<"buildTouchBar">) {
|
||||||
const { TouchBar, buildIcon } = data;
|
const { TouchBar, buildIcon } = data;
|
||||||
const { TouchBarSegmentedControl, TouchBarGroup, TouchBarButton } = TouchBar;
|
const { TouchBarSegmentedControl, TouchBarGroup, TouchBarButton } = TouchBar;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user