From b12476de9a32050225e90410aecc2ac4330c4151 Mon Sep 17 00:00:00 2001 From: Matthias Metelka <62722460+kleinerpirat@users.noreply.github.com> Date: Mon, 27 Feb 2023 07:23:19 +0100 Subject: [PATCH] Simplify NoteEditor by replacing Pane components with Collapsible (#2395) * Remove Pane components and use Collapsible for TagEditor * Update translations * Give TagEditor border and focus outline * Use ScrollArea from #2248 for fields * Refactor ScrollArea * Fix error caused by calling bridgeCommand when it's not available * Make sure tag editor fills whole width of container which is important for the CSV import page. * Update NoteEditor.svelte * Add back removed ftl strings * Fix tests (dae) --- ftl/core/editing.ftl | 2 + qt/aqt/editor.py | 14 +- ts/components/HorizontalResizer.svelte | 149 --------- ts/components/Pane.svelte | 65 ---- ts/components/PaneContent.svelte | 81 ----- ts/components/ScrollArea.svelte | 147 +++++++++ ts/components/VerticalResizer.svelte | 103 ------ ts/editor/CollapseBadge.svelte | 5 +- ts/editor/CollapseLabel.svelte | 29 ++ ts/editor/EditorField.svelte | 2 +- ts/editor/Fields.svelte | 12 +- ts/editor/LabelContainer.svelte | 25 +- ts/editor/NoteEditor.svelte | 414 ++++++++++--------------- ts/tag-editor/TagEditor.svelte | 12 +- 14 files changed, 371 insertions(+), 689 deletions(-) delete mode 100644 ts/components/HorizontalResizer.svelte delete mode 100644 ts/components/Pane.svelte delete mode 100644 ts/components/PaneContent.svelte create mode 100644 ts/components/ScrollArea.svelte delete mode 100644 ts/components/VerticalResizer.svelte create mode 100644 ts/editor/CollapseLabel.svelte diff --git a/ftl/core/editing.ftl b/ftl/core/editing.ftl index f3447f716..89493690a 100644 --- a/ftl/core/editing.ftl +++ b/ftl/core/editing.ftl @@ -56,6 +56,8 @@ editing-to-make-a-cloze-deletion-on = To make a cloze deletion on an existing no editing-toggle-html-editor = Toggle HTML Editor editing-toggle-visual-editor = Toggle Visual Editor editing-toggle-sticky = Toggle sticky +editing-expand = Expand +editing-collapse = Collapse editing-expand-field = Expand field editing-collapse-field = Collapse field editing-underline-text = Underline text diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index d73c04962..0d68fc19b 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -465,6 +465,11 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too if not self.addMode: self._save_current_note() + elif cmd.startswith("setTagsCollapsed"): + (type, collapsed_string) = cmd.split(":", 1) + collapsed = collapsed_string == "true" + self.setTagsCollapsed(collapsed) + elif cmd in self._links: return self._links[cmd](self) @@ -1165,11 +1170,8 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too not self.mw.col.get_config("closeHTMLTags", True), ) - def collapseTags(self) -> None: - aqt.mw.pm.set_tags_collapsed(self.editorMode, True) - - def expandTags(self) -> None: - aqt.mw.pm.set_tags_collapsed(self.editorMode, False) + def setTagsCollapsed(self, collapsed: bool) -> None: + aqt.mw.pm.set_tags_collapsed(self.editorMode, collapsed) # Links from HTML ###################################################################### @@ -1200,8 +1202,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too toggleMathjax=Editor.toggleMathjax, toggleShrinkImages=Editor.toggleShrinkImages, toggleCloseHTMLTags=Editor.toggleCloseHTMLTags, - expandTags=Editor.expandTags, - collapseTags=Editor.collapseTags, ) diff --git a/ts/components/HorizontalResizer.svelte b/ts/components/HorizontalResizer.svelte deleted file mode 100644 index 0a5932f14..000000000 --- a/ts/components/HorizontalResizer.svelte +++ /dev/null @@ -1,149 +0,0 @@ - - - -
- {#if showIndicator} -
- -
- {/if} - -
- {@html horizontalHandle} -
-
- - diff --git a/ts/components/Pane.svelte b/ts/components/Pane.svelte deleted file mode 100644 index 597592b16..000000000 --- a/ts/components/Pane.svelte +++ /dev/null @@ -1,65 +0,0 @@ - - - -
element.offsetWidth} - use:heightAction={(element) => element.offsetHeight} -> - -
- - diff --git a/ts/components/PaneContent.svelte b/ts/components/PaneContent.svelte deleted file mode 100644 index 516e4a85b..000000000 --- a/ts/components/PaneContent.svelte +++ /dev/null @@ -1,81 +0,0 @@ - - - -
- -
- - diff --git a/ts/components/ScrollArea.svelte b/ts/components/ScrollArea.svelte new file mode 100644 index 000000000..a4d2f34da --- /dev/null +++ b/ts/components/ScrollArea.svelte @@ -0,0 +1,147 @@ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + {#if scrollStates.top}
{/if} + {#if scrollStates.bottom}
{/if} + {#if scrollStates.left}
{/if} + {#if scrollStates.right}
{/if} +
+
+ + diff --git a/ts/components/VerticalResizer.svelte b/ts/components/VerticalResizer.svelte deleted file mode 100644 index cc9a5f41c..000000000 --- a/ts/components/VerticalResizer.svelte +++ /dev/null @@ -1,103 +0,0 @@ - - - -
-
- {@html verticalHandle} -
-
- - diff --git a/ts/editor/CollapseBadge.svelte b/ts/editor/CollapseBadge.svelte index 3ca97677c..6bc51b40c 100644 --- a/ts/editor/CollapseBadge.svelte +++ b/ts/editor/CollapseBadge.svelte @@ -7,10 +7,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { chevronDown } from "./icons"; export let collapsed = false; - export let highlighted = false; -
+
{@html chevronDown}
@@ -20,7 +19,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html opacity: 0.4; transition: opacity var(--transition) ease-in-out, transform var(--transition) ease-in; - &.highlighted { + :global(.collapse-label:hover) & { opacity: 1; } &.collapsed { diff --git a/ts/editor/CollapseLabel.svelte b/ts/editor/CollapseLabel.svelte new file mode 100644 index 000000000..051424ba0 --- /dev/null +++ b/ts/editor/CollapseLabel.svelte @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/ts/editor/EditorField.svelte b/ts/editor/EditorField.svelte index 82ca7887e..9238250c0 100644 --- a/ts/editor/EditorField.svelte +++ b/ts/editor/EditorField.svelte @@ -132,7 +132,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html /* make room for thicker focus border */ margin: 1px; - border-radius: 5px; + border-radius: var(--border-radius); border: 1px solid var(--border); @include elevation(1); diff --git a/ts/editor/Fields.svelte b/ts/editor/Fields.svelte index 557d59353..f3c3b94ea 100644 --- a/ts/editor/Fields.svelte +++ b/ts/editor/Fields.svelte @@ -2,13 +2,19 @@ Copyright: Ankitects Pty Ltd and contributors 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 b4d316b2b..b2044b519 100644 --- a/ts/editor/NoteEditor.svelte +++ b/ts/editor/NoteEditor.svelte @@ -47,12 +47,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import Absolute from "../components/Absolute.svelte"; import Badge from "../components/Badge.svelte"; - import HorizontalResizer from "../components/HorizontalResizer.svelte"; - import Pane from "../components/Pane.svelte"; - import PaneContent from "../components/PaneContent.svelte"; - import { ResizablePane } from "../components/types"; import { TagEditor } from "../tag-editor"; - import TagAddButton from "../tag-editor/tag-options-button/TagAddButton.svelte"; import { ChangeTimer } from "./change-timer"; import { clearableArray } from "./destroyable"; import DuplicateLink from "./DuplicateLink.svelte"; @@ -197,9 +192,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html const tagsCollapsed = writable(); export function setTagsCollapsed(collapsed: boolean): void { $tagsCollapsed = collapsed; - if (collapsed) { - lowerResizer.move([tagsPane, fieldsPane], tagsPane.minHeight); - } + } + + function updateTagsCollapsed(collapsed: boolean) { + $tagsCollapsed = collapsed; + bridgeCommand(`setTagsCollapsed:${$tagsCollapsed}`); } let noteId: number | null = null; @@ -312,8 +309,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html } import { wrapInternal } from "@tslib/wrap"; + import Shortcut from "components/Shortcut.svelte"; import { mathjaxConfig } from "../editable/mathjax-element"; + import CollapseLabel from "./CollapseLabel.svelte"; import { refocusInput } from "./helpers"; import * as oldEditorAdapter from "./old-editor-adapter"; @@ -376,39 +375,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html setContextProperty(api); setupLifecycleHooks(api); - let clientHeight: number; - - const fieldsPane = new ResizablePane(); - const tagsPane = new ResizablePane(); - - let lowerResizer: HorizontalResizer; - let tagEditor: TagEditor; - $: tagAmount = $tags.length; - - let snapTags = $tagsCollapsed; - - function collapseTags(): void { - lowerResizer.move([tagsPane, fieldsPane], tagsPane.minHeight); - $tagsCollapsed = snapTags = true; - } - - function expandTags(): void { - lowerResizer.move([tagsPane, fieldsPane], tagsPane.maxHeight); - $tagsCollapsed = snapTags = false; - } - - window.addEventListener("resize", () => snapResizer(snapTags)); - - function snapResizer(collapse: boolean): void { - if (collapse) { - collapseTags(); - bridgeCommand("collapseTags"); - } else { - expandTags(); - bridgeCommand("expandTags"); - } - } -
+
@@ -435,223 +402,166 @@ the AddCards dialog) should be implemented in the user of this component. {/if} - { - fieldsPane.height = e.detail.height; - }} - > - - - {#each fieldsData as field, index} - {@const content = fieldStores[index]} + + {#each fieldsData as field, index} + {@const content = fieldStores[index]} - { - $focusedField = fields[index]; - bridgeCommand(`focus:${index}`); - }} - on:focusout={() => { - $focusedField = null; - bridgeCommand( - `blur:${index}:${getNoteId()}:${transformContentBeforeSave( - get(content), - )}`, - ); - }} - on:mouseenter={() => { - $hoveredField = fields[index]; - }} - on:mouseleave={() => { - $hoveredField = null; - }} - collapsed={fieldsCollapsed[index]} - dupe={cols[index] === "dupe"} - --description-font-size="{field.fontSize}px" - --description-content={`"${field.description}"`} - > - - { - fieldsCollapsed[index] = !fieldsCollapsed[index]; - - const defaultInput = !plainTextDefaults[index] - ? richTextInputs[index] - : plainTextInputs[index]; - - if (!fieldsCollapsed[index]) { - refocusInput(defaultInput.api); - } else if (!plainTextDefaults[index]) { - plainTextsHidden[index] = true; - } else { - richTextsHidden[index] = true; - } - }} - --icon-align="bottom" - > - - - {field.name} - - - - {#if cols[index] === "dupe"} - - {/if} - {#if plainTextDefaults[index]} - { - richTextsHidden[index] = - !richTextsHidden[index]; - - if (!richTextsHidden[index]) { - refocusInput( - richTextInputs[index].api, - ); - } - }} - /> - {:else} - { - plainTextsHidden[index] = - !plainTextsHidden[index]; - - if (!plainTextsHidden[index]) { - refocusInput( - plainTextInputs[index].api, - ); - } - }} - /> - {/if} - - - - - - - { - saveFieldNow(); - $focusedInput = null; - }} - bind:this={richTextInputs[index]} - /> - - - - - { - saveFieldNow(); - $focusedInput = null; - }} - bind:this={plainTextInputs[index]} - /> - - - - {/each} - - - - {#if insertSymbols} - - {/if} - - - - - snapResizer(!$tagsCollapsed)} - on:release={() => { - snapResizer(snapTags); - }} - > -
- { - tagEditor.appendEmptyTag(); + { + $focusedField = fields[index]; + bridgeCommand(`focus:${index}`); }} - keyCombination="Control+Shift+T" + on:focusout={() => { + $focusedField = null; + bridgeCommand( + `blur:${index}:${getNoteId()}:${transformContentBeforeSave( + get(content), + )}`, + ); + }} + on:mouseenter={() => { + $hoveredField = fields[index]; + }} + on:mouseleave={() => { + $hoveredField = null; + }} + collapsed={fieldsCollapsed[index]} + dupe={cols[index] === "dupe"} + --description-font-size="{field.fontSize}px" + --description-content={`"${field.description}"`} > - {@html tagAmount > 0 ? `${tagAmount} ${tr.editingTags()}` : ""} - -
-
+ + { + fieldsCollapsed[index] = !fieldsCollapsed[index]; - { - tagsPane.height = e.detail.height; - if (tagsPane.maxHeight > 0) { - snapTags = tagsPane.height < tagsPane.maxHeight / 2; - } + const defaultInput = !plainTextDefaults[index] + ? richTextInputs[index] + : plainTextInputs[index]; + + if (!fieldsCollapsed[index]) { + refocusInput(defaultInput.api); + } else if (!plainTextDefaults[index]) { + plainTextsHidden[index] = true; + } else { + richTextsHidden[index] = true; + } + }} + --icon-align="bottom" + > + + + {field.name} + + + + {#if cols[index] === "dupe"} + + {/if} + {#if plainTextDefaults[index]} + { + richTextsHidden[index] = + !richTextsHidden[index]; + + if (!richTextsHidden[index]) { + refocusInput(richTextInputs[index].api); + } + }} + /> + {:else} + { + plainTextsHidden[index] = + !plainTextsHidden[index]; + + if (!plainTextsHidden[index]) { + refocusInput(plainTextInputs[index].api); + } + }} + /> + {/if} + + + + + + + { + saveFieldNow(); + $focusedInput = null; + }} + bind:this={richTextInputs[index]} + /> + + + + + { + saveFieldNow(); + $focusedInput = null; + }} + bind:this={plainTextInputs[index]} + /> + + + + {/each} + + + + {#if insertSymbols} + + {/if} + + + { + updateTagsCollapsed(false); }} - --opacity={(() => { - if (!$tagsCollapsed) { - return 1; - } else { - return snapTags ? tagsPane.height / tagsPane.maxHeight : 1; - } - })()} + /> + updateTagsCollapsed(!$tagsCollapsed)} > - - { - expandTags(); - $tagsCollapsed = false; - }} - on:heightChange={(e) => { - tagsPane.maxHeight = e.detail.height; - if (!$tagsCollapsed) { - expandTags(); - } - }} - /> - - + {@html `${tagAmount > 0 ? tagAmount : ""} ${tr.editingTags()}`} + + + +