Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved add-on extension API #1626

Merged
merged 45 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
19e09ae
Add componentHook functionality
hgiesel Jan 23, 2022
a5fffd5
Register package NoteEditor
hgiesel Jan 23, 2022
b6767a2
Rename OldEditorAdapter to NoteEditor
hgiesel Jan 23, 2022
53079fe
Expose instances in component-hook as well
hgiesel Jan 23, 2022
22b0b6b
Rename NoteTypeButtons to NotetypeButtons
hgiesel Jan 23, 2022
e5b9423
Move PreviewButton initialization to BrowserEditor.svelte
hgiesel Jan 23, 2022
705582b
Remove focusInRichText
hgiesel Jan 24, 2022
3194816
Satisfy formatter
hgiesel Jan 24, 2022
0e7352b
Fix remaining rebase issues
hgiesel Jan 24, 2022
fc4257f
Add .bazel to .prettierignore
hgiesel Jan 24, 2022
e14fe8e
Rename currentField and activeInput to focused{Field,Input}
hgiesel Jan 24, 2022
78a6bde
Move identifier to lib and registration to sveltelib
hgiesel Jan 24, 2022
7c11182
Fix Dynamic component insertion
hgiesel Jan 25, 2022
f33e114
Simplify editingInputIsRichText
hgiesel Jan 25, 2022
289955f
Give extra warning in svelte/svelte.ts
hgiesel Jan 25, 2022
b61f1d2
Change signature of contextProperty
hgiesel Jan 26, 2022
c999737
Add ts/typings for add-on definition files
hgiesel Jan 26, 2022
5396a8e
Add Anki types in typings/common/index.d.ts
hgiesel Jan 26, 2022
c7d4e36
Export without .svelte suffix
hgiesel Jan 26, 2022
298cf8f
Fix left over .svelte import from editor.py
hgiesel Jan 26, 2022
2fbd3ca
Rename NoteTypeButtons to unrelated to ensure case-only rename
hgiesel Jan 27, 2022
2b33a65
Rename back to NotetypeButtons.svelte
hgiesel Jan 27, 2022
a29666b
Remove unused component-hook.ts, Fix typing in lifecycle-hooks
hgiesel Jan 27, 2022
67b3350
Merge runtime-require and register-package into one file
hgiesel Jan 27, 2022
3adfb79
Rename uiDidLoad to loaded
hgiesel Jan 27, 2022
d02dd2f
Fix eslint / svelte-check
hgiesel Jan 27, 2022
c35855f
Rename context imports to noteEditorContext
hgiesel Jan 27, 2022
1c2d822
Fix import name mismatch
hgiesel Jan 28, 2022
504fa9c
Rename two missed usages of uiDidLoad
hgiesel Jan 28, 2022
f849748
Fix ButtonDropdown from having wrong border-radius
hgiesel Jan 28, 2022
bf23240
Uniformly rename libraries to packages
hgiesel Jan 28, 2022
45c3c4b
Refactor registration.ts into dynamic-slotting
hgiesel Jan 30, 2022
1552a06
Remove dynamically-slottable logic from ButtonToolbar
hgiesel Jan 30, 2022
86a0dff
Use DynamicallySlottable in editor-toolbar
hgiesel Jan 30, 2022
a4a9b70
Fix no border radius on indentation button dropdown
hgiesel Jan 31, 2022
5490f85
Fix AddonButtons
hgiesel Jan 31, 2022
c14d8fd
Remove Item/ButtonGroupItem in deck-options, where it's not necessary
hgiesel Feb 1, 2022
17eabe1
Remove unnecessary uses of Item and ButtonGroupItem
hgiesel Feb 1, 2022
97a4553
Fix remaining tests
hgiesel Feb 2, 2022
200cae3
Fix relative imports
hgiesel Feb 2, 2022
40c78c3
Revert change return value of remapBinToSrcDir to ./bazel/out...
hgiesel Feb 2, 2022
1a380e0
Remove typings directory
hgiesel Feb 2, 2022
f4f5e0d
Adjust comments for dynamic-slottings
hgiesel Feb 2, 2022
96e96c7
Merge branch 'main' into uiPromisePack
hgiesel Feb 2, 2022
13e37bf
Merge branch 'uiPromisePack' of github.com:hgiesel/anki into uiPromis…
hgiesel Feb 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ licenses.json
vendor
node_modules
bazel-*
.bazel
ftl/usage
.mypy_cache
.mypy_cache
7 changes: 1 addition & 6 deletions qt/aqt/browser/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,6 @@ def setupEditor(self) -> None:

def add_preview_button(editor: Editor) -> None:
editor._links["preview"] = lambda _editor: self.onTogglePreview()
editor.web.eval(
"noteEditorPromise.then(noteEditor => noteEditor.toolbar.notetypeButtons.appendButton({ component: editorToolbar.PreviewButton, id: 'preview' }));",
)

gui_hooks.editor_did_init.append(add_preview_button)
self.editor = aqt.editor.Editor(
Expand Down Expand Up @@ -633,9 +630,7 @@ def _renderPreview(self) -> None:

def toggle_preview_button_state(self, active: bool) -> None:
if self.editor.web:
self.editor.web.eval(
f"editorToolbar.togglePreviewButtonState({json.dumps(active)});"
)
self.editor.web.eval(f"togglePreviewButtonState({json.dumps(active)});")

def _cleanup_preview(self) -> None:
if self._previewer:
Expand Down
28 changes: 16 additions & 12 deletions qt/aqt/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def setupWeb(self) -> None:
righttopbtns_defs = ", ".join([json.dumps(button) for button in righttopbtns])
righttopbtns_js = (
f"""
uiPromise.then(noteEditor => noteEditor.toolbar.toolbar.appendGroup({{
require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].toolbar.toolbar.append({{
component: editorToolbar.AddonButtons,
id: "addons",
props: {{ buttons: [ {righttopbtns_defs} ] }},
Expand Down Expand Up @@ -525,7 +525,9 @@ def oncallback(arg: Any) -> None:
js += " setSticky(%s);" % json.dumps(sticky)

js = gui_hooks.editor_will_load_note(js, self.note, self)
self.web.evalWithCallback(f"uiPromise.then(() => {{ {js} }})", oncallback)
self.web.evalWithCallback(
f'require("anki/ui").loaded.then(() => {{ {js} }})', oncallback
)

def _save_current_note(self) -> None:
"Call after note is updated with data from webview."
Expand Down Expand Up @@ -579,8 +581,12 @@ def _update_duplicate_display(self, result: NoteFieldsCheckResult.V) -> None:
elif result == NoteFieldsCheckResult.FIELD_NOT_CLOZE:
cloze_hint = tr.adding_cloze_outside_cloze_field()

self.web.eval(f"uiPromise.then(() => setBackgrounds({json.dumps(cols)}));")
self.web.eval(f"uiPromise.then(() => setClozeHint({json.dumps(cloze_hint)}));")
self.web.eval(
'require("anki/ui").loaded.then(() => {'
f"setBackgrounds({json.dumps(cols)});\n"
f"setClozeHint({json.dumps(cloze_hint)});\n"
"}); "
)

def showDupes(self) -> None:
aqt.dialogs.open(
Expand Down Expand Up @@ -1353,14 +1359,12 @@ def reverse_url_quoting(txt: str, editor: Editor) -> str:


def set_cloze_button(editor: Editor) -> None:
if editor.note.note_type()["type"] == MODEL_CLOZE:
editor.web.eval(
'uiPromise.then((noteEditor) => noteEditor.toolbar.templateButtons.showButton("cloze")); '
)
else:
editor.web.eval(
'uiPromise.then((noteEditor) => noteEditor.toolbar.templateButtons.hideButton("cloze")); '
)
action = "show" if editor.note.note_type()["type"] == MODEL_CLOZE else "hide"
editor.web.eval(
'require("anki/ui").loaded.then(() =>'
f'require("anki/NoteEditor").instances[0].toolbar.templateButtons.{action}("cloze")'
"); "
)


gui_hooks.editor_did_load_note.append(set_cloze_button)
57 changes: 20 additions & 37 deletions ts/change-notetype/NotetypeSelector.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { ChangeNotetypeState } from "./lib";
import StickyContainer from "../components/StickyContainer.svelte";
import ButtonToolbar from "../components/ButtonToolbar.svelte";
import Item from "../components/Item.svelte";
import ButtonGroup from "../components/ButtonGroup.svelte";
import ButtonGroupItem from "../components/ButtonGroupItem.svelte";
import LabelButton from "../components/LabelButton.svelte";
import Badge from "../components/Badge.svelte";
import { arrowRightIcon, arrowLeftIcon } from "./icons";
Expand All @@ -33,41 +31,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--sticky-borders="0 0 1px"
>
<ButtonToolbar class="justify-content-between" size={2.3} wrap={false}>
<Item>
<ButtonGroupItem>
<LabelButton disabled={true}>
{$info.oldNotetypeName}
</LabelButton>
</ButtonGroupItem>
</Item>
<Item>
<Badge iconSize={70}>
{#if window.getComputedStyle(document.body).direction == "rtl"}
{@html arrowLeftIcon}
{:else}
{@html arrowRightIcon}
{/if}
</Badge>
</Item>
<Item>
<ButtonGroup class="flex-grow-1">
<ButtonGroupItem>
<SelectButton class="flex-grow-1" on:change={blur}>
{#each $notetypes as entry}
<SelectOption
value={String(entry.idx)}
selected={entry.current}
>
{entry.name}
</SelectOption>
{/each}
</SelectButton>
</ButtonGroupItem>
</ButtonGroup>
</Item>
<LabelButton disabled={true}>
{$info.oldNotetypeName}
</LabelButton>
<Badge iconSize={70}>
{#if window.getComputedStyle(document.body).direction == "rtl"}
{@html arrowLeftIcon}
{:else}
{@html arrowRightIcon}
{/if}
</Badge>
<ButtonGroup class="flex-grow-1">
<SelectButton class="flex-grow-1" on:change={blur}>
{#each $notetypes as entry}
<SelectOption value={String(entry.idx)} selected={entry.current}>
{entry.name}
</SelectOption>
{/each}
</SelectButton>
</ButtonGroup>

<Item>
<SaveButton {state} />
</Item>
<SaveButton {state} />
</ButtonToolbar>
</StickyContainer>
17 changes: 8 additions & 9 deletions ts/change-notetype/SaveButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { getPlatformString } from "../lib/shortcuts";

import ButtonGroup from "../components/ButtonGroup.svelte";
import ButtonGroupItem from "../components/ButtonGroupItem.svelte";
import LabelButton from "../components/LabelButton.svelte";
import Shortcut from "../components/Shortcut.svelte";

Expand All @@ -25,12 +24,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>

<ButtonGroup>
<ButtonGroupItem>
<LabelButton
theme="primary"
tooltip={getPlatformString(keyCombination)}
on:click={save}>{tr.actionsSave()}</LabelButton
>
<Shortcut {keyCombination} on:action={save} />
</ButtonGroupItem>
<LabelButton
theme="primary"
tooltip={getPlatformString(keyCombination)}
on:click={save}
--border-left-radius="5px"
--border-right-radius="5px">{tr.actionsSave()}</LabelButton
>
<Shortcut {keyCombination} on:action={save} />
</ButtonGroup>
1 change: 1 addition & 0 deletions ts/components/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ svelte_check(
"//sass:breakpoints_lib",
"//sass/bootstrap",
"@npm//@types/bootstrap",
"//ts/lib:lib_pkg",
"//ts/sveltelib:sveltelib_pkg",
],
)
9 changes: 1 addition & 8 deletions ts/components/ButtonDropdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let className = "";
export { className as class };

export let api: Record<string, unknown> | undefined = undefined;

setContext(dropdownKey, null);
</script>

<ButtonToolbar
{id}
class="dropdown-menu btn-dropdown-menu {className}"
wrap={false}
{api}
>
<ButtonToolbar {id} class="dropdown-menu btn-dropdown-menu {className}" wrap={false}>
<div on:mousedown|preventDefault|stopPropagation on:click>
<slot />
</div>
Expand Down
101 changes: 1 addition & 100 deletions ts/components/ButtonGroup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,12 @@
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script context="module" lang="ts">
import type { SvelteComponent } from "./registration";
import type { Identifier } from "./identifier";

export interface ButtonGroupAPI {
insertButton(button: SvelteComponent, position: Identifier): void;
appendButton(button: SvelteComponent, position: Identifier): void;
showButton(position: Identifier): void;
hideButton(position: Identifier): void;
toggleButton(position: Identifier): void;
}
</script>

<script lang="ts">
import ButtonGroupItem from "./ButtonGroupItem.svelte";
import { setContext } from "svelte";
import { writable } from "svelte/store";
import { buttonGroupKey } from "./context-keys";
import { insertElement, appendElement } from "./identifier";
import type { ButtonRegistration } from "./buttons";
import { ButtonPosition } from "./buttons";
import { makeInterface } from "./registration";

export let id: string | undefined = undefined;
let className: string = "";
export { className as class };

export let size: number | undefined = undefined;

export let wrap: boolean | undefined = undefined;

$: buttonSize = size ? `--buttons-size: ${size}rem; ` : "";
Expand All @@ -42,86 +19,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}

$: style = buttonSize + buttonWrap;

function makeRegistration(): ButtonRegistration {
const detach = writable(false);
const position = writable(ButtonPosition.Standalone);
return { detach, position };
}

const { registerComponent, items, dynamicItems, getDynamicInterface } =
makeInterface(makeRegistration);

$: for (const [index, item] of $items.entries()) {
item.position.update(() => {
if ($items.length === 1) {
return ButtonPosition.Standalone;
} else if (index === 0) {
return ButtonPosition.InlineStart;
} else if (index === $items.length - 1) {
return ButtonPosition.InlineEnd;
} else {
return ButtonPosition.Center;
}
});
}

setContext(buttonGroupKey, registerComponent);

export let api: Partial<ButtonGroupAPI> | undefined = undefined;
let buttonGroupRef: HTMLDivElement;

function createApi(): void {
const { addComponent, updateRegistration } =
getDynamicInterface(buttonGroupRef);

const insertButton = (button: SvelteComponent, position: Identifier = 0) =>
addComponent(button, (added, parent) =>
insertElement(added, parent, position),
);
const appendButton = (button: SvelteComponent, position: Identifier = -1) =>
addComponent(button, (added, parent) =>
appendElement(added, parent, position),
);

const showButton = (id: Identifier) =>
updateRegistration(({ detach }) => detach.set(false), id);
const hideButton = (id: Identifier) =>
updateRegistration(({ detach }) => detach.set(true), id);
const toggleButton = (id: Identifier) =>
updateRegistration(
({ detach }) => detach.update((old: boolean): boolean => !old),
id,
);

Object.assign(api, {
insertButton,
appendButton,
showButton,
hideButton,
toggleButton,
} as ButtonGroupAPI);
}

$: if (api && buttonGroupRef) {
createApi();
}
</script>

<div
bind:this={buttonGroupRef}
{id}
class="button-group btn-group {className}"
{style}
dir="ltr"
role="group"
>
<div {id} class="button-group btn-group {className}" {style} dir="ltr" role="group">
<slot />
{#each $dynamicItems as item (item[0].id)}
<ButtonGroupItem id={item[0].id} registration={item[1]}>
<svelte:component this={item[0].component} {...item[0].props} />
</ButtonGroupItem>
{/each}
</div>

<style lang="scss">
Expand Down
Loading