Utilize enableButtons disableButtons from Svelte component

This commit is contained in:
Henrik Giesel 2021-03-30 06:14:00 +02:00
parent 9340d20c20
commit a820059b8f
13 changed files with 71 additions and 95 deletions

View file

@ -82,7 +82,7 @@ _html = """
}
</style>
<div>
<anki-editor-toolbar></anki-editor-toolbar>
<anki-editor-toolbar id="editorToolbar"></anki-editor-toolbar>
<div id="fields">
</div>
<div id="dupes" class="is-inactive">
@ -1113,6 +1113,7 @@ class Editor:
dupes=showDupes,
paste=onPaste,
cutOrCopy=onCutOrCopy,
htmlEdit=onHtmlEdit,
)

View file

@ -77,7 +77,7 @@ esbuild(
"//ts:protobuf-shim.js",
],
args = [
"--global-name=anki",
"--global-name=editorToolbar",
"--inject:ts/protobuf-shim.js",
"--loader:.svg=text",
],

View file

@ -3,7 +3,7 @@
export const commandMap = writable(new Map<string, boolean>());
function updateButton(key: string): void {
function initializeButton(key: string): void {
commandMap.update(
(map: Map<string, boolean>): Map<string, boolean> =>
new Map([...map, [key, document.queryCommandState(key)]])
@ -24,11 +24,11 @@
);
}
export function updateButtonActive() {
export function updateActiveButtons() {
updateButtons((key: string): boolean => document.queryCommandState(key));
}
export function clearButtonActive() {
export function clearActiveButtons() {
updateButtons((): boolean => false);
}
</script>
@ -44,7 +44,7 @@
let active = false;
if (activatable) {
updateButton(command);
initializeButton(command);
commandMap.subscribe((map: Record<string, boolean>): void => {
active = map.get(command);

View file

@ -1,11 +1,17 @@
<script lang="typescript">
import type { Readable } from "svelte/store";
import { setContext } from "svelte";
import { disabledKey, nightModeKey } from "./contextKeys";
import ButtonGroup from "./ButtonGroup.svelte";
import type { Buttons } from "./ButtonGroup.svelte";
export let buttons: Buttons = [];
export let nightMode: boolean;
export let disabled: Readable<boolean> = false;
console.log(nightMode);
setContext(disabledKey, disabled);
setContext(nightModeKey, nightMode);
</script>
<style lang="scss">

View file

@ -1,8 +1,14 @@
<script lang="typescript">
import { getContext } from "svelte";
import type { Readable } from "svelte/store";
import { disabledKey } from "./contextKeys";
export let className: string = "";
export let onClick: (event: ClickEvent) => void;
export let active = false;
export let disabled = false;
const disabledStore = getContext(disabledKey)
$: disabled = $disabledStore;
</script>
<style lang="scss">
@ -16,6 +22,7 @@
& > :global(svg),
& > :global(img) {
fill: currentColor;
vertical-align: unset;
width: 100%;
height: 100%;
@ -38,6 +45,7 @@
&[disabled] {
opacity: 0.4;
cursor: not-allowed;
&:hover {
background-color: white;

View file

@ -0,0 +1,2 @@
export let nightModeKey = Symbol("nightMode");
export let disabledKey = Symbol("disabled");

View file

@ -1,5 +1,5 @@
// @ts-ignore
import CommandIconButton, { updateButtonActive } from "./CommandIconButton.svelte";
import CommandIconButton from "./CommandIconButton.svelte";
import boldIcon from "./type-bold.svg";
import italicIcon from "./type-italic.svg";
import underlineIcon from "./type-underline.svg";
@ -43,6 +43,3 @@ export const eraserButton = {
command: "removeFormat",
highlightable: false,
};
// TODO
setInterval(updateButtonActive, 2000);

View file

@ -1,9 +1,16 @@
import type { SvelteComponent } from "svelte";
import { checkNightMode } from "anki/nightmode";
import { setupI18n, ModuleName } from "anki/i18n";
import EditorToolbarSvelte from "./EditorToolbar.svelte";
import LabelButton from "./LabelButton.svelte";
// @ts-ignore
export { updateActiveButtons, clearActiveButtons } from "./CommandIconButton.svelte";
import { Writable, writable } from "svelte/store";
import {
boldButton,
italicButton,
@ -42,17 +49,29 @@ const defaultButtons = [
class EditorToolbar extends HTMLElement {
component?: SvelteComponent;
disabled?: Writable<boolean>;
connectedCallback(): void {
const nightMode = checkNightMode();
this.disabled = writable(false);
this.component = new EditorToolbarSvelte({
target: this,
props: {
nightMode,
buttons: defaultButtons,
},
});
setupI18n({ modules: [ModuleName.STATISTICS, ModuleName.SCHEDULING] }).then(() => {
this.component = new EditorToolbarSvelte({
target: this,
props: {
buttons: defaultButtons,
nightMode: checkNightMode(),
disabled: this.disabled,
},
});
})
}
enableButtons(): void {
this.disabled?.set(false);
}
disableButtons(): void {
this.disabled?.set(true);
}
}

View file

@ -6,7 +6,6 @@ import type { Editable } from "./editable";
import { bridgeCommand } from "./lib";
import { onInput, onKey, onKeyUp } from "./inputHandlers";
import { onFocus, onBlur } from "./focusHandlers";
import { updateButtonState } from "./toolbar";
function onPaste(evt: ClipboardEvent): void {
bridgeCommand("paste");
@ -60,7 +59,8 @@ export class EditingArea extends HTMLDivElement {
this.addEventListener("paste", onPaste);
this.addEventListener("copy", onCutOrCopy);
this.addEventListener("oncut", onCutOrCopy);
this.addEventListener("mouseup", updateButtonState);
// @ts-ignore
this.addEventListener("mouseup", editorToolbar.updateActiveButtons);
const baseStyleSheet = this.baseStyle.sheet as CSSStyleSheet;
baseStyleSheet.insertRule("anki-editable {}", 0);
@ -75,7 +75,8 @@ export class EditingArea extends HTMLDivElement {
this.removeEventListener("paste", onPaste);
this.removeEventListener("copy", onCutOrCopy);
this.removeEventListener("oncut", onCutOrCopy);
this.removeEventListener("mouseup", updateButtonState);
// @ts-ignore
this.removeEventListener("mouseup", editorToolbar.updateActiveButtons);
}
initialize(color: string, content: string): void {

View file

@ -5,13 +5,13 @@ import type { EditingArea } from "./editingArea";
import { saveField } from "./changeTimer";
import { bridgeCommand } from "./lib";
import { enableButtons, disableButtons } from "./toolbar";
export function onFocus(evt: FocusEvent): void {
const currentField = evt.currentTarget as EditingArea;
currentField.focusEditable();
bridgeCommand(`focus:${currentField.ord}`);
enableButtons();
// @ts-ignore
document.getElementById("editorToolbar").enableButtons();
}
export function onBlur(evt: FocusEvent): void {
@ -19,5 +19,6 @@ export function onBlur(evt: FocusEvent): void {
const currentFieldUnchanged = previousFocus === document.activeElement;
saveField(previousFocus, currentFieldUnchanged ? "key" : "blur");
disableButtons();
// @ts-ignore
document.getElementById("editorToolbar").disableButtons();
}

View file

@ -5,7 +5,6 @@ import { filterHTML } from "html-filter";
import { caretToEnd } from "./helpers";
import { saveField } from "./changeTimer";
import { updateButtonState, disableButtons } from "./toolbar";
import { EditorField } from "./editorField";
import { LabelContainer } from "./labelContainer";
@ -13,7 +12,6 @@ import { EditingArea } from "./editingArea";
import { Editable } from "./editable";
export { setNoteId, getNoteId } from "./noteId";
export { preventButtonFocus, toggleEditorButton, setFGButton } from "./toolbar";
export { saveNow } from "./changeTimer";
export { wrap, wrapIntoText } from "./wrap";
@ -43,7 +41,8 @@ export function focusField(n: number): void {
if (field) {
field.editingArea.focusEditable();
caretToEnd(field.editingArea);
updateButtonState();
// @ts-ignore
editorToolbar.updateActiveButtons();
}
}
@ -123,7 +122,8 @@ export function setFields(fields: [string, string][]): void {
if (!getCurrentField()) {
// when initial focus of the window is not on editor (e.g. browser)
disableButtons();
// @ts-ignore
document.getElementById("editorToolbar").disableButtons();
}
}
@ -158,6 +158,7 @@ export function setFormat(cmd: string, arg?: any, nosave: boolean = false): void
document.execCommand(cmd, false, arg);
if (!nosave) {
saveField(getCurrentField() as EditingArea, "key");
updateButtonState();
// @ts-ignore
editorToolbar.updateActiveButtons();
}
}

View file

@ -4,7 +4,6 @@
import { EditingArea } from "./editingArea";
import { caretToEnd, nodeIsElement } from "./helpers";
import { triggerChangeTimer } from "./changeTimer";
import { updateButtonState } from "./toolbar";
function inListItem(currentField: EditingArea): boolean {
const anchor = currentField.getSelection()!.anchorNode!;
@ -22,7 +21,8 @@ function inListItem(currentField: EditingArea): boolean {
export function onInput(event: Event): void {
// make sure IME changes get saved
triggerChangeTimer(event.currentTarget as EditingArea);
updateButtonState();
// @ts-ignore
editorToolbar.updateActiveButtons();
}
export function onKey(evt: KeyboardEvent): void {
@ -69,7 +69,8 @@ globalThis.addEventListener("keydown", (evt: KeyboardEvent) => {
const newFocusTarget = evt.target;
if (newFocusTarget instanceof EditingArea) {
caretToEnd(newFocusTarget);
updateButtonState();
// @ts-ignore
editorToolbar.updateActiveButtons();
}
},
{ once: true }

View file

@ -1,61 +0,0 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const highlightButtons = ["bold", "italic", "underline", "superscript", "subscript"];
export function updateButtonState(): void {
for (const name of highlightButtons) {
const elem = document.querySelector(`#${name}`) as HTMLElement;
elem.classList.toggle("highlighted", document.queryCommandState(name));
}
// fixme: forecolor
// 'col': document.queryCommandValue("forecolor")
}
function clearButtonHighlight(): void {
for (const name of highlightButtons) {
const elem = document.querySelector(`#${name}`) as HTMLElement;
elem.classList.remove("highlighted");
}
}
export function preventButtonFocus(): void {
for (const element of document.querySelectorAll("button.linkb")) {
element.addEventListener("mousedown", (evt: Event) => {
evt.preventDefault();
});
}
}
export function enableButtons(): void {
const buttons = document.querySelectorAll(
"button.linkb"
) as NodeListOf<HTMLButtonElement>;
buttons.forEach((elem: HTMLButtonElement): void => {
elem.disabled = false;
});
updateButtonState();
}
export function disableButtons(): void {
const buttons = document.querySelectorAll(
"button.linkb:not(.perm)"
) as NodeListOf<HTMLButtonElement>;
buttons.forEach((elem: HTMLButtonElement): void => {
elem.disabled = true;
});
clearButtonHighlight();
}
export function setFGButton(col: string): void {
document.getElementById("forecolor")!.style.backgroundColor = col;
}
export function toggleEditorButton(buttonOrId: string | HTMLElement): void {
const button =
typeof buttonOrId === "string"
? (document.getElementById(buttonOrId) as HTMLElement)
: buttonOrId;
button.classList.toggle("highlighted");
}