mirror of
https://github.com/ankitects/anki.git
synced 2025-12-14 07:10:59 -05:00
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:
parent
9e147c6335
commit
7ce1c4439a
4 changed files with 89 additions and 0 deletions
|
|
@ -90,6 +90,18 @@ class EditorMode(Enum):
|
||||||
BROWSER = 2
|
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:
|
class Editor:
|
||||||
"""The screen that embeds an editing widget should listen for changes via
|
"""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
|
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
|
self.last_field_index: int | None = None
|
||||||
# current card, for card layout
|
# current card, for card layout
|
||||||
self.card: Card | None = None
|
self.card: Card | None = None
|
||||||
|
self.state: EditorState = EditorState.INITIAL
|
||||||
self._init_links()
|
self._init_links()
|
||||||
self.setupOuter()
|
self.setupOuter()
|
||||||
self.add_webview()
|
self.add_webview()
|
||||||
|
|
@ -474,6 +487,12 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
||||||
collapsed = collapsed_string == "true"
|
collapsed = collapsed_string == "true"
|
||||||
self.setTagsCollapsed(collapsed)
|
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:
|
elif cmd in self._links:
|
||||||
return self._links[cmd](self)
|
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:
|
def mungeHTML(self, txt: str) -> str:
|
||||||
return gui_hooks.editor_will_munge_html(txt, self)
|
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
|
# Setting/unsetting the current note
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1152,6 +1152,16 @@ gui_hooks.webview_did_inject_style_into_page.append(mytest)
|
||||||
or by a right-click paste.
|
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
|
# Tag
|
||||||
###################
|
###################
|
||||||
Hook(name="tag_editor_did_process_key", args=["tag_edit: TagEdit", "evt: QEvent"]),
|
Hook(name="tag_editor_did_process_key", args=["tag_edit: TagEdit", "evt: QEvent"]),
|
||||||
|
|
|
||||||
|
|
@ -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 RichTextInput, { editingInputIsRichText } from "./rich-text-input";
|
||||||
import RichTextBadge from "./RichTextBadge.svelte";
|
import RichTextBadge from "./RichTextBadge.svelte";
|
||||||
import type { NotetypeIdAndModTime, SessionOptions } from "./types";
|
import type { NotetypeIdAndModTime, SessionOptions } from "./types";
|
||||||
|
import { EditorState } from "./types";
|
||||||
|
|
||||||
function quoteFontFamily(fontFamily: string): string {
|
function quoteFontFamily(fontFamily: string): string {
|
||||||
// generic families (e.g. sans-serif) must not be quoted
|
// 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;
|
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(() => {
|
onMount(() => {
|
||||||
function wrap(before: string, after: string): void {
|
function wrap(before: string, after: string): void {
|
||||||
if (!$focusedInput || !editingInputIsRichText($focusedInput)) {
|
if (!$focusedInput || !editingInputIsRichText($focusedInput)) {
|
||||||
|
|
@ -537,6 +576,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
...oldEditorAdapter,
|
...oldEditorAdapter,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
editorState = getEditorState(
|
||||||
|
$ioMaskEditorVisible,
|
||||||
|
isImageOcclusion,
|
||||||
|
isIOImageLoaded,
|
||||||
|
imageOcclusionMode,
|
||||||
|
);
|
||||||
|
|
||||||
document.addEventListener("visibilitychange", saveOnPageHide);
|
document.addEventListener("visibilitychange", saveOnPageHide);
|
||||||
return () => document.removeEventListener("visibilitychange", saveOnPageHide);
|
return () => document.removeEventListener("visibilitychange", saveOnPageHide);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,11 @@ export type NotetypeIdAndModTime = {
|
||||||
id: number;
|
id: number;
|
||||||
modTime: number;
|
modTime: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum EditorState {
|
||||||
|
Initial = -1,
|
||||||
|
Fields = 0,
|
||||||
|
ImageOcclusionPicker = 1,
|
||||||
|
ImageOcclusionMasks = 2,
|
||||||
|
ImageOcclusionFields = 3,
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue