Fix "Create copy" for IO notes (#3730)

* expose get_image_occlusion_fields

* fix create copy for io

* revert current impl

* passthru original note id when creating copy

* add IOCloningMode

* fix create copy for io
This commit is contained in:
llama 2025-01-17 13:03:00 +08:00 committed by GitHub
parent 3acca96ed8
commit 9c0911891d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 49 additions and 21 deletions

View file

@ -78,7 +78,7 @@ class AddCards(QMainWindow):
new_note.fields = note.fields[:]
new_note.tags = note.tags[:]
self.setAndFocusNote(new_note)
self.setAndFocusNote(new_note, orig_note_id=note.id)
def setupEditor(self) -> None:
self.editor = aqt.editor.Editor(
@ -143,8 +143,8 @@ class AddCards(QMainWindow):
b.setEnabled(False)
self.historyButton = b
def setAndFocusNote(self, note: Note) -> None:
self.editor.set_note(note, focusTo=0)
def setAndFocusNote(self, note: Note, orig_note_id: NoteId | None = None) -> None:
self.editor.set_note(note, focusTo=0, orig_note_id=orig_note_id)
def show_notetype_selector(self) -> None:
self.editor.call_after_note_saved(self.notetype_chooser.choose_notetype)

View file

@ -524,20 +524,26 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
######################################################################
def set_note(
self, note: Note | None, hide: bool = True, focusTo: int | None = None
self,
note: Note | None,
hide: bool = True,
focusTo: int | None = None,
orig_note_id: NoteId | None = None,
) -> None:
"Make NOTE the current note."
self.note = note
self.currentField = None
if self.note:
self.loadNote(focusTo=focusTo)
self.loadNote(focusTo=focusTo, orig_note_id=orig_note_id)
elif hide:
self.widget.hide()
def loadNoteKeepingFocus(self) -> None:
self.loadNote(self.currentField)
def loadNote(self, focusTo: int | None = None) -> None:
def loadNote(
self, focusTo: int | None = None, orig_note_id: NoteId | None = None
) -> None:
if not self.note:
return
@ -596,12 +602,13 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
sticky = [field["sticky"] for field in self.note_type()["flds"]]
js += " setSticky(%s);" % json.dumps(sticky)
if (
self.editorMode != EditorMode.ADD_CARDS
and self.current_notetype_is_image_occlusion()
):
io_options = self._create_edit_io_options(note_id=self.note.id)
js += " setupMaskEditor(%s);" % json.dumps(io_options)
if self.current_notetype_is_image_occlusion():
if self.editorMode is not EditorMode.ADD_CARDS:
io_options = self._create_edit_io_options(note_id=self.note.id)
js += " setupMaskEditor(%s);" % json.dumps(io_options)
elif orig_note_id:
io_options = self._create_clone_io_options(cloned_note_id=orig_note_id)
js += " setupMaskEditor(%s);" % json.dumps(io_options)
js = gui_hooks.editor_will_load_note(js, self.note, self)
self.web.evalWithCallback(
@ -1161,6 +1168,12 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
"html": image_field_html,
}
@staticmethod
def _create_clone_io_options(cloned_note_id: NoteId) -> dict:
return {
"mode": {"kind": "add", "clonedNoteId": cloned_note_id},
}
@staticmethod
def _create_edit_io_options(note_id: NoteId) -> dict:
return {"mode": {"kind": "edit", "noteId": note_id}}

View file

@ -431,7 +431,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
imageOcclusionMode = undefined;
await tick();
imageOcclusionMode = options.mode;
if (options.mode.kind === "add") {
if (options.mode.kind === "add" && !("clonedNoteId" in options.mode)) {
fieldStores[ioFields.image].set(options.html);
// the image field is set programmatically and does not need debouncing
// commit immediately to avoid a race condition with the occlusions field

View file

@ -44,10 +44,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function init(_node: HTMLDivElement) {
if (mode.kind == "add") {
// Editing occlusions on a new note through the "Add" window
setupMaskEditor(mode.imagePath, onImageLoaded).then((canvas1) => {
canvas = canvas1;
});
if ("clonedNoteId" in mode) {
// Editing occlusions on a new note cloned from an existing note via "Create copy"
setupMaskEditorForEdit(mode.clonedNoteId, onImageLoaded).then(
(canvas1) => {
canvas = canvas1;
},
);
} else {
// Editing occlusions on a new note through the "Add" window
setupMaskEditor(mode.imagePath, onImageLoaded).then((canvas1) => {
canvas = canvas1;
});
}
} else {
// Editing occlusions on an existing note through the "Browser" window
setupMaskEditorForEdit(mode.noteId, onImageLoaded).then((canvas1) => {

View file

@ -7,7 +7,7 @@ import * as tr from "@generated/ftl";
import { get } from "svelte/store";
import { mount } from "svelte";
import type { IOMode } from "./lib";
import type { IOAddingMode, IOMode } from "./lib";
import { exportShapesToClozeDeletions } from "./shapes/to-cloze";
import { notesDataStore, tagsWritable } from "./store";
import Toast from "./Toast.svelte";
@ -40,8 +40,9 @@ export const addOrUpdateNote = async function(
showResult(mode.noteId, result, noteCount);
} else {
const result = await addImageOcclusionNote({
notetypeId: BigInt(mode.notetypeId),
imagePath: mode.imagePath,
// IOCloningMode is not used on mobile
notetypeId: BigInt((<IOAddingMode> mode).notetypeId),
imagePath: (<IOAddingMode> mode).imagePath,
occlusions: occlusionCloze,
header,
backExtra,

View file

@ -7,9 +7,14 @@ export interface IOAddingMode {
imagePath: string;
}
export interface IOCloningMode {
kind: "add";
clonedNoteId: number;
}
export interface IOEditingMode {
kind: "edit";
noteId: number;
}
export type IOMode = IOAddingMode | IOEditingMode;
export type IOMode = IOAddingMode | IOEditingMode | IOCloningMode;