From f5fba15435788b56b0ef2738a3ec6ec1e690a500 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 25 Apr 2021 18:25:03 +0200 Subject: [PATCH 1/2] Initialize editor toolbar via function, not web component --- qt/aqt/browser/browser.py | 4 +- qt/aqt/editor.py | 12 +-- ts/editor-toolbar/editorToolbar.d.ts | 5 - ts/editor-toolbar/index.ts | 154 +++++++++++++-------------- ts/editor/index.ts | 3 +- ts/editor/toolbar.ts | 16 ++- 6 files changed, 98 insertions(+), 96 deletions(-) delete mode 100644 ts/editor-toolbar/editorToolbar.d.ts diff --git a/qt/aqt/browser/browser.py b/qt/aqt/browser/browser.py index f3acadde8..d607c301a 100644 --- a/qt/aqt/browser/browser.py +++ b/qt/aqt/browser/browser.py @@ -387,12 +387,12 @@ class Browser(QMainWindow): editor._links["preview"] = lambda _editor: self.onTogglePreview() editor.web.eval( f""" -$editorToolbar.addButton(editorToolbar.labelButton({{ +$editorToolbar.then(({{ addButton }}) => addButton(editorToolbar.labelButton({{ label: `{tr.actions_preview()}`, tooltip: `{tr.browsing_preview_selected_card(val=shortcut(preview_shortcut))}`, onClick: () => bridgeCommand("preview"), disables: false, -}}), "notetype", -1); +}}), "notetype", -1)); """ ) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 1db017bb1..6b2b3b2ac 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -82,7 +82,7 @@ _html = """ }
- +
@@ -155,7 +155,7 @@ class Editor: gui_hooks.editor_did_init_left_buttons(lefttopbtns, self) 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 ] lefttopbtns_js = "\n".join(lefttopbtns_defs) @@ -173,10 +173,10 @@ class Editor: ) righttopbtns_js = ( f""" -$editorToolbar.addButton(editorToolbar.buttonGroup({{ +$editorToolbar.then(({{ addButton }}) => addButton(editorToolbar.buttonGroup({{ id: "addons", items: [ {righttopbtns_defs} ] -}}), -1); +}}), -1)); """ if righttopbtns_defs else "" @@ -1277,9 +1277,9 @@ gui_hooks.editor_will_munge_html.append(reverse_url_quoting) def set_cloze_button(editor: Editor) -> None: if editor.note.model()["type"] == MODEL_CLOZE: - editor.web.eval('$editorToolbar.showButton("template", "cloze"); ') + editor.web.eval('$editorToolbar.then(({ showButton }) => showButton("template", "cloze")); ') 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) diff --git a/ts/editor-toolbar/editorToolbar.d.ts b/ts/editor-toolbar/editorToolbar.d.ts deleted file mode 100644 index 4fd9afb11..000000000 --- a/ts/editor-toolbar/editorToolbar.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { EditorToolbar } from "."; - -declare namespace globalThis { - const $editorToolbar: EditorToolbar; -} diff --git a/ts/editor-toolbar/index.ts b/ts/editor-toolbar/index.ts index 0ff494251..ff6e645c7 100644 --- a/ts/editor-toolbar/index.ts +++ b/ts/editor-toolbar/index.ts @@ -3,7 +3,7 @@ import type { ToolbarItem, IterableToolbarItem } from "./types"; import type { Identifier } from "./identifiable"; -import { Writable, writable } from "svelte/store"; +import { writable } from "svelte/store"; import EditorToolbarSvelte from "./EditorToolbar.svelte"; @@ -12,78 +12,73 @@ import "./bootstrap.css"; import { add, insert, updateRecursive } from "./identifiable"; import { showComponent, hideComponent, toggleComponent } from "./hideable"; -let buttonsResolve: (value: Writable) => void; -let menusResolve: (value: Writable) => void; - -export class EditorToolbar extends HTMLElement { - private buttonsPromise: Promise> = new Promise( - (resolve) => { - buttonsResolve = resolve; - } - ); - private menusPromise: Promise> = 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); - } - +export interface EditorToolbarAPI { + // Button API updateButton( update: (component: ToolbarItem) => ToolbarItem, ...identifiers: Identifier[] - ): void { - this.buttonsPromise.then( - ( - buttons: Writable - ): Writable => { - buttons.update( - (items: IterableToolbarItem[]): IterableToolbarItem[] => - updateRecursive( - update, - ({ items } as unknown) as ToolbarItem, - ...identifiers - ).items as IterableToolbarItem[] - ); + ): void; + showButton(...identifiers: Identifier[]): void; + hideButton(...identifiers: Identifier[]): void; + toggleButton(...identifiers: Identifier[]): void; + insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void; + addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void; - 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 { - this.updateButton(showComponent, ...identifiers); + function showButton(...identifiers: Identifier[]): void { + updateButton(showComponent, ...identifiers); } - hideButton(...identifiers: Identifier[]): void { - this.updateButton(hideComponent, ...identifiers); + function hideButton(...identifiers: Identifier[]): void { + updateButton(hideComponent, ...identifiers); } - toggleButton(...identifiers: Identifier[]): void { - this.updateButton(toggleComponent, ...identifiers); + function toggleButton(...identifiers: Identifier[]): void { + updateButton(toggleComponent, ...identifiers); } - insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void { + function insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void { const initIdentifiers = identifiers.slice(0, -1); const lastIdentifier = identifiers[identifiers.length - 1]; - this.updateButton( + updateButton( (component: ToolbarItem) => 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 lastIdentifier = identifiers[identifiers.length - 1]; - this.updateButton( + updateButton( (component: ToolbarItem) => add(component as IterableToolbarItem, newButton, lastIdentifier), ...initIdentifiers ); } - updateMenu( + function updateMenu( update: (component: ToolbarItem) => ToolbarItem, ...identifiers: Identifier[] ): void { - this.menusPromise.then( - (menus: Writable): Writable => { - menus.update( - (items: ToolbarItem[]): ToolbarItem[] => - updateRecursive( - update, - ({ items } as unknown) as ToolbarItem, - ...identifiers - ).items as ToolbarItem[] - ); - - return menus; - } + menus.update( + (items: ToolbarItem[]): ToolbarItem[] => + updateRecursive( + update, + ({ items } as unknown) as ToolbarItem, + ...identifiers + ).items as ToolbarItem[] ); } - addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void { + function addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void { const initIdentifiers = identifiers.slice(0, -1); const lastIdentifier = identifiers[identifiers.length - 1]; - this.updateMenu( + updateMenu( (component: ToolbarItem) => add(component as IterableToolbarItem, newMenu, lastIdentifier), ...initIdentifiers ); } -} -customElements.define("anki-editor-toolbar", EditorToolbar); + return { + updateButton, + showButton, + hideButton, + toggleButton, + insertButton, + addButton, + updateMenu, + addMenu, + }; +} /* Exports for editor */ // @ts-expect-error insufficient typing of svelte modules diff --git a/ts/editor/index.ts b/ts/editor/index.ts index 826d7942f..8cac7ee94 100644 --- a/ts/editor/index.ts +++ b/ts/editor/index.ts @@ -31,7 +31,6 @@ declare global { } } -import "editor-toolbar"; customElements.define("anki-editable", Editable); customElements.define("anki-editing-area", EditingArea, { 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] }); -initToolbar(i18n); +export const $editorToolbar = initToolbar(i18n); diff --git a/ts/editor/toolbar.ts b/ts/editor/toolbar.ts index f0af19df7..b74de5ccf 100644 --- a/ts/editor/toolbar.ts +++ b/ts/editor/toolbar.ts @@ -1,14 +1,23 @@ // Copyright: Ankitects Pty Ltd and contributors // 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 { getFormatInlineGroup } from "./formatInline"; import { getFormatBlockGroup, getFormatBlockMenus } from "./formatBlock"; import { getColorGroup } from "./color"; import { getTemplateGroup, getTemplateMenus } from "./template"; -export function initToolbar(i18n: Promise): void { +export function initToolbar(i18n: Promise): Promise { + let toolbarResolve: (value: EditorToolbarAPI) => void; + const toolbarPromise = new Promise((resolve) => { + toolbarResolve = resolve; + }); + document.addEventListener("DOMContentLoaded", () => { i18n.then(() => { + const target = document.getElementById("editorToolbar")!; + const buttons = [ getNotetypeGroup(), getFormatInlineGroup(), @@ -19,8 +28,9 @@ export function initToolbar(i18n: Promise): void { const menus = [...getFormatBlockMenus(), ...getTemplateMenus()]; - globalThis.$editorToolbar.updateButton(() => ({ items: buttons })); - globalThis.$editorToolbar.updateMenu(() => ({ items: menus })); + toolbarResolve(editorToolbar(target, buttons, menus)); }); }); + + return toolbarPromise; } From 268adf1d039434ae89f94a9e4909dd764a2797e5 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Sun, 25 Apr 2021 19:15:00 +0200 Subject: [PATCH 2/2] Move EditorToolbar API into EditorToolbar.svelte --- qt/aqt/editor.py | 8 +- ts/editor-toolbar/EditorToolbar.svelte | 88 ++++++++++++++++-- ts/editor-toolbar/index.ts | 122 ++----------------------- ts/editor/toolbar.ts | 8 +- 4 files changed, 95 insertions(+), 131 deletions(-) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 6b2b3b2ac..5065abb29 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -1277,9 +1277,13 @@ gui_hooks.editor_will_munge_html.append(reverse_url_quoting) def set_cloze_button(editor: Editor) -> None: if editor.note.model()["type"] == MODEL_CLOZE: - editor.web.eval('$editorToolbar.then(({ showButton }) => showButton("template", "cloze")); ') + editor.web.eval( + '$editorToolbar.then(({ showButton }) => showButton("template", "cloze")); ' + ) else: - editor.web.eval('$editorToolbar.then(({ hideButton }) => hideButton("template", "cloze")); ') + editor.web.eval( + '$editorToolbar.then(({ hideButton }) => hideButton("template", "cloze")); ' + ) gui_hooks.editor_did_load_note.append(set_cloze_button) diff --git a/ts/editor-toolbar/EditorToolbar.svelte b/ts/editor-toolbar/EditorToolbar.svelte index c11f6ee7f..5626973dc 100644 --- a/ts/editor-toolbar/EditorToolbar.svelte +++ b/ts/editor-toolbar/EditorToolbar.svelte @@ -18,19 +18,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
- {#each _menus as menu} + {#each menus as menu} {/each}
diff --git a/ts/editor-toolbar/index.ts b/ts/editor-toolbar/index.ts index ff6e645c7..0e64430cb 100644 --- a/ts/editor-toolbar/index.ts +++ b/ts/editor-toolbar/index.ts @@ -1,46 +1,18 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import type { ToolbarItem, IterableToolbarItem } from "./types"; -import type { Identifier } from "./identifiable"; -import { writable } from "svelte/store"; - -import EditorToolbarSvelte from "./EditorToolbar.svelte"; +import EditorToolbar from "./EditorToolbar.svelte"; +export { default as EditorToolbar } from "./EditorToolbar.svelte"; import "./bootstrap.css"; -import { add, insert, updateRecursive } from "./identifiable"; -import { showComponent, hideComponent, toggleComponent } from "./hideable"; - -export interface EditorToolbarAPI { - // Button API - updateButton( - update: (component: ToolbarItem) => ToolbarItem, - ...identifiers: Identifier[] - ): void; - showButton(...identifiers: Identifier[]): void; - hideButton(...identifiers: Identifier[]): void; - toggleButton(...identifiers: Identifier[]): void; - insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void; - addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void; - - // 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({ + buttons: IterableToolbarItem[] = [], + menus: ToolbarItem[] = [] +): EditorToolbar { + return new EditorToolbar({ target, props: { buttons, @@ -48,88 +20,6 @@ export function editorToolbar( 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[] - ); - } - - function showButton(...identifiers: Identifier[]): void { - updateButton(showComponent, ...identifiers); - } - - function hideButton(...identifiers: Identifier[]): void { - updateButton(hideComponent, ...identifiers); - } - - function toggleButton(...identifiers: Identifier[]): void { - updateButton(toggleComponent, ...identifiers); - } - - function insertButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void { - const initIdentifiers = identifiers.slice(0, -1); - const lastIdentifier = identifiers[identifiers.length - 1]; - updateButton( - (component: ToolbarItem) => - insert(component as IterableToolbarItem, newButton, lastIdentifier), - - ...initIdentifiers - ); - } - - function addButton(newButton: ToolbarItem, ...identifiers: Identifier[]): void { - const initIdentifiers = identifiers.slice(0, -1); - const lastIdentifier = identifiers[identifiers.length - 1]; - updateButton( - (component: ToolbarItem) => - add(component as IterableToolbarItem, newButton, lastIdentifier), - ...initIdentifiers - ); - } - - function updateMenu( - update: (component: ToolbarItem) => ToolbarItem, - ...identifiers: Identifier[] - ): void { - menus.update( - (items: ToolbarItem[]): ToolbarItem[] => - updateRecursive( - update, - ({ items } as unknown) as ToolbarItem, - ...identifiers - ).items as ToolbarItem[] - ); - } - - function addMenu(newMenu: ToolbarItem, ...identifiers: Identifier[]): void { - const initIdentifiers = identifiers.slice(0, -1); - const lastIdentifier = identifiers[identifiers.length - 1]; - updateMenu( - (component: ToolbarItem) => - add(component as IterableToolbarItem, newMenu, lastIdentifier), - ...initIdentifiers - ); - } - - return { - updateButton, - showButton, - hideButton, - toggleButton, - insertButton, - addButton, - updateMenu, - addMenu, - }; } /* Exports for editor */ diff --git a/ts/editor/toolbar.ts b/ts/editor/toolbar.ts index b74de5ccf..930c3ee41 100644 --- a/ts/editor/toolbar.ts +++ b/ts/editor/toolbar.ts @@ -1,6 +1,6 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -import { editorToolbar, EditorToolbarAPI } from "editor-toolbar"; +import { editorToolbar, EditorToolbar } from "editor-toolbar"; import { getNotetypeGroup } from "./notetype"; import { getFormatInlineGroup } from "./formatInline"; @@ -8,9 +8,9 @@ import { getFormatBlockGroup, getFormatBlockMenus } from "./formatBlock"; import { getColorGroup } from "./color"; import { getTemplateGroup, getTemplateMenus } from "./template"; -export function initToolbar(i18n: Promise): Promise { - let toolbarResolve: (value: EditorToolbarAPI) => void; - const toolbarPromise = new Promise((resolve) => { +export function initToolbar(i18n: Promise) { + let toolbarResolve: (value: EditorToolbar) => void; + const toolbarPromise = new Promise((resolve) => { toolbarResolve = resolve; });