Initialize editor toolbar via function, not web component
This commit is contained in:
parent
09629e4e4a
commit
f5fba15435
@ -387,12 +387,12 @@ class Browser(QMainWindow):
|
|||||||
editor._links["preview"] = lambda _editor: self.onTogglePreview()
|
editor._links["preview"] = lambda _editor: self.onTogglePreview()
|
||||||
editor.web.eval(
|
editor.web.eval(
|
||||||
f"""
|
f"""
|
||||||
$editorToolbar.addButton(editorToolbar.labelButton({{
|
$editorToolbar.then(({{ addButton }}) => addButton(editorToolbar.labelButton({{
|
||||||
label: `{tr.actions_preview()}`,
|
label: `{tr.actions_preview()}`,
|
||||||
tooltip: `{tr.browsing_preview_selected_card(val=shortcut(preview_shortcut))}`,
|
tooltip: `{tr.browsing_preview_selected_card(val=shortcut(preview_shortcut))}`,
|
||||||
onClick: () => bridgeCommand("preview"),
|
onClick: () => bridgeCommand("preview"),
|
||||||
disables: false,
|
disables: false,
|
||||||
}}), "notetype", -1);
|
}}), "notetype", -1));
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ _html = """
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div>
|
<div>
|
||||||
<anki-editor-toolbar id="editorToolbar"></anki-editor-toolbar>
|
<div id="editorToolbar"></div>
|
||||||
<div id="fields">
|
<div id="fields">
|
||||||
</div>
|
</div>
|
||||||
<div id="dupes" class="is-inactive">
|
<div id="dupes" class="is-inactive">
|
||||||
@ -155,7 +155,7 @@ class Editor:
|
|||||||
gui_hooks.editor_did_init_left_buttons(lefttopbtns, self)
|
gui_hooks.editor_did_init_left_buttons(lefttopbtns, self)
|
||||||
|
|
||||||
lefttopbtns_defs = [
|
lefttopbtns_defs = [
|
||||||
f"$editorToolbar.addButton(editorToolbar.rawButton({{ html: `{button}` }}), 'notetype', -1);"
|
f"$editorToolbar.then(({{ addButton }}) => addButton(editorToolbar.rawButton({{ html: `{button}` }}), 'notetype', -1));"
|
||||||
for button in lefttopbtns
|
for button in lefttopbtns
|
||||||
]
|
]
|
||||||
lefttopbtns_js = "\n".join(lefttopbtns_defs)
|
lefttopbtns_js = "\n".join(lefttopbtns_defs)
|
||||||
@ -173,10 +173,10 @@ class Editor:
|
|||||||
)
|
)
|
||||||
righttopbtns_js = (
|
righttopbtns_js = (
|
||||||
f"""
|
f"""
|
||||||
$editorToolbar.addButton(editorToolbar.buttonGroup({{
|
$editorToolbar.then(({{ addButton }}) => addButton(editorToolbar.buttonGroup({{
|
||||||
id: "addons",
|
id: "addons",
|
||||||
items: [ {righttopbtns_defs} ]
|
items: [ {righttopbtns_defs} ]
|
||||||
}}), -1);
|
}}), -1));
|
||||||
"""
|
"""
|
||||||
if righttopbtns_defs
|
if righttopbtns_defs
|
||||||
else ""
|
else ""
|
||||||
@ -1277,9 +1277,9 @@ gui_hooks.editor_will_munge_html.append(reverse_url_quoting)
|
|||||||
|
|
||||||
def set_cloze_button(editor: Editor) -> None:
|
def set_cloze_button(editor: Editor) -> None:
|
||||||
if editor.note.model()["type"] == MODEL_CLOZE:
|
if editor.note.model()["type"] == MODEL_CLOZE:
|
||||||
editor.web.eval('$editorToolbar.showButton("template", "cloze"); ')
|
editor.web.eval('$editorToolbar.then(({ showButton }) => showButton("template", "cloze")); ')
|
||||||
else:
|
else:
|
||||||
editor.web.eval('$editorToolbar.hideButton("template", "cloze"); ')
|
editor.web.eval('$editorToolbar.then(({ hideButton }) => hideButton("template", "cloze")); ')
|
||||||
|
|
||||||
|
|
||||||
gui_hooks.editor_did_load_note.append(set_cloze_button)
|
gui_hooks.editor_did_load_note.append(set_cloze_button)
|
||||||
|
5
ts/editor-toolbar/editorToolbar.d.ts
vendored
5
ts/editor-toolbar/editorToolbar.d.ts
vendored
@ -1,5 +0,0 @@
|
|||||||
import type { EditorToolbar } from ".";
|
|
||||||
|
|
||||||
declare namespace globalThis {
|
|
||||||
const $editorToolbar: EditorToolbar;
|
|
||||||
}
|
|
@ -3,7 +3,7 @@
|
|||||||
import type { ToolbarItem, IterableToolbarItem } from "./types";
|
import type { ToolbarItem, IterableToolbarItem } from "./types";
|
||||||
import type { Identifier } from "./identifiable";
|
import type { Identifier } from "./identifiable";
|
||||||
|
|
||||||
import { Writable, writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
import EditorToolbarSvelte from "./EditorToolbar.svelte";
|
import EditorToolbarSvelte from "./EditorToolbar.svelte";
|
||||||
|
|
||||||
@ -12,78 +12,73 @@ import "./bootstrap.css";
|
|||||||
import { add, insert, updateRecursive } from "./identifiable";
|
import { add, insert, updateRecursive } from "./identifiable";
|
||||||
import { showComponent, hideComponent, toggleComponent } from "./hideable";
|
import { showComponent, hideComponent, toggleComponent } from "./hideable";
|
||||||
|
|
||||||
let buttonsResolve: (value: Writable<IterableToolbarItem[]>) => void;
|
export interface EditorToolbarAPI {
|
||||||
let menusResolve: (value: Writable<ToolbarItem[]>) => void;
|
// Button API
|
||||||
|
|
||||||
export class EditorToolbar extends HTMLElement {
|
|
||||||
private buttonsPromise: Promise<Writable<IterableToolbarItem[]>> = new Promise(
|
|
||||||
(resolve) => {
|
|
||||||
buttonsResolve = resolve;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
private menusPromise: Promise<Writable<ToolbarItem[]>> = new Promise(
|
|
||||||
(resolve): void => {
|
|
||||||
menusResolve = resolve;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
connectedCallback(): void {
|
|
||||||
globalThis.$editorToolbar = this;
|
|
||||||
|
|
||||||
const buttons = writable([]);
|
|
||||||
const menus = writable([]);
|
|
||||||
|
|
||||||
new EditorToolbarSvelte({
|
|
||||||
target: this,
|
|
||||||
props: {
|
|
||||||
buttons,
|
|
||||||
menus,
|
|
||||||
nightMode: document.documentElement.classList.contains("night-mode"),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonsResolve(buttons);
|
|
||||||
menusResolve(menus);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateButton(
|
updateButton(
|
||||||
update: (component: ToolbarItem) => ToolbarItem,
|
update: (component: ToolbarItem) => ToolbarItem,
|
||||||
...identifiers: Identifier[]
|
...identifiers: Identifier[]
|
||||||
): void {
|
): void;
|
||||||
this.buttonsPromise.then(
|
showButton(...identifiers: Identifier[]): void;
|
||||||
(
|
hideButton(...identifiers: Identifier[]): void;
|
||||||
buttons: Writable<IterableToolbarItem[]>
|
toggleButton(...identifiers: Identifier[]): void;
|
||||||
): Writable<IterableToolbarItem[]> => {
|
insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void;
|
||||||
buttons.update(
|
addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void;
|
||||||
(items: IterableToolbarItem[]): IterableToolbarItem[] =>
|
|
||||||
updateRecursive(
|
|
||||||
update,
|
|
||||||
({ items } as unknown) as ToolbarItem,
|
|
||||||
...identifiers
|
|
||||||
).items as IterableToolbarItem[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return buttons;
|
// Menu API
|
||||||
}
|
updateMenu(
|
||||||
|
update: (component: ToolbarItem) => ToolbarItem,
|
||||||
|
...identifiers: Identifier[]
|
||||||
|
): void;
|
||||||
|
addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function editorToolbar(
|
||||||
|
target: HTMLElement,
|
||||||
|
initialButtons: IterableToolbarItem[] = [],
|
||||||
|
initialMenus: ToolbarItem[] = []
|
||||||
|
): EditorToolbarAPI {
|
||||||
|
const buttons = writable(initialButtons);
|
||||||
|
const menus = writable(initialMenus);
|
||||||
|
|
||||||
|
new EditorToolbarSvelte({
|
||||||
|
target,
|
||||||
|
props: {
|
||||||
|
buttons,
|
||||||
|
menus,
|
||||||
|
nightMode: document.documentElement.classList.contains("night-mode"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateButton(
|
||||||
|
update: (component: ToolbarItem) => ToolbarItem,
|
||||||
|
...identifiers: Identifier[]
|
||||||
|
): void {
|
||||||
|
buttons.update(
|
||||||
|
(items: IterableToolbarItem[]): IterableToolbarItem[] =>
|
||||||
|
updateRecursive(
|
||||||
|
update,
|
||||||
|
({ items } as unknown) as ToolbarItem,
|
||||||
|
...identifiers
|
||||||
|
).items as IterableToolbarItem[]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
showButton(...identifiers: Identifier[]): void {
|
function showButton(...identifiers: Identifier[]): void {
|
||||||
this.updateButton(showComponent, ...identifiers);
|
updateButton(showComponent, ...identifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
hideButton(...identifiers: Identifier[]): void {
|
function hideButton(...identifiers: Identifier[]): void {
|
||||||
this.updateButton(hideComponent, ...identifiers);
|
updateButton(hideComponent, ...identifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleButton(...identifiers: Identifier[]): void {
|
function toggleButton(...identifiers: Identifier[]): void {
|
||||||
this.updateButton(toggleComponent, ...identifiers);
|
updateButton(toggleComponent, ...identifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void {
|
function insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void {
|
||||||
const initIdentifiers = identifiers.slice(0, -1);
|
const initIdentifiers = identifiers.slice(0, -1);
|
||||||
const lastIdentifier = identifiers[identifiers.length - 1];
|
const lastIdentifier = identifiers[identifiers.length - 1];
|
||||||
this.updateButton(
|
updateButton(
|
||||||
(component: ToolbarItem) =>
|
(component: ToolbarItem) =>
|
||||||
insert(component as IterableToolbarItem, newButton, lastIdentifier),
|
insert(component as IterableToolbarItem, newButton, lastIdentifier),
|
||||||
|
|
||||||
@ -91,48 +86,51 @@ export class EditorToolbar extends HTMLElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void {
|
function addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void {
|
||||||
const initIdentifiers = identifiers.slice(0, -1);
|
const initIdentifiers = identifiers.slice(0, -1);
|
||||||
const lastIdentifier = identifiers[identifiers.length - 1];
|
const lastIdentifier = identifiers[identifiers.length - 1];
|
||||||
this.updateButton(
|
updateButton(
|
||||||
(component: ToolbarItem) =>
|
(component: ToolbarItem) =>
|
||||||
add(component as IterableToolbarItem, newButton, lastIdentifier),
|
add(component as IterableToolbarItem, newButton, lastIdentifier),
|
||||||
...initIdentifiers
|
...initIdentifiers
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMenu(
|
function updateMenu(
|
||||||
update: (component: ToolbarItem) => ToolbarItem,
|
update: (component: ToolbarItem) => ToolbarItem,
|
||||||
...identifiers: Identifier[]
|
...identifiers: Identifier[]
|
||||||
): void {
|
): void {
|
||||||
this.menusPromise.then(
|
menus.update(
|
||||||
(menus: Writable<ToolbarItem[]>): Writable<ToolbarItem[]> => {
|
(items: ToolbarItem[]): ToolbarItem[] =>
|
||||||
menus.update(
|
updateRecursive(
|
||||||
(items: ToolbarItem[]): ToolbarItem[] =>
|
update,
|
||||||
updateRecursive(
|
({ items } as unknown) as ToolbarItem,
|
||||||
update,
|
...identifiers
|
||||||
({ items } as unknown) as ToolbarItem,
|
).items as ToolbarItem[]
|
||||||
...identifiers
|
|
||||||
).items as ToolbarItem[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return menus;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void {
|
function addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void {
|
||||||
const initIdentifiers = identifiers.slice(0, -1);
|
const initIdentifiers = identifiers.slice(0, -1);
|
||||||
const lastIdentifier = identifiers[identifiers.length - 1];
|
const lastIdentifier = identifiers[identifiers.length - 1];
|
||||||
this.updateMenu(
|
updateMenu(
|
||||||
(component: ToolbarItem) =>
|
(component: ToolbarItem) =>
|
||||||
add(component as IterableToolbarItem, newMenu, lastIdentifier),
|
add(component as IterableToolbarItem, newMenu, lastIdentifier),
|
||||||
...initIdentifiers
|
...initIdentifiers
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("anki-editor-toolbar", EditorToolbar);
|
return {
|
||||||
|
updateButton,
|
||||||
|
showButton,
|
||||||
|
hideButton,
|
||||||
|
toggleButton,
|
||||||
|
insertButton,
|
||||||
|
addButton,
|
||||||
|
updateMenu,
|
||||||
|
addMenu,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/* Exports for editor */
|
/* Exports for editor */
|
||||||
// @ts-expect-error insufficient typing of svelte modules
|
// @ts-expect-error insufficient typing of svelte modules
|
||||||
|
@ -31,7 +31,6 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import "editor-toolbar";
|
|
||||||
customElements.define("anki-editable", Editable);
|
customElements.define("anki-editable", Editable);
|
||||||
customElements.define("anki-editing-area", EditingArea, { extends: "div" });
|
customElements.define("anki-editing-area", EditingArea, { extends: "div" });
|
||||||
customElements.define("anki-label-container", LabelContainer, { extends: "div" });
|
customElements.define("anki-label-container", LabelContainer, { extends: "div" });
|
||||||
@ -170,4 +169,4 @@ export function setFormat(cmd: string, arg?: any, nosave: boolean = false): void
|
|||||||
|
|
||||||
const i18n = setupI18n({ modules: [ModuleName.EDITING] });
|
const i18n = setupI18n({ modules: [ModuleName.EDITING] });
|
||||||
|
|
||||||
initToolbar(i18n);
|
export const $editorToolbar = initToolbar(i18n);
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
import { editorToolbar, EditorToolbarAPI } from "editor-toolbar";
|
||||||
|
|
||||||
import { getNotetypeGroup } from "./notetype";
|
import { getNotetypeGroup } from "./notetype";
|
||||||
import { getFormatInlineGroup } from "./formatInline";
|
import { getFormatInlineGroup } from "./formatInline";
|
||||||
import { getFormatBlockGroup, getFormatBlockMenus } from "./formatBlock";
|
import { getFormatBlockGroup, getFormatBlockMenus } from "./formatBlock";
|
||||||
import { getColorGroup } from "./color";
|
import { getColorGroup } from "./color";
|
||||||
import { getTemplateGroup, getTemplateMenus } from "./template";
|
import { getTemplateGroup, getTemplateMenus } from "./template";
|
||||||
|
|
||||||
export function initToolbar(i18n: Promise<void>): void {
|
export function initToolbar(i18n: Promise<void>): Promise<EditorToolbarAPI> {
|
||||||
|
let toolbarResolve: (value: EditorToolbarAPI) => void;
|
||||||
|
const toolbarPromise = new Promise<EditorToolbarAPI>((resolve) => {
|
||||||
|
toolbarResolve = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
i18n.then(() => {
|
i18n.then(() => {
|
||||||
|
const target = document.getElementById("editorToolbar")!;
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
getNotetypeGroup(),
|
getNotetypeGroup(),
|
||||||
getFormatInlineGroup(),
|
getFormatInlineGroup(),
|
||||||
@ -19,8 +28,9 @@ export function initToolbar(i18n: Promise<void>): void {
|
|||||||
|
|
||||||
const menus = [...getFormatBlockMenus(), ...getTemplateMenus()];
|
const menus = [...getFormatBlockMenus(), ...getTemplateMenus()];
|
||||||
|
|
||||||
globalThis.$editorToolbar.updateButton(() => ({ items: buttons }));
|
toolbarResolve(editorToolbar(target, buttons, menus));
|
||||||
globalThis.$editorToolbar.updateMenu(() => ({ items: menus }));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return toolbarPromise;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user