diff --git a/ftl/core/editing.ftl b/ftl/core/editing.ftl index df5d391db..6e4d9086a 100644 --- a/ftl/core/editing.ftl +++ b/ftl/core/editing.ftl @@ -15,6 +15,7 @@ editing-customize-card-templates = Customize Card Templates editing-customize-fields = Customize Fields editing-cut = Cut editing-double-click-image = double-click image +editing-double-click-to-expand = (double-click to expand) editing-edit-current = Edit Current editing-edit-html = Edit HTML editing-fields = Fields @@ -38,6 +39,7 @@ editing-outdent = Decrease indent editing-paste = Paste editing-record-audio = Record audio editing-remove-formatting = Remove formatting +editing-restore-original-size = Restore original size editing-select-remove-formatting = Select formatting to remove editing-show-duplicates = Show Duplicates editing-subscript = Subscript diff --git a/ts/editable/ResizableImage.svelte b/ts/editable/ResizableImage.svelte new file mode 100644 index 000000000..36b06871b --- /dev/null +++ b/ts/editable/ResizableImage.svelte @@ -0,0 +1,11 @@ + + diff --git a/ts/editable/index.ts b/ts/editable/index.ts index 8fa7331d7..f8fa11f71 100644 --- a/ts/editable/index.ts +++ b/ts/editable/index.ts @@ -5,3 +5,4 @@ import "./editable-base.css"; /* only imported for the CSS */ import "./ContentEditable.svelte"; import "./Mathjax.svelte"; +import "./ResizableImage.svelte"; diff --git a/ts/editor/HandleLabel.svelte b/ts/editor/HandleLabel.svelte index 4be58bb74..5b023c69a 100644 --- a/ts/editor/HandleLabel.svelte +++ b/ts/editor/HandleLabel.svelte @@ -4,53 +4,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> -
+
diff --git a/ts/editor/NoteEditor.svelte b/ts/editor/NoteEditor.svelte index 754628b29..b58d740c6 100644 --- a/ts/editor/NoteEditor.svelte +++ b/ts/editor/NoteEditor.svelte @@ -339,7 +339,7 @@ the AddCards dialog) should be implemented in the user of this component. }} bind:this={richTextInputs[index]} > - + diff --git a/ts/editor/editor-toolbar/BoldButton.svelte b/ts/editor/editor-toolbar/BoldButton.svelte index edd07a307..d1b0f51e7 100644 --- a/ts/editor/editor-toolbar/BoldButton.svelte +++ b/ts/editor/editor-toolbar/BoldButton.svelte @@ -9,9 +9,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import type { MatchType } from "../../domlib/surround"; import * as tr from "../../lib/ftl"; import { getPlatformString } from "../../lib/shortcuts"; + import { removeStyleProperties } from "../../lib/styling"; import { context as noteEditorContext } from "../NoteEditor.svelte"; import { editingInputIsRichText } from "../rich-text-input"; - import { removeEmptyStyle, Surrounder } from "../surround"; + import { Surrounder } from "../surround"; import { context as editorToolbarContext } from "./EditorToolbar.svelte"; import { boldIcon } from "./icons"; @@ -25,9 +26,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html const fontWeight = element.style.fontWeight; if (fontWeight === "bold" || Number(fontWeight) >= 400) { return match.clear((): void => { - element.style.removeProperty("font-weight"); - - if (removeEmptyStyle(element) && element.className.length === 0) { + if ( + removeStyleProperties(element, "font-weight") && + element.className.length === 0 + ) { match.remove(); } }); diff --git a/ts/editor/editor-toolbar/HighlightColorButton.svelte b/ts/editor/editor-toolbar/HighlightColorButton.svelte index f1313d54e..d6514a043 100644 --- a/ts/editor/editor-toolbar/HighlightColorButton.svelte +++ b/ts/editor/editor-toolbar/HighlightColorButton.svelte @@ -11,9 +11,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html } from "../../domlib/surround"; import { bridgeCommand } from "../../lib/bridgecommand"; import * as tr from "../../lib/ftl"; + import { removeStyleProperties } from "../../lib/styling"; import { context as noteEditorContext } from "../NoteEditor.svelte"; import { editingInputIsRichText } from "../rich-text-input"; - import { removeEmptyStyle, Surrounder } from "../surround"; + import { Surrounder } from "../surround"; import ColorPicker from "./ColorPicker.svelte"; import type { RemoveFormat } from "./EditorToolbar.svelte"; import { context as editorToolbarContext } from "./EditorToolbar.svelte"; @@ -45,9 +46,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html match.setCache(value); match.clear((): void => { - element.style.removeProperty("background-color"); - - if (removeEmptyStyle(element) && element.className.length === 0) { + if ( + removeStyleProperties(element, "background-color") && + element.className.length === 0 + ) { match.remove(); } }); diff --git a/ts/editor/editor-toolbar/ItalicButton.svelte b/ts/editor/editor-toolbar/ItalicButton.svelte index a4d9fd7d8..965453292 100644 --- a/ts/editor/editor-toolbar/ItalicButton.svelte +++ b/ts/editor/editor-toolbar/ItalicButton.svelte @@ -9,9 +9,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import type { MatchType } from "../../domlib/surround"; import * as tr from "../../lib/ftl"; import { getPlatformString } from "../../lib/shortcuts"; + import { removeStyleProperties } from "../../lib/styling"; import { context as noteEditorContext } from "../NoteEditor.svelte"; import { editingInputIsRichText } from "../rich-text-input"; - import { removeEmptyStyle, Surrounder } from "../surround"; + import { Surrounder } from "../surround"; import { context as editorToolbarContext } from "./EditorToolbar.svelte"; import { italicIcon } from "./icons"; @@ -24,9 +25,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html if (["italic", "oblique"].includes(element.style.fontStyle)) { return match.clear((): void => { - element.style.removeProperty("font-style"); - - if (removeEmptyStyle(element) && element.className.length === 0) { + if ( + removeStyleProperties(element, "font-style") && + element.className.length === 0 + ) { return match.remove(); } }); diff --git a/ts/editor/editor-toolbar/SubscriptButton.svelte b/ts/editor/editor-toolbar/SubscriptButton.svelte index df1316a20..5fdb113b4 100644 --- a/ts/editor/editor-toolbar/SubscriptButton.svelte +++ b/ts/editor/editor-toolbar/SubscriptButton.svelte @@ -4,7 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> - {#await sheetPromise then sheet} - { - updateSizesWithDimensions(); - dropdownObject.update(); - }} - let:toggleActualSize - let:active + image={activeImage} + on:mount={(event) => createDropdown(event.detail.selection)} > - {#if activeImage} - createDropdown(event.detail.selection)} - > - + { + if (shrinkingDisabled) { + return; + } + toggleActualSize(); + updateSizesWithDimensions(); + dropdownObject.update(); + }} + /> - - {actualWidth}×{actualHeight} - {#if customDimensions} - (Original: {naturalWidth}×{naturalHeight}) - {/if} - + + {#if isSizeConstrained} + {tr.editingDoubleClickToExpand()} + {:else} + {actualWidth}×{actualHeight} + {#if customDimensions} + (Original: {naturalWidth}×{naturalHeight}) + {/if} + {/if} + - { - if (active) { - setPointerCapture(event); - } - }} - on:pointermove={(event) => { - resize(event); - updateSizesWithDimensions(); - dropdownObject.update(); - }} - /> - - - - - - {/if} - - {/await} + { + if (!isSizeConstrained) { + setPointerCapture(event); + } + }} + on:pointermove={(event) => { + resize(event); + updateSizesWithDimensions(); + dropdownObject.update(); + }} + /> + + + + { + toggleActualSize(); + updateSizesWithDimensions(); + dropdownObject.update(); + }} + on:imageclear={() => { + clearActualSize(); + updateSizesWithDimensions(); + dropdownObject.update(); + }} + /> + + {/if} diff --git a/ts/editor/image-overlay/SizeSelect.svelte b/ts/editor/image-overlay/SizeSelect.svelte index 9afacc1ff..022b3aad5 100644 --- a/ts/editor/image-overlay/SizeSelect.svelte +++ b/ts/editor/image-overlay/SizeSelect.svelte @@ -3,29 +3,38 @@ Copyright: Ankitects Pty Ltd and contributors License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> {@html icon} dispatch("imagetoggle")} + --border-left-radius="5px">{@html icon} + + dispatch("imageclear")} + --border-right-radius="5px">{@html sizeClear} diff --git a/ts/editor/image-overlay/WithImageConstrained.svelte b/ts/editor/image-overlay/WithImageConstrained.svelte deleted file mode 100644 index d0d6cb935..000000000 --- a/ts/editor/image-overlay/WithImageConstrained.svelte +++ /dev/null @@ -1,203 +0,0 @@ - - - -{#if activeImage} - -{/if} diff --git a/ts/editor/image-overlay/icons.ts b/ts/editor/image-overlay/icons.ts index 9fd979fe7..fa1019d56 100644 --- a/ts/editor/image-overlay/icons.ts +++ b/ts/editor/image-overlay/icons.ts @@ -4,5 +4,6 @@ export { default as floatLeftIcon } from "@mdi/svg/svg/format-float-left.svg"; export { default as floatNoneIcon } from "@mdi/svg/svg/format-float-none.svg"; export { default as floatRightIcon } from "@mdi/svg/svg/format-float-right.svg"; +export { default as sizeClear } from "@mdi/svg/svg/image-remove.svg"; export { default as sizeActual } from "@mdi/svg/svg/image-size-select-actual.svg"; export { default as sizeMinimized } from "@mdi/svg/svg/image-size-select-large.svg"; diff --git a/ts/editor/surround.ts b/ts/editor/surround.ts index e09aeffd3..9044dde34 100644 --- a/ts/editor/surround.ts +++ b/ts/editor/surround.ts @@ -243,19 +243,6 @@ export class Surrounder { } } -/** - * @returns True, if element has no style attribute (anymore). - */ -export function removeEmptyStyle(element: HTMLElement | SVGElement): boolean { - if (element.style.cssText.length === 0) { - element.removeAttribute("style"); - // Calling `.hasAttribute` right after `.removeAttribute` might return true. - return true; - } - - return false; -} - registerPackage("anki/surround", { Surrounder, }); diff --git a/ts/lib/styling.ts b/ts/lib/styling.ts new file mode 100644 index 000000000..cac1df4c8 --- /dev/null +++ b/ts/lib/styling.ts @@ -0,0 +1,31 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +/** + * @returns True, if element has no style attribute (anymore). + */ +function removeEmptyStyle(element: HTMLElement | SVGElement): boolean { + if (element.style.cssText.length === 0) { + element.removeAttribute("style"); + // Calling `.hasAttribute` right after `.removeAttribute` might return true. + return true; + } + + return false; +} + +/** + * Will remove the style attribute, if all properties were removed. + * + * @returns True, if element has no style attributes anymore + */ +export function removeStyleProperties( + element: HTMLElement | SVGElement, + ...props: string[] +): boolean { + for (const prop of props) { + element.style.removeProperty(prop); + } + + return removeEmptyStyle(element); +}