Propagate editor UI state transitions to add-ons (#2711)

* Propagate editor UI state transitions to add-ons

* Also set initial Python state to EditorState.INITIAL

---------

Co-authored-by: Glutanimate <glutanimate@users.noreply.github.com>
This commit is contained in:
Aristotelis 2023-10-13 00:47:50 +02:00 committed by GitHub
parent 9e147c6335
commit 7ce1c4439a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 0 deletions

View file

@ -90,6 +90,18 @@ class EditorMode(Enum):
BROWSER = 2
class EditorState(Enum):
"""
Current input state of the editing UI.
"""
INITIAL = -1
FIELDS = 0
IO_PICKER = 1
IO_MASKS = 2
IO_FIELDS = 3
class Editor:
"""The screen that embeds an editing widget should listen for changes via
the `operation_did_execute` hook, and call set_note() when the editor needs
@ -124,6 +136,7 @@ class Editor:
self.last_field_index: int | None = None
# current card, for card layout
self.card: Card | None = None
self.state: EditorState = EditorState.INITIAL
self._init_links()
self.setupOuter()
self.add_webview()
@ -474,6 +487,12 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
collapsed = collapsed_string == "true"
self.setTagsCollapsed(collapsed)
elif cmd.startswith("editorState"):
(_, new_state_id, old_state_id) = cmd.split(":", 2)
self.signal_state_change(
EditorState(int(new_state_id)), EditorState(int(old_state_id))
)
elif cmd in self._links:
return self._links[cmd](self)
@ -483,6 +502,12 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
def mungeHTML(self, txt: str) -> str:
return gui_hooks.editor_will_munge_html(txt, self)
def signal_state_change(
self, new_state: EditorState, old_state: EditorState
) -> None:
self.state = new_state
gui_hooks.editor_state_did_change(self, new_state, old_state)
# Setting/unsetting the current note
######################################################################

View file

@ -1152,6 +1152,16 @@ gui_hooks.webview_did_inject_style_into_page.append(mytest)
or by a right-click paste.
""",
),
Hook(
name="editor_state_did_change",
args=[
"editor: aqt.editor.Editor",
"new_state: aqt.editor.EditorState",
"old_state: aqt.editor.EditorState",
],
doc="""Called when the input state of the editor changes, e.g. when
switching to an image occlusion note type.""",
),
# Tag
###################
Hook(name="tag_editor_did_process_key", args=["tag_edit: TagEdit", "evt: QEvent"]),

View file

@ -69,6 +69,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 type { NotetypeIdAndModTime, SessionOptions } from "./types";
import { EditorState } from "./types";
function quoteFontFamily(fontFamily: string): string {
// generic families (e.g. sans-serif) must not be quoted
@ -496,6 +497,44 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
return false;
}
// Signal editor UI state changes to add-ons
let editorState: EditorState = EditorState.Initial;
let lastEditorState: EditorState = editorState;
function getEditorState(
ioMaskEditorVisible: boolean,
isImageOcclusion: boolean,
isIOImageLoaded: boolean,
imageOcclusionMode: IOMode | undefined,
): EditorState {
if (isImageOcclusion && ioMaskEditorVisible && !isIOImageLoaded) {
return EditorState.ImageOcclusionPicker;
} else if (imageOcclusionMode && ioMaskEditorVisible) {
return EditorState.ImageOcclusionMasks;
} else if (!ioMaskEditorVisible && isImageOcclusion) {
return EditorState.ImageOcclusionFields;
}
return EditorState.Fields;
}
function signalEditorState(newState: EditorState) {
tick().then(() => {
globalThis.editorState = newState;
bridgeCommand(`editorState:${newState}:${lastEditorState}`);
lastEditorState = newState;
});
}
$: signalEditorState(editorState);
$: editorState = getEditorState(
$ioMaskEditorVisible,
isImageOcclusion,
isIOImageLoaded,
imageOcclusionMode,
);
onMount(() => {
function wrap(before: string, after: string): void {
if (!$focusedInput || !editingInputIsRichText($focusedInput)) {
@ -537,6 +576,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
...oldEditorAdapter,
});
editorState = getEditorState(
$ioMaskEditorVisible,
isImageOcclusion,
isIOImageLoaded,
imageOcclusionMode,
);
document.addEventListener("visibilitychange", saveOnPageHide);
return () => document.removeEventListener("visibilitychange", saveOnPageHide);
});

View file

@ -19,3 +19,11 @@ export type NotetypeIdAndModTime = {
id: number;
modTime: number;
};
export enum EditorState {
Initial = -1,
Fields = 0,
ImageOcclusionPicker = 1,
ImageOcclusionMasks = 2,
ImageOcclusionFields = 3,
}