mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
Move note saving to TS
This commit is contained in:
parent
75bc67608a
commit
1809e793e6
4 changed files with 64 additions and 55 deletions
|
@ -10,6 +10,7 @@ package anki.frontend;
|
|||
import "anki/scheduler.proto";
|
||||
import "anki/generic.proto";
|
||||
import "anki/search.proto";
|
||||
import "anki/notes.proto";
|
||||
|
||||
service FrontendService {
|
||||
// Returns values from the reviewer
|
||||
|
@ -28,7 +29,9 @@ service FrontendService {
|
|||
// Warns python that the deck option web view is ready to receive requests.
|
||||
rpc deckOptionsReady(generic.Empty) returns (generic.Empty);
|
||||
|
||||
// Editor
|
||||
rpc editorReady(generic.Empty) returns (generic.Empty);
|
||||
rpc editorUpdateNote(notes.UpdateNotesRequest) returns (generic.Empty);
|
||||
}
|
||||
|
||||
service BackendFrontendService {}
|
||||
|
|
|
@ -402,24 +402,8 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
|||
|
||||
# focus lost or key/button pressed?
|
||||
if cmd.startswith("blur") or cmd.startswith("key"):
|
||||
(type, ord_str, nid_str, txt) = cmd.split(":", 3)
|
||||
(type, ord_str) = cmd.split(":", 1)
|
||||
ord = int(ord_str)
|
||||
try:
|
||||
nid = int(nid_str)
|
||||
except ValueError:
|
||||
nid = 0
|
||||
if nid != self.note.id:
|
||||
print("ignored late blur")
|
||||
return
|
||||
|
||||
try:
|
||||
self.note.fields[ord] = self.mungeHTML(txt)
|
||||
except IndexError:
|
||||
print("ignored late blur after notetype change")
|
||||
return
|
||||
|
||||
if not self.addMode:
|
||||
self._save_current_note()
|
||||
if type == "blur":
|
||||
self.currentField = None
|
||||
# run any filters
|
||||
|
|
|
@ -608,13 +608,30 @@ def editor_ready() -> bytes:
|
|||
|
||||
def handle_on_main() -> None:
|
||||
window = aqt.mw.app.activeWindow()
|
||||
if isinstance(getattr(window, "editor"), Editor):
|
||||
if window and isinstance(getattr(window, "editor"), Editor):
|
||||
window.editor._set_ready() # type: ignore
|
||||
|
||||
aqt.mw.taskman.run_on_main(handle_on_main)
|
||||
return b""
|
||||
|
||||
|
||||
def editor_update_note() -> bytes:
|
||||
from aqt.editor import Editor
|
||||
|
||||
output = raw_backend_request("update_notes")()
|
||||
response = OpChanges()
|
||||
response.ParseFromString(output)
|
||||
|
||||
def handle_on_main() -> None:
|
||||
window = aqt.mw.app.activeWindow()
|
||||
if window and isinstance(getattr(window, "editor"), Editor):
|
||||
on_op_finished(aqt.mw, response, window.editor) # type: ignore
|
||||
|
||||
aqt.mw.taskman.run_on_main(handle_on_main)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
post_handler_list = [
|
||||
congrats_info,
|
||||
get_deck_configs_for_update,
|
||||
|
@ -631,6 +648,7 @@ post_handler_list = [
|
|||
deck_options_require_close,
|
||||
deck_options_ready,
|
||||
editor_ready,
|
||||
editor_update_note,
|
||||
]
|
||||
|
||||
|
||||
|
@ -647,6 +665,7 @@ exposed_backend_list = [
|
|||
# NotesService
|
||||
"get_field_names",
|
||||
"get_note",
|
||||
"new_note",
|
||||
# NotetypesService
|
||||
"get_notetype",
|
||||
"get_notetype_names",
|
||||
|
|
|
@ -224,14 +224,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
bridgeCommand(`setTagsCollapsed:${$tagsCollapsed}`);
|
||||
}
|
||||
|
||||
let noteId: bigint | null = null;
|
||||
export function setNoteId(ntid: bigint | null): void {
|
||||
let note: Note | null = null;
|
||||
export function setNote(n: Note): void {
|
||||
note = n;
|
||||
// TODO this is a hack, because it requires the NoteEditor to know implementation details of the PlainTextInput.
|
||||
// It should be refactored once we work on our own Undo stack
|
||||
for (const pi of plainTextInputs) {
|
||||
pi.api.codeMirror.editor.then((editor) => editor.clearHistory());
|
||||
}
|
||||
noteId = ntid;
|
||||
}
|
||||
|
||||
let notetypeMeta: NotetypeIdAndModTime;
|
||||
|
@ -251,10 +251,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
}
|
||||
|
||||
function getNoteId(): string | null {
|
||||
return noteId?.toString() ?? null;
|
||||
}
|
||||
|
||||
let isImageOcclusion = false;
|
||||
function setIsImageOcclusion(val: boolean) {
|
||||
isImageOcclusion = val;
|
||||
|
@ -294,18 +290,24 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
function transformContentBeforeSave(content: string): string {
|
||||
return content.replace(/ data-editor-shrink="(true|false)"/g, "");
|
||||
// TODO: mungeHTML()
|
||||
}
|
||||
|
||||
async function updateCurrentNote() {
|
||||
if (mode !== "add") {
|
||||
await editorUpdateNote({
|
||||
notes: [note!],
|
||||
skipUndoEntry: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateField(index: number, content: string): void {
|
||||
fieldSave.schedule(
|
||||
() =>
|
||||
bridgeCommand(
|
||||
`key:${index}:${getNoteId()}:${transformContentBeforeSave(
|
||||
content,
|
||||
)}`,
|
||||
),
|
||||
600,
|
||||
);
|
||||
fieldSave.schedule(() => {
|
||||
bridgeCommand(`key:${index}`);
|
||||
note!.fields[index] = transformContentBeforeSave(content);
|
||||
updateCurrentNote();
|
||||
}, 600);
|
||||
}
|
||||
|
||||
function saveFieldNow(): void {
|
||||
|
@ -422,6 +424,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
getNote,
|
||||
getNotetype,
|
||||
encodeIriPaths,
|
||||
newNote,
|
||||
editorUpdateNote,
|
||||
} from "@generated/backend";
|
||||
import { wrapInternal } from "@tslib/wrap";
|
||||
|
||||
|
@ -442,6 +446,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import StickyBadge from "./StickyBadge.svelte";
|
||||
import ButtonGroupItem from "$lib/components/ButtonGroupItem.svelte";
|
||||
import PreviewButton from "./PreviewButton.svelte";
|
||||
import type { Note } from "@generated/anki/notes_pb";
|
||||
|
||||
$: isIOImageLoaded = false;
|
||||
$: ioImageLoadedStore.set(isIOImageLoaded);
|
||||
|
@ -562,11 +567,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
});
|
||||
}
|
||||
|
||||
async function loadNote(nid: bigint | null, notetypeId: bigint, focusTo: number) {
|
||||
async function loadNote(nid: bigint, notetypeId: bigint, focusTo: number) {
|
||||
const notetype = await getNotetype({
|
||||
ntid: notetypeId,
|
||||
});
|
||||
let fieldValues: string[] = notetype.fields.map(() => "");
|
||||
const fieldNames = (
|
||||
await getFieldNames({
|
||||
ntid: notetype.id,
|
||||
|
@ -576,18 +580,22 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
const clozeFields = fieldNames.map((name, index) =>
|
||||
clozeFieldOrds.includes(index),
|
||||
);
|
||||
let tags: string[] = [];
|
||||
if (nid) {
|
||||
const note = await getNote({
|
||||
nid,
|
||||
});
|
||||
fieldValues = (
|
||||
await Promise.all(
|
||||
note.fields.map((field) => encodeIriPaths({ val: field })),
|
||||
)
|
||||
).map((field) => field.val);
|
||||
tags = note.tags;
|
||||
if (mode === "add") {
|
||||
setNote(await newNote({ ntid: notetype.id }));
|
||||
} else {
|
||||
setNote(
|
||||
await getNote({
|
||||
nid,
|
||||
}),
|
||||
);
|
||||
}
|
||||
const fieldValues = (
|
||||
await Promise.all(
|
||||
note!.fields.map((field) => encodeIriPaths({ val: field })),
|
||||
)
|
||||
).map((field) => field.val);
|
||||
const tags = note!.tags;
|
||||
|
||||
saveSession();
|
||||
setFields(fieldNames, fieldValues);
|
||||
setIsImageOcclusion(
|
||||
|
@ -610,7 +618,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
]),
|
||||
);
|
||||
focusField(focusTo);
|
||||
setNoteId(nid);
|
||||
// TODO: lastTextColor/lastHighlightColor profile config
|
||||
// setColorButtons(["#0000ff", "#0000ff"]);
|
||||
setTags(tags);
|
||||
|
@ -666,8 +673,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
setClozeHint,
|
||||
saveNow,
|
||||
focusIfField,
|
||||
getNoteId,
|
||||
setNoteId,
|
||||
setNotetypeMeta,
|
||||
wrap,
|
||||
setMathjaxEnabled,
|
||||
|
@ -786,11 +791,9 @@ components and functionality for general note editing.
|
|||
on:focusout={() => {
|
||||
$focusedField = null;
|
||||
setAddonButtonsDisabled(true);
|
||||
bridgeCommand(
|
||||
`blur:${index}:${getNoteId()}:${transformContentBeforeSave(
|
||||
get(content),
|
||||
)}`,
|
||||
);
|
||||
bridgeCommand(`blur:${index}`);
|
||||
note!.fields[index] = transformContentBeforeSave(get(content));
|
||||
updateCurrentNote();
|
||||
}}
|
||||
on:mouseenter={() => {
|
||||
$hoveredField = fields[index];
|
||||
|
|
Loading…
Reference in a new issue