Fix two issues that can cause editor fields to behave incorrectly (#2540)

* Fix shortcut not being unregistered when Plain/RichTextBadge is detroyed

This fixes an issue where, if the "Show HTML by default" option of
fields located at the same position in two notetypes have different
values, switching between those notetypes during an editor session
would cause the keyboard shortcut (Ctrl+Shift+X) to no longer function
correctly thereafter.

* Don't restore fields' state if notetype has been modified

This fixes an issue where editor fields behave incorrectly after
opening the 'Fields' dialog and customizing the notetype. An example
of incorrect behavior is that after adding a new field and closing
the dialog, the added field would display both richtext input and
plaintext input, regardless of the options.

* Rename type, variable and function

- Apply suggestions from code review
- Also use optional chaining instead of non-null assertion
This commit is contained in:
Hikaru Y 2023-06-14 08:38:06 +09:00 committed by GitHub
parent f6fdf64c5d
commit 7164723a7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 20 deletions

View file

@ -511,6 +511,7 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
collapsed = [fld["collapsed"] for fld in flds]
plain_texts = [fld.get("plainText", False) for fld in flds]
descriptions = [fld.get("description", "") for fld in flds]
notetype_meta = {"id": self.note.mid, "modTime": self.note.note_type()["mod"]}
self.widget.show()
@ -533,7 +534,7 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
js = f"""
saveSession();
setFields({json.dumps(data)});
setNotetypeId({json.dumps(self.note.mid)});
setNotetypeMeta({json.dumps(notetype_meta)});
setCollapsed({json.dumps(collapsed)});
setPlainTexts({json.dumps(plain_texts)});
setDescriptions({json.dumps(descriptions)});

View file

@ -67,7 +67,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import RichTextInput, { editingInputIsRichText } from "./rich-text-input";
import RichTextBadge from "./RichTextBadge.svelte";
import SymbolsOverlay from "./symbols-overlay";
import type { SessionOptions } from "./types";
import type { NotetypeIdAndModTime, SessionOptions } from "./types";
function quoteFontFamily(fontFamily: string): string {
// generic families (e.g. sans-serif) must not be quoted
@ -82,14 +82,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const sessionOptions: SessionOptions = {};
export function saveSession(): void {
if (notetypeId) {
sessionOptions[notetypeId] = {
if (notetypeMeta) {
sessionOptions[notetypeMeta.id] = {
fieldsCollapsed,
fieldStates: {
richTextsHidden,
plainTextsHidden,
plainTextDefaults,
},
modTimeOfNotetype: notetypeMeta.modTime,
};
}
}
@ -132,7 +133,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let fieldsCollapsed: boolean[] = [];
export function setCollapsed(defaultCollapsed: boolean[]): void {
fieldsCollapsed =
sessionOptions[notetypeId!]?.fieldsCollapsed ?? defaultCollapsed;
sessionOptions[notetypeMeta?.id]?.fieldsCollapsed ?? defaultCollapsed;
}
let richTextsHidden: boolean[] = [];
@ -140,7 +141,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let plainTextDefaults: boolean[] = [];
export function setPlainTexts(defaultPlainTexts: boolean[]): void {
const states = sessionOptions[notetypeId!]?.fieldStates;
const states = sessionOptions[notetypeMeta?.id]?.fieldStates;
if (states) {
richTextsHidden = states.richTextsHidden;
plainTextsHidden = states.plainTextsHidden;
@ -223,9 +224,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
noteId = ntid;
}
let notetypeId: number | null = null;
export function setNotetypeId(mid: number): void {
notetypeId = mid;
let notetypeMeta: NotetypeIdAndModTime;
function setNotetypeMeta({ id, modTime }: NotetypeIdAndModTime): void {
notetypeMeta = { id, modTime };
// Discard the saved state of the fields if the notetype has been modified.
if (sessionOptions[id]?.modTimeOfNotetype !== modTime) {
delete sessionOptions[id];
}
}
let insertSymbols = false;
@ -405,7 +410,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
focusIfField,
getNoteId,
setNoteId,
setNotetypeId,
setNotetypeMeta,
wrap,
setMathjaxEnabled,
setInsertSymbolsEnabled,

View file

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import * as tr from "@tslib/ftl";
import { getPlatformString, registerShortcut } from "@tslib/shortcuts";
import { createEventDispatcher, onMount } from "svelte";
import { createEventDispatcher, onDestroy } from "svelte";
import Badge from "../components/Badge.svelte";
import { context as editorFieldContext } from "./EditorField.svelte";
@ -24,11 +24,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
dispatch("toggle");
}
function shortcut(target: HTMLElement): () => void {
return registerShortcut(toggle, keyCombination, { target });
}
let unregister: ReturnType<typeof registerShortcut> | undefined;
onMount(() => editorField.element.then(shortcut));
editorField.element.then((target) => {
unregister = registerShortcut(toggle, keyCombination, { target });
});
onDestroy(() => unregister?.());
</script>
<span

View file

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts">
import * as tr from "@tslib/ftl";
import { getPlatformString, registerShortcut } from "@tslib/shortcuts";
import { createEventDispatcher, onMount } from "svelte";
import { createEventDispatcher, onDestroy } from "svelte";
import Badge from "../components/Badge.svelte";
import { context as editorFieldContext } from "./EditorField.svelte";
@ -24,11 +24,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
dispatch("toggle");
}
function shortcut(target: HTMLElement): () => void {
return registerShortcut(toggle, keyCombination, { target });
}
let unregister: ReturnType<typeof registerShortcut> | undefined;
onMount(() => editorField.element.then(shortcut));
editorField.element.then((target) => {
unregister = registerShortcut(toggle, keyCombination, { target });
});
onDestroy(() => unregister?.());
</script>
<span

View file

@ -8,8 +8,14 @@ export type EditorOptions = {
plainTextsHidden: boolean[];
plainTextDefaults: boolean[];
};
modTimeOfNotetype: number;
};
export type SessionOptions = {
[key: number]: EditorOptions;
};
export type NotetypeIdAndModTime = {
id: number;
modTime: number;
};