mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 00:36:38 -04:00
Add a temporary workaround for addcards
This commit is contained in:
parent
b3aa8e93f3
commit
05360e2d19
4 changed files with 97 additions and 90 deletions
|
@ -172,63 +172,13 @@ class AddCards(QMainWindow):
|
|||
if deck_id := self.col.default_deck_for_notetype(notetype_id):
|
||||
self.deck_chooser.selected_deck_id = deck_id
|
||||
|
||||
# only used for detecting changed sticky fields on close
|
||||
self._last_added_note = None
|
||||
|
||||
# copy fields into new note with the new notetype
|
||||
old_note = self.editor.note
|
||||
new_note = self._new_note()
|
||||
if old_note:
|
||||
old_field_names = list(old_note.keys())
|
||||
new_field_names = list(new_note.keys())
|
||||
copied_field_names = set()
|
||||
for f in new_note.note_type()["flds"]:
|
||||
field_name = f["name"]
|
||||
# copy identical non-empty fields
|
||||
if field_name in old_field_names and old_note[field_name]:
|
||||
new_note[field_name] = old_note[field_name]
|
||||
copied_field_names.add(field_name)
|
||||
new_idx = 0
|
||||
for old_idx, old_field_value in enumerate(old_field_names):
|
||||
# skip previously copied identical fields in new note
|
||||
while (
|
||||
new_idx < len(new_field_names)
|
||||
and new_field_names[new_idx] in copied_field_names
|
||||
):
|
||||
new_idx += 1
|
||||
if new_idx >= len(new_field_names):
|
||||
break
|
||||
# copy non-empty old fields
|
||||
if (
|
||||
old_field_value not in copied_field_names
|
||||
and old_note.fields[old_idx]
|
||||
):
|
||||
new_note.fields[new_idx] = old_note.fields[old_idx]
|
||||
new_idx += 1
|
||||
|
||||
new_note.tags = old_note.tags
|
||||
|
||||
# and update editor state
|
||||
self.editor.note = new_note
|
||||
self.editor.loadNote(
|
||||
focusTo=min(self.editor.last_field_index or 0, len(new_note.fields) - 1)
|
||||
)
|
||||
gui_hooks.addcards_did_change_note_type(
|
||||
self, old_note.note_type(), new_note.note_type()
|
||||
)
|
||||
if notetype_id:
|
||||
self.editor.set_nid(None, mid=notetype_id, focus_to=0)
|
||||
|
||||
def _load_new_note(self, sticky_fields_from: Note | None = None) -> None:
|
||||
note = self._new_note()
|
||||
if old_note := sticky_fields_from:
|
||||
flds = note.note_type()["flds"]
|
||||
# copy fields from old note
|
||||
if old_note:
|
||||
for n in range(min(len(note.fields), len(old_note.fields))):
|
||||
if flds[n]["sticky"]:
|
||||
note.fields[n] = old_note.fields[n]
|
||||
# and tags
|
||||
note.tags = old_note.tags
|
||||
self.setAndFocusNote(note)
|
||||
self.editor.set_nid(
|
||||
None, mid=self.notetype_chooser.selected_notetype_id, focus_to=0
|
||||
)
|
||||
|
||||
def on_operation_did_execute(
|
||||
self, changes: OpChanges, handler: object | None
|
||||
|
@ -279,12 +229,7 @@ class AddCards(QMainWindow):
|
|||
aqt.dialogs.open("Browser", self.mw, search=(SearchNode(nid=nid),))
|
||||
|
||||
def add_current_note(self) -> None:
|
||||
if self.editor.current_notetype_is_image_occlusion():
|
||||
self.editor.update_occlusions_field()
|
||||
self.editor.call_after_note_saved(self._add_current_note)
|
||||
self.editor.reset_image_occlusion()
|
||||
else:
|
||||
self.editor.call_after_note_saved(self._add_current_note)
|
||||
self.editor.web.eval(f"addCurrentNote({self.deck_chooser.selected_deck_id})")
|
||||
|
||||
def _add_current_note(self) -> None:
|
||||
note = self.editor.note
|
||||
|
|
|
@ -28,6 +28,7 @@ import aqt
|
|||
import aqt.forms
|
||||
import aqt.operations
|
||||
import aqt.sound
|
||||
from anki._legacy import deprecated
|
||||
from anki.cards import Card
|
||||
from anki.collection import Config
|
||||
from anki.consts import MODEL_CLOZE
|
||||
|
@ -37,7 +38,6 @@ from anki.models import NotetypeDict, NotetypeId, StockNotetype
|
|||
from anki.notes import Note, NoteId
|
||||
from anki.utils import checksum, is_mac, is_win, namedtmp
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.operations.note import update_note
|
||||
from aqt.operations.notetype import update_notetype_legacy
|
||||
from aqt.qt import *
|
||||
from aqt.sound import av_player
|
||||
|
@ -129,7 +129,7 @@ class Editor:
|
|||
self.mw = mw
|
||||
self.widget = widget
|
||||
self.parentWindow = parentWindow
|
||||
self.note: Note | None = None
|
||||
self.nid: NoteId | None = None
|
||||
# legacy argument provided?
|
||||
if addMode is not None:
|
||||
editor_mode = EditorMode.ADD_CARDS if addMode else EditorMode.EDIT_CURRENT
|
||||
|
@ -380,10 +380,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
|||
######################################################################
|
||||
|
||||
def onBridgeCmd(self, cmd: str) -> Any:
|
||||
if not self.note:
|
||||
# shutdown
|
||||
return
|
||||
|
||||
# focus lost or key/button pressed?
|
||||
if cmd.startswith("blur") or cmd.startswith("key"):
|
||||
(type, ord_str) = cmd.split(":", 1)
|
||||
|
@ -475,6 +471,18 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
|||
# Setting/unsetting the current note
|
||||
######################################################################
|
||||
|
||||
def set_nid(
|
||||
self,
|
||||
nid: NoteId | None,
|
||||
mid: int,
|
||||
focus_to: int | None = None,
|
||||
) -> None:
|
||||
"Make note with ID `nid` the current note."
|
||||
self.nid = nid
|
||||
self.currentField = None
|
||||
self.load_note(mid, focus_to=focus_to)
|
||||
|
||||
@deprecated(replaced_by=set_nid)
|
||||
def set_note(
|
||||
self,
|
||||
note: Note | None,
|
||||
|
@ -482,10 +490,10 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
|||
focusTo: int | None = None,
|
||||
) -> None:
|
||||
"Make NOTE the current note."
|
||||
self.note = note
|
||||
self.currentField = None
|
||||
if self.note:
|
||||
self.loadNote(focusTo=focusTo)
|
||||
if note:
|
||||
self.nid = note.id
|
||||
self.load_note(mid=note.mid, focus_to=focusTo)
|
||||
elif hide:
|
||||
self.widget.hide()
|
||||
|
||||
|
@ -493,43 +501,35 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
|||
self.loadNote(self.currentField)
|
||||
|
||||
@on_editor_ready
|
||||
def loadNote(self, focusTo: int | None = None) -> None:
|
||||
if not self.note:
|
||||
return
|
||||
def load_note(self, mid: int, focus_to: int | None = None) -> None:
|
||||
|
||||
self.widget.show()
|
||||
# note_fields_status = self.note.fields_check()
|
||||
|
||||
def oncallback(arg: Any) -> None:
|
||||
if not self.note:
|
||||
if not self.nid:
|
||||
return
|
||||
# we currently do this synchronously to ensure we load before the
|
||||
# sidebar on browser startup
|
||||
if focusTo is not None:
|
||||
if focus_to is not None:
|
||||
self.web.setFocus()
|
||||
gui_hooks.editor_did_load_note(self)
|
||||
|
||||
assert self.mw.pm.profile is not None
|
||||
js = f"loadNote({self.note.id}, {self.note.mid}, {json.dumps(focusTo)}, {json.dumps(self.orig_note_id)});"
|
||||
js = f"loadNote({json.dumps(self.nid)}, {mid}, {json.dumps(focus_to)}, {json.dumps(self.orig_note_id)});"
|
||||
js = gui_hooks.editor_will_load_note(js, self.note, self)
|
||||
self.web.evalWithCallback(
|
||||
f'require("anki/ui").loaded.then(() => {{ {js} }})', oncallback
|
||||
)
|
||||
|
||||
def _save_current_note(self) -> None:
|
||||
"Call after note is updated with data from webview."
|
||||
if not self.note:
|
||||
return
|
||||
|
||||
update_note(parent=self.widget, note=self.note).run_in_background(
|
||||
initiator=self
|
||||
)
|
||||
@deprecated(replaced_by=load_note)
|
||||
def loadNote(self, focusTo: int | None = None) -> None:
|
||||
self.load_note(self.note.mid, focus_to=focusTo)
|
||||
|
||||
def call_after_note_saved(
|
||||
self, callback: Callable, keepFocus: bool = False
|
||||
) -> None:
|
||||
"Save unsaved edits then call callback()."
|
||||
if not self.note:
|
||||
if not self.nid:
|
||||
# calling code may not expect the callback to fire immediately
|
||||
self.mw.progress.single_shot(10, callback)
|
||||
return
|
||||
|
@ -1007,6 +1007,12 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
|
|||
addImageForOcclusionFromClipboard=Editor.select_image_from_clipboard_and_occlude,
|
||||
)
|
||||
|
||||
@property
|
||||
def note(self) -> Note | None:
|
||||
if self.nid is None:
|
||||
return None
|
||||
return self.mw.col.get_note(self.nid)
|
||||
|
||||
def note_type(self) -> NotetypeDict:
|
||||
assert self.note is not None
|
||||
note_type = self.note.note_type()
|
||||
|
|
|
@ -704,6 +704,7 @@ exposed_backend_list = [
|
|||
"get_note",
|
||||
"new_note",
|
||||
"note_fields_check",
|
||||
"add_note",
|
||||
# NotetypesService
|
||||
"get_notetype",
|
||||
"get_notetype_names",
|
||||
|
|
|
@ -365,6 +365,57 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
setClozeHint(hint);
|
||||
}
|
||||
|
||||
async function loadNewNote() {
|
||||
await loadNote(0n, notetypeMeta.id, 0, null);
|
||||
}
|
||||
|
||||
async function noteCanBeAdded(): Promise<boolean> {
|
||||
let problem: string | null = null;
|
||||
const result = await noteFieldsCheck(note!);
|
||||
if(result.state === NoteFieldsCheckResponse_State.EMPTY) {
|
||||
if(isImageOcclusion) {
|
||||
problem = tr.notetypesNoOcclusionCreated2();
|
||||
} else {
|
||||
problem = tr.addingTheFirstFieldIsEmpty();
|
||||
}
|
||||
}
|
||||
if(result.state === NoteFieldsCheckResponse_State.MISSING_CLOZE) {
|
||||
// TODO: askUser(tr.addingYouHaveAClozeDeletionNote())
|
||||
return false;
|
||||
}
|
||||
if(result.state === NoteFieldsCheckResponse_State.NOTETYPE_NOT_CLOZE) {
|
||||
problem = tr.addingClozeOutsideClozeNotetype();
|
||||
}
|
||||
if(result.state === NoteFieldsCheckResponse_State.FIELD_NOT_CLOZE) {
|
||||
problem = tr.addingClozeOutsideClozeField();
|
||||
}
|
||||
return problem ? false : true;
|
||||
}
|
||||
|
||||
async function addCurrentNoteInner(deckId: bigint) {
|
||||
if(!await noteCanBeAdded()) {
|
||||
return;
|
||||
}
|
||||
await addNote({
|
||||
note: note!,
|
||||
deckId,
|
||||
});
|
||||
await loadNewNote();
|
||||
}
|
||||
|
||||
export async function addCurrentNote(deckId: bigint) {
|
||||
if(mode !== "add") {
|
||||
return;
|
||||
}
|
||||
if(isImageOcclusion) {
|
||||
saveOcclusions();
|
||||
await addCurrentNoteInner(deckId);
|
||||
resetIOImageLoaded();
|
||||
} else {
|
||||
await addCurrentNoteInner(deckId);
|
||||
}
|
||||
}
|
||||
|
||||
export function focusIfField(x: number, y: number): boolean {
|
||||
const elements = document.elementsFromPoint(x, y);
|
||||
const first = elements[0].closest(".field-container");
|
||||
|
@ -465,6 +516,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
editorUpdateNote,
|
||||
decodeIriPaths,
|
||||
noteFieldsCheck,
|
||||
addNote,
|
||||
} from "@generated/backend";
|
||||
import { wrapInternal } from "@tslib/wrap";
|
||||
import { getProfileConfig, getMeta, setMeta, getColConfig } from "@tslib/profile";
|
||||
|
@ -605,11 +657,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
|
||||
async function loadNote(
|
||||
nid: bigint,
|
||||
nid: bigint | null,
|
||||
notetypeId: bigint,
|
||||
focusTo: number,
|
||||
originalNoteId: bigint | null,
|
||||
) {
|
||||
): Promise<bigint> {
|
||||
const notetype = await getNotetype({
|
||||
ntid: notetypeId,
|
||||
});
|
||||
|
@ -627,7 +679,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
} else {
|
||||
setNote(
|
||||
await getNote({
|
||||
nid,
|
||||
nid!,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -679,7 +731,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
html: imageField,
|
||||
mode: {
|
||||
kind: "edit",
|
||||
noteId: nid,
|
||||
noteId: nid!,
|
||||
},
|
||||
});
|
||||
} else if (originalNoteId) {
|
||||
|
@ -694,6 +746,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
await updateDuplicateDisplay();
|
||||
triggerChanges();
|
||||
|
||||
return note!.id;
|
||||
}
|
||||
|
||||
$: signalEditorState(editorState);
|
||||
|
@ -749,6 +803,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
resetIOImageLoaded,
|
||||
saveOcclusions,
|
||||
setSticky,
|
||||
addCurrentNote,
|
||||
...oldEditorAdapter,
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue