mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Add extra button group for cloze commands (#1756)
* First attempt at adding a directory for icons under //ts * Fix image import * Fix import order * Add cloze button group * Fix issue with toolbar.toolbar dynamically slottable * Change tooltip for repeating cloze deletion * Fix repeat cloze button not working on macOS (dae)
This commit is contained in:
parent
7f737b60c6
commit
5b1fcccf33
12 changed files with 130 additions and 85 deletions
|
@ -9,6 +9,7 @@ editing-cards = Cards
|
||||||
editing-center = Center
|
editing-center = Center
|
||||||
editing-change-color = Change color
|
editing-change-color = Change color
|
||||||
editing-cloze-deletion = Cloze deletion
|
editing-cloze-deletion = Cloze deletion
|
||||||
|
editing-cloze-deletion-repeat = Repeat cloze deletion
|
||||||
editing-couldnt-record-audio-have-you-installed = Couldn't record audio. Have you installed 'lame'?
|
editing-couldnt-record-audio-have-you-installed = Couldn't record audio. Have you installed 'lame'?
|
||||||
editing-customize-card-templates = Customize Card Templates
|
editing-customize-card-templates = Customize Card Templates
|
||||||
editing-customize-fields = Customize Fields
|
editing-customize-fields = Customize Fields
|
||||||
|
|
|
@ -1387,7 +1387,7 @@ def set_cloze_button(editor: Editor) -> None:
|
||||||
action = "show" if editor.note.note_type()["type"] == MODEL_CLOZE else "hide"
|
action = "show" if editor.note.note_type()["type"] == MODEL_CLOZE else "hide"
|
||||||
editor.web.eval(
|
editor.web.eval(
|
||||||
'require("anki/ui").loaded.then(() =>'
|
'require("anki/ui").loaded.then(() =>'
|
||||||
f'require("anki/NoteEditor").instances[0].toolbar.templateButtons.{action}("cloze")'
|
f'require("anki/NoteEditor").instances[0].toolbar.toolbar.{action}("cloze")'
|
||||||
"); "
|
"); "
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -35,3 +35,11 @@ alias(
|
||||||
name = "node",
|
name = "node",
|
||||||
actual = "@nodejs//:node",
|
actual = "@nodejs//:node",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "ts",
|
||||||
|
srcs = [
|
||||||
|
"//ts/icons",
|
||||||
|
],
|
||||||
|
visibility = ["//ts:__subpackages__"],
|
||||||
|
)
|
||||||
|
|
|
@ -47,6 +47,7 @@ _esbuild_deps = [
|
||||||
"//sass:button_mixins_lib",
|
"//sass:button_mixins_lib",
|
||||||
"@npm//@mdi",
|
"@npm//@mdi",
|
||||||
"@npm//bootstrap-icons",
|
"@npm//bootstrap-icons",
|
||||||
|
"//ts/icons",
|
||||||
"@npm//protobufjs",
|
"@npm//protobufjs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
} from "../../components/ButtonGroupItem.svelte";
|
} from "../../components/ButtonGroupItem.svelte";
|
||||||
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte";
|
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte";
|
||||||
import IconButton from "../../components/IconButton.svelte";
|
import IconButton from "../../components/IconButton.svelte";
|
||||||
import Item from "../../components/Item.svelte";
|
|
||||||
import Shortcut from "../../components/Shortcut.svelte";
|
import Shortcut from "../../components/Shortcut.svelte";
|
||||||
import WithDropdown from "../../components/WithDropdown.svelte";
|
import WithDropdown from "../../components/WithDropdown.svelte";
|
||||||
import { getListItem } from "../../lib/dom";
|
import { getListItem } from "../../lib/dom";
|
||||||
|
@ -92,73 +91,69 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<ButtonDropdown>
|
<ButtonDropdown>
|
||||||
<Item id="justify">
|
<ButtonGroup>
|
||||||
<ButtonGroup>
|
<CommandIconButton
|
||||||
<CommandIconButton
|
key="justifyLeft"
|
||||||
key="justifyLeft"
|
tooltip={tr.editingAlignLeft()}
|
||||||
tooltip={tr.editingAlignLeft()}
|
--border-left-radius="5px"
|
||||||
--border-left-radius="5px"
|
--border-right-radius="0px"
|
||||||
--border-right-radius="0px"
|
>{@html justifyLeftIcon}</CommandIconButton
|
||||||
>{@html justifyLeftIcon}</CommandIconButton
|
>
|
||||||
>
|
|
||||||
|
|
||||||
<CommandIconButton
|
<CommandIconButton
|
||||||
key="justifyCenter"
|
key="justifyCenter"
|
||||||
tooltip={tr.editingCenter()}
|
tooltip={tr.editingCenter()}
|
||||||
>{@html justifyCenterIcon}</CommandIconButton
|
>{@html justifyCenterIcon}</CommandIconButton
|
||||||
>
|
>
|
||||||
|
|
||||||
<CommandIconButton
|
<CommandIconButton
|
||||||
key="justifyRight"
|
key="justifyRight"
|
||||||
tooltip={tr.editingAlignRight()}
|
tooltip={tr.editingAlignRight()}
|
||||||
>{@html justifyRightIcon}</CommandIconButton
|
>{@html justifyRightIcon}</CommandIconButton
|
||||||
>
|
>
|
||||||
|
|
||||||
<CommandIconButton
|
<CommandIconButton
|
||||||
key="justifyFull"
|
key="justifyFull"
|
||||||
tooltip={tr.editingJustify()}
|
tooltip={tr.editingJustify()}
|
||||||
--border-right-radius="5px"
|
--border-right-radius="5px"
|
||||||
>{@html justifyFullIcon}</CommandIconButton
|
>{@html justifyFullIcon}</CommandIconButton
|
||||||
>
|
>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</Item>
|
|
||||||
|
|
||||||
<Item id="indentation">
|
<ButtonGroup>
|
||||||
<ButtonGroup>
|
<IconButton
|
||||||
<IconButton
|
tooltip="{tr.editingOutdent()} ({getPlatformString(
|
||||||
tooltip="{tr.editingOutdent()} ({getPlatformString(
|
outdentKeyCombination,
|
||||||
outdentKeyCombination,
|
)})"
|
||||||
)})"
|
{disabled}
|
||||||
{disabled}
|
on:click={outdentListItem}
|
||||||
on:click={outdentListItem}
|
--border-left-radius="5px"
|
||||||
--border-left-radius="5px"
|
--border-right-radius="0px"
|
||||||
--border-right-radius="0px"
|
>
|
||||||
>
|
{@html outdentIcon}
|
||||||
{@html outdentIcon}
|
</IconButton>
|
||||||
</IconButton>
|
|
||||||
|
|
||||||
<Shortcut
|
<Shortcut
|
||||||
keyCombination={outdentKeyCombination}
|
keyCombination={outdentKeyCombination}
|
||||||
on:action={outdentListItem}
|
on:action={outdentListItem}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
tooltip="{tr.editingIndent()} ({getPlatformString(
|
tooltip="{tr.editingIndent()} ({getPlatformString(
|
||||||
indentKeyCombination,
|
indentKeyCombination,
|
||||||
)})"
|
)})"
|
||||||
{disabled}
|
{disabled}
|
||||||
on:click={indentListItem}
|
on:click={indentListItem}
|
||||||
--border-right-radius="5px"
|
--border-right-radius="5px"
|
||||||
>
|
>
|
||||||
{@html indentIcon}
|
{@html indentIcon}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<Shortcut
|
<Shortcut
|
||||||
keyCombination={indentKeyCombination}
|
keyCombination={indentKeyCombination}
|
||||||
on:action={indentListItem}
|
on:action={indentListItem}
|
||||||
/>
|
/>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</Item>
|
|
||||||
</ButtonDropdown>
|
</ButtonDropdown>
|
||||||
</WithDropdown>
|
</WithDropdown>
|
||||||
</ButtonGroupItem>
|
</ButtonGroupItem>
|
||||||
|
|
|
@ -5,6 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
|
import ButtonGroup from "../../components/ButtonGroup.svelte";
|
||||||
import IconButton from "../../components/IconButton.svelte";
|
import IconButton from "../../components/IconButton.svelte";
|
||||||
import Shortcut from "../../components/Shortcut.svelte";
|
import Shortcut from "../../components/Shortcut.svelte";
|
||||||
import * as tr from "../../lib/ftl";
|
import * as tr from "../../lib/ftl";
|
||||||
|
@ -14,7 +15,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import { context as noteEditorContext } from "../NoteEditor.svelte";
|
import { context as noteEditorContext } from "../NoteEditor.svelte";
|
||||||
import type { RichTextInputAPI } from "../rich-text-input";
|
import type { RichTextInputAPI } from "../rich-text-input";
|
||||||
import { editingInputIsRichText } from "../rich-text-input";
|
import { editingInputIsRichText } from "../rich-text-input";
|
||||||
import { ellipseIcon } from "./icons";
|
import { clozeIcon, incrementClozeIcon } from "./icons";
|
||||||
|
|
||||||
const { focusedInput, fields } = noteEditorContext.get();
|
const { focusedInput, fields } = noteEditorContext.get();
|
||||||
|
|
||||||
|
@ -49,27 +50,54 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
$: richTextAPI = $focusedInput as RichTextInputAPI;
|
$: richTextAPI = $focusedInput as RichTextInputAPI;
|
||||||
|
|
||||||
async function onCloze(event: KeyboardEvent | MouseEvent): Promise<void> {
|
async function onIncrementCloze(): Promise<void> {
|
||||||
const highestCloze = getCurrentHighestCloze(!event.getModifierState("Alt"));
|
|
||||||
const richText = await richTextAPI.element;
|
const richText = await richTextAPI.element;
|
||||||
|
|
||||||
|
const highestCloze = getCurrentHighestCloze(true);
|
||||||
|
wrapInternal(richText, `{{c${highestCloze}::`, "}}", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onSameCloze(): Promise<void> {
|
||||||
|
const richText = await richTextAPI.element;
|
||||||
|
|
||||||
|
const highestCloze = getCurrentHighestCloze(false);
|
||||||
wrapInternal(richText, `{{c${highestCloze}::`, "}}", false);
|
wrapInternal(richText, `{{c${highestCloze}::`, "}}", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
$: disabled = !editingInputIsRichText($focusedInput);
|
$: disabled = !editingInputIsRichText($focusedInput);
|
||||||
|
|
||||||
const keyCombination = "Control+Alt?+Shift+C";
|
const incrementKeyCombination = "Control+Shift+C";
|
||||||
|
const sameKeyCombination = "Control+Alt+Shift+C";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<IconButton
|
<ButtonGroup>
|
||||||
tooltip="{tr.editingClozeDeletion()} {getPlatformString(keyCombination)}"
|
<IconButton
|
||||||
{disabled}
|
tooltip="{tr.editingClozeDeletion()} {getPlatformString(
|
||||||
on:click={onCloze}
|
incrementKeyCombination,
|
||||||
>
|
)}"
|
||||||
{@html ellipseIcon}
|
{disabled}
|
||||||
</IconButton>
|
on:click={onIncrementCloze}
|
||||||
|
--border-left-radius="5px"
|
||||||
|
>
|
||||||
|
{@html incrementClozeIcon}
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
<Shortcut
|
<Shortcut
|
||||||
{keyCombination}
|
keyCombination={incrementKeyCombination}
|
||||||
{event}
|
{event}
|
||||||
on:action={(event) => onCloze(event.detail.originalEvent)}
|
on:action={onIncrementCloze}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
tooltip="{tr.editingClozeDeletionRepeat()} {getPlatformString(
|
||||||
|
sameKeyCombination,
|
||||||
|
)}"
|
||||||
|
{disabled}
|
||||||
|
on:click={onSameCloze}
|
||||||
|
--border-right-radius="5px"
|
||||||
|
>
|
||||||
|
{@html clozeIcon}
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<Shortcut keyCombination={sameKeyCombination} {event} on:action={onSameCloze} />
|
||||||
|
</ButtonGroup>
|
|
@ -56,6 +56,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import Item from "../../components/Item.svelte";
|
import Item from "../../components/Item.svelte";
|
||||||
import StickyContainer from "../../components/StickyContainer.svelte";
|
import StickyContainer from "../../components/StickyContainer.svelte";
|
||||||
import BlockButtons from "./BlockButtons.svelte";
|
import BlockButtons from "./BlockButtons.svelte";
|
||||||
|
import ClozeButtons from "./ClozeButtons.svelte";
|
||||||
import InlineButtons from "./InlineButtons.svelte";
|
import InlineButtons from "./InlineButtons.svelte";
|
||||||
import NotetypeButtons from "./NotetypeButtons.svelte";
|
import NotetypeButtons from "./NotetypeButtons.svelte";
|
||||||
import TemplateButtons from "./TemplateButtons.svelte";
|
import TemplateButtons from "./TemplateButtons.svelte";
|
||||||
|
@ -105,6 +106,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<Item id="template">
|
<Item id="template">
|
||||||
<TemplateButtons api={templateButtons} />
|
<TemplateButtons api={templateButtons} />
|
||||||
</Item>
|
</Item>
|
||||||
|
|
||||||
|
<Item id="cloze">
|
||||||
|
<ClozeButtons />
|
||||||
|
</Item>
|
||||||
</DynamicallySlottable>
|
</DynamicallySlottable>
|
||||||
</ButtonToolbar>
|
</ButtonToolbar>
|
||||||
</StickyContainer>
|
</StickyContainer>
|
||||||
|
|
|
@ -20,7 +20,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import { context } from "../NoteEditor.svelte";
|
import { context } from "../NoteEditor.svelte";
|
||||||
import { setFormat } from "../old-editor-adapter";
|
import { setFormat } from "../old-editor-adapter";
|
||||||
import { editingInputIsRichText } from "../rich-text-input";
|
import { editingInputIsRichText } from "../rich-text-input";
|
||||||
import ClozeButton from "./ClozeButton.svelte";
|
|
||||||
import { micIcon, paperclipIcon } from "./icons";
|
import { micIcon, paperclipIcon } from "./icons";
|
||||||
import LatexButton from "./LatexButton.svelte";
|
import LatexButton from "./LatexButton.svelte";
|
||||||
|
|
||||||
|
@ -116,10 +115,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
/>
|
/>
|
||||||
</ButtonGroupItem>
|
</ButtonGroupItem>
|
||||||
|
|
||||||
<ButtonGroupItem id="cloze">
|
|
||||||
<ClozeButton />
|
|
||||||
</ButtonGroupItem>
|
|
||||||
|
|
||||||
<ButtonGroupItem>
|
<ButtonGroupItem>
|
||||||
<LatexButton />
|
<LatexButton />
|
||||||
</ButtonGroupItem>
|
</ButtonGroupItem>
|
||||||
|
|
|
@ -24,7 +24,8 @@ export { default as underlineIcon } from "bootstrap-icons/icons/type-underline.s
|
||||||
export const arrowIcon =
|
export const arrowIcon =
|
||||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="transparent" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2 5l6 6 6-6"/></svg>';
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="transparent" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2 5l6 6 6-6"/></svg>';
|
||||||
|
|
||||||
export { default as ellipseIcon } from "@mdi/svg/svg/contain.svg";
|
export { default as incrementClozeIcon } from "../../icons/contain-plus.svg";
|
||||||
|
export { default as clozeIcon } from "@mdi/svg/svg/contain.svg";
|
||||||
export { default as functionIcon } from "@mdi/svg/svg/function-variant.svg";
|
export { default as functionIcon } from "@mdi/svg/svg/function-variant.svg";
|
||||||
export { default as paperclipIcon } from "@mdi/svg/svg/paperclip.svg";
|
export { default as paperclipIcon } from "@mdi/svg/svg/paperclip.svg";
|
||||||
export { default as micIcon } from "bootstrap-icons/icons/mic.svg";
|
export { default as micIcon } from "bootstrap-icons/icons/mic.svg";
|
||||||
|
|
9
ts/icons/BUILD.bazel
Normal file
9
ts/icons/BUILD.bazel
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
|
||||||
|
|
||||||
|
js_library(
|
||||||
|
name = "icons",
|
||||||
|
srcs = glob([
|
||||||
|
"*.svg",
|
||||||
|
]),
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
1
ts/icons/contain-plus.svg
Normal file
1
ts/icons/contain-plus.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="mdi-contain" width="24" height="24" viewBox="0 0 24 24"><path d="M1 2h6v2h-4v14h4v2h-6zm5 14v-2h2v2zm4 0v-2h2v2zm4 0v-2h2v.54c-.625.583-.891.887-1.191 1.46zM21 2v11.082c-.68-.11-1.32-.11-2 0v-9.082h-4v-2zm0 13v3h3v2h-3v3h-2v-3h-3v-2h3v-3h2Z" /></svg>
|
After Width: | Height: | Size: 488 B |
|
@ -12,7 +12,8 @@
|
||||||
{ "path": "reviewer" },
|
{ "path": "reviewer" },
|
||||||
{ "path": "lib" },
|
{ "path": "lib" },
|
||||||
{ "path": "domlib" },
|
{ "path": "domlib" },
|
||||||
{ "path": "sveltelib" }
|
{ "path": "sveltelib" },
|
||||||
|
{ "path": "icons" }
|
||||||
],
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
|
|
Loading…
Reference in a new issue