Fix field not restored if active (#1639)

* Fix field not being restored after Undo, if field also has focus

* Execute moveCaretToEnd after undoing a change

- Otherwise the caret might be placed in seemingly random positions

* Fix wording of comments

* Remove autofocus functionality of EditingArea

- instead await a tick in focusField
- We used the autofocus prop for the initial focus setting when opening the
  editor. However it seems that awaiting tick in focusField also does the trick.
This commit is contained in:
Henrik Giesel 2022-02-05 06:58:31 +01:00 committed by GitHub
parent c5280cd056
commit 0c81bbce04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 26 deletions

View file

@ -9,10 +9,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export interface EditingInputAPI { export interface EditingInputAPI {
readonly name: string; readonly name: string;
focus(): void;
refocus(): void;
focusable: boolean; focusable: boolean;
moveCaretToEnd(): void; /**
* The reaction to a user-initiated focus, e.g. by clicking on the
* editor label, or pressing Tab.
*/
focus(): void;
/**
* Behaves similar to a refresh, e.g. sync with content, put the caret
* into a neutral position, and/or clear selections.
*/
refocus(): void;
} }
export interface EditingAreaAPI { export interface EditingAreaAPI {
@ -29,7 +36,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import { onMount, setContext as svelteSetContext } from "svelte"; import { setContext as svelteSetContext } from "svelte";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import { fontFamilyKey, fontSizeKey } from "../lib/context-keys"; import { fontFamilyKey, fontSizeKey } from "../lib/context-keys";
@ -46,7 +53,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
svelteSetContext(fontSizeKey, fontSizeStore); svelteSetContext(fontSizeKey, fontSizeStore);
export let content: Writable<string>; export let content: Writable<string>;
export let autofocus = false;
let editingArea: HTMLElement; let editingArea: HTMLElement;
let focusTrap: FocusTrap; let focusTrap: FocusTrap;
@ -130,12 +136,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}); });
setContextProperty(api); setContextProperty(api);
onMount(() => {
if (autofocus) {
focus();
}
});
</script> </script>
<FocusTrap bind:this={focusTrap} on:focus={focusEditingInputInsteadIfAvailable} /> <FocusTrap bind:this={focusTrap} on:focus={focusEditingInputInsteadIfAvailable} />

View file

@ -44,7 +44,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let content: Writable<string>; export let content: Writable<string>;
export let field: FieldData; export let field: FieldData;
export let autofocus = false;
const directionStore = writable<"ltr" | "rtl">(); const directionStore = writable<"ltr" | "rtl">();
setContext(directionKey, directionStore); setContext(directionKey, directionStore);
@ -88,7 +87,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</LabelContainer> </LabelContainer>
<EditingArea <EditingArea
{content} {content}
{autofocus}
fontFamily={field.fontFamily} fontFamily={field.fontFamily}
fontSize={field.fontSize} fontSize={field.fontSize}
api={editingArea} api={editingArea}

View file

@ -34,7 +34,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount, tick } from "svelte";
import { get, writable } from "svelte/store"; import { get, writable } from "svelte/store";
import Absolute from "../components/Absolute.svelte"; import Absolute from "../components/Absolute.svelte";
@ -125,12 +125,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
plainTextsHidden = fonts.map((_, index) => plainTextsHidden[index] ?? true); plainTextsHidden = fonts.map((_, index) => plainTextsHidden[index] ?? true);
} }
let focusTo: number = 0; export function focusField(index: number | null): void {
export function focusField(n: number): void { tick().then(() => {
if (typeof n === "number") { if (typeof index === "number") {
focusTo = n; if (!(index in fields)) {
fields[focusTo].editingArea?.refocus(); return;
} }
fields[index].editingArea?.refocus();
} else {
$focusedInput?.refocus();
}
});
} }
let textColor: string = "black"; let textColor: string = "black";
@ -298,7 +304,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<EditorField <EditorField
{field} {field}
content={fieldStores[index]} content={fieldStores[index]}
autofocus={index === focusTo}
api={fields[index]} api={fields[index]}
on:focusin={() => { on:focusin={() => {
$focusedField = fields[index]; $focusedField = fields[index];

View file

@ -83,13 +83,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
codeMirror?.editor.focus(); codeMirror?.editor.focus();
} }
function moveCaretToEnd(): void {
codeMirror?.editor.setCursor(codeMirror.editor.lineCount(), 0);
}
function refocus(): void { function refocus(): void {
(codeMirror?.editor as any).display.input.blur(); (codeMirror?.editor as any).display.input.blur();
focus(); focus();
} moveCaretToEnd();
function moveCaretToEnd(): void {
codeMirror?.editor.setCursor(codeMirror.editor.lineCount(), 0);
} }
function toggle(): boolean { function toggle(): boolean {

View file

@ -19,7 +19,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
shadowRoot: Promise<ShadowRoot>; shadowRoot: Promise<ShadowRoot>;
element: Promise<HTMLElement>; element: Promise<HTMLElement>;
moveCaretToEnd(): void; moveCaretToEnd(): void;
refocus(): void;
toggle(): boolean; toggle(): boolean;
preventResubscription(): () => void; preventResubscription(): () => void;
getTriggerOnNextInsert(): Trigger<OnInsertCallback>; getTriggerOnNextInsert(): Trigger<OnInsertCallback>;
@ -196,6 +195,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
richTextPromise.then((richText) => { richTextPromise.then((richText) => {
richText.blur(); richText.blur();
richText.focus(); richText.focus();
moveCaretToEnd();
}); });
}, },
focusable: !hidden, focusable: !hidden,