diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a4fac45f38d..f2a931c8995 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -187,13 +187,14 @@ Christian Donat Asuka Minato Dillon Baldwin Voczi -Ben Nguyen <105088397+bpnguyen107@users.noreply.github.com> +Ben Nguyen <105088397+bpnguyen107@users.noreply.github.com> Themis Demetriades Luke Bartholomew Gregory Abrasaldo Taylor Obyen <162023405+taylorobyen@users.noreply.github.com> Kris Cherven twwn +Shirish Pokhrel Park Hyunwoo ******************** diff --git a/qt/aqt/browser/browser.py b/qt/aqt/browser/browser.py index 3056f96327b..0ddb4737177 100644 --- a/qt/aqt/browser/browser.py +++ b/qt/aqt/browser/browser.py @@ -740,7 +740,7 @@ def onHelp(self) -> None: def on_create_copy(self) -> None: if note := self.table.get_current_note(): - deck_id = self.table.get_current_card().did + deck_id = self.table.get_current_card().current_deck_id() aqt.dialogs.open("AddCards", self.mw).set_note(note, deck_id) @no_arg_trigger diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 975780e4eb7..ebd1f50589c 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -1125,7 +1125,7 @@ def reset_image_occlusion(self) -> None: self.web.eval("resetIOImageLoaded()") def update_occlusions_field(self) -> None: - self.web.eval("updateOcclusionsField()") + self.web.eval("saveOcclusions()") def _setup_mask_editor(self, io_options: dict): self.web.eval( diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index f64f82208df..c219dfc42e6 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -1155,7 +1155,7 @@ def forget_current_card(self) -> None: def on_create_copy(self) -> None: if self.card: aqt.dialogs.open("AddCards", self.mw).set_note( - self.card.note(), self.card.did + self.card.note(), self.card.current_deck_id() ) def delete_current_note(self) -> None: diff --git a/rslib/src/import_export/text/import.rs b/rslib/src/import_export/text/import.rs index 6b332a65164..524a0c2391b 100644 --- a/rslib/src/import_export/text/import.rs +++ b/rslib/src/import_export/text/import.rs @@ -635,9 +635,9 @@ impl ForeignCard { } fn native_due(self, timing: &SchedTimingToday) -> i32 { - let day_start = timing.next_day_at.0 as i32 - 86_400; + let day_start = timing.next_day_at.0 - 86_400; let due_delta = (self.due - day_start) / 86_400; - due_delta + timing.days_elapsed as i32 + due_delta as i32 + timing.days_elapsed as i32 } } diff --git a/rslib/src/import_export/text/mod.rs b/rslib/src/import_export/text/mod.rs index 7dbf55f581f..e9e2da76690 100644 --- a/rslib/src/import_export/text/mod.rs +++ b/rslib/src/import_export/text/mod.rs @@ -40,7 +40,7 @@ pub struct ForeignNote { #[serde(default)] pub struct ForeignCard { /// Seconds-based timestamp - pub due: i32, + pub due: i64, /// In days pub interval: u32, pub ease_factor: f32, diff --git a/rslib/src/search/parser.rs b/rslib/src/search/parser.rs index 492c88d937a..93df4ea082c 100644 --- a/rslib/src/search/parser.rs +++ b/rslib/src/search/parser.rs @@ -61,10 +61,11 @@ pub enum SearchNode { EditedInDays(u32), CardTemplate(TemplateKind), Deck(String), - /// Matches cards in a list of decks (original_deck_id is not checked). + /// Matches cards in a list of deck ids. Cards are matched even if they are + /// in a filtered deck. DeckIdsWithoutChildren(String), /// Matches cards in a deck or its children (original_deck_id is not - /// checked). + /// checked, so filtered cards are not matched). DeckIdWithChildren(DeckId), IntroducedInDays(u32), NotetypeId(NotetypeId), diff --git a/rslib/src/search/sqlwriter.rs b/rslib/src/search/sqlwriter.rs index 20930b2f5d3..97a6a29a3a3 100644 --- a/rslib/src/search/sqlwriter.rs +++ b/rslib/src/search/sqlwriter.rs @@ -161,7 +161,12 @@ impl SqlWriter<'_> { write!(self.sql, "n.mid = {}", ntid).unwrap(); } SearchNode::DeckIdsWithoutChildren(dids) => { - write!(self.sql, "c.did in ({})", dids).unwrap(); + write!( + self.sql, + "c.did in ({}) or (c.odid != 0 and c.odid in ({}))", + dids, dids + ) + .unwrap(); } SearchNode::DeckIdWithChildren(did) => self.write_deck_id_with_children(*did)?, SearchNode::Notetype(notetype) => self.write_notetype(&norm(notetype)), diff --git a/rslib/src/typeanswer.rs b/rslib/src/typeanswer.rs index d1975dbdbb5..5277e88ff16 100644 --- a/rslib/src/typeanswer.rs +++ b/rslib/src/typeanswer.rs @@ -34,12 +34,12 @@ macro_rules! format_typeans { // Public API pub fn compare_answer(expected: &str, typed: &str, combining: bool) -> String { - if typed.is_empty() { - format_typeans!(htmlescape::encode_minimal(&prepare_expected(expected))) - } else if combining { - Diff::new(expected, typed).to_html() - } else { - DiffNonCombining::new(expected, typed).to_html() + let stripped = strip_expected(expected); + + match typed.is_empty() { + true => format_typeans!(htmlescape::encode_minimal(&stripped)), + false if combining => Diff::new(&stripped, typed).to_html(), + false => DiffNonCombining::new(&stripped, typed).to_html(), } } @@ -116,7 +116,7 @@ fn slice(chars: &[char], start: usize, end: usize) -> String { chars[start..end].iter().collect() } -fn prepare_expected(expected: &str) -> String { +fn strip_expected(expected: &str) -> String { let no_av_tags = strip_av_tags(expected); let no_linebreaks = LINEBREAKS.replace_all(&no_av_tags, " "); strip_html(&no_linebreaks).trim().to_string() @@ -167,7 +167,7 @@ impl DiffTrait for Diff { fn new(expected: &str, typed: &str) -> Self { Self { typed: Self::normalize_typed(typed), - expected: normalize(&prepare_expected(expected)), + expected: normalize(expected), } } fn normalize_typed(typed: &str) -> Vec { @@ -202,7 +202,7 @@ impl DiffTrait for DiffNonCombining { let mut expected_stripped = String::new(); // tokenized into "char+combining" for final rendering let mut expected_split: Vec = Vec::new(); - for c in normalize(&prepare_expected(expected)) { + for c in normalize(expected) { if unicode_normalization::char::is_combining_mark(c) { if let Some(last) = expected_split.last_mut() { last.push(c); @@ -219,7 +219,7 @@ impl DiffTrait for DiffNonCombining { expected: expected_stripped.chars().collect(), }, expected_split, - expected_original: prepare_expected(expected), + expected_original: expected.to_string(), } } @@ -340,7 +340,8 @@ mod test { #[test] fn html_and_media() { - let ctx = Diff::new("[sound:foo.mp3]1  2", "1 2"); + let stripped = strip_expected("[sound:foo.mp3]1  2"); + let ctx = Diff::new(&stripped, "1 2"); // the spacing is handled by wrapping html output in white-space: pre-wrap assert_eq!(ctx.to_tokens().expected_tokens, &[good("1 2")]); } @@ -387,9 +388,10 @@ mod test { #[test] fn tags_removed() { - assert_eq!(prepare_expected("
123
"), "123"); + let stripped = strip_expected("
123
"); + assert_eq!(stripped, "123"); assert_eq!( - Diff::new("
123
", "123").to_html(), + Diff::new(&stripped, "123").to_html(), "123" ); } diff --git a/ts/editor/NoteEditor.svelte b/ts/editor/NoteEditor.svelte index 83ceec32871..885200e07d4 100644 --- a/ts/editor/NoteEditor.svelte +++ b/ts/editor/NoteEditor.svelte @@ -459,7 +459,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html } globalThis.setImageField = setImageField; - function updateOcclusionsField(): void { + function saveOcclusions(): void { if (isImageOcclusion && globalThis.canvas) { const occlusionsData = exportShapesToClozeDeletions($hideAllGuessOne); fieldStores[ioFields.occlusions].set(occlusionsData.clozes); @@ -572,7 +572,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html triggerChanges, setIsImageOcclusion, setupMaskEditor, - updateOcclusionsField, + saveOcclusions, ...oldEditorAdapter, }); @@ -637,7 +637,7 @@ the AddCards dialog) should be implemented in the user of this component.
diff --git a/ts/editor/editor-toolbar/BoldButton.svelte b/ts/editor/editor-toolbar/BoldButton.svelte index d6b580b5633..215e984302b 100644 --- a/ts/editor/editor-toolbar/BoldButton.svelte +++ b/ts/editor/editor-toolbar/BoldButton.svelte @@ -17,8 +17,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html return match.remove(); } - const fontWeight = element.style.fontWeight; - if (fontWeight === "bold" || Number(fontWeight) >= 700) { + const fontWeight = getComputedStyle(element).fontWeight; + const threshold = 700; + if (fontWeight && Number(fontWeight) >= threshold) { return match.clear((): void => { if ( removeStyleProperties(element, "font-weight") && diff --git a/ts/editor/editor-toolbar/ItalicButton.svelte b/ts/editor/editor-toolbar/ItalicButton.svelte index c31b8e93bb3..d5bbb300440 100644 --- a/ts/editor/editor-toolbar/ItalicButton.svelte +++ b/ts/editor/editor-toolbar/ItalicButton.svelte @@ -17,7 +17,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html return match.remove(); } - if (["italic", "oblique"].includes(element.style.fontStyle)) { + const fontStyle = getComputedStyle(element).fontStyle; + if (["italic", "oblique"].includes(fontStyle)) { return match.clear((): void => { if ( removeStyleProperties(element, "font-style") && diff --git a/ts/routes/image-occlusion/ImageOcclusionPage.svelte b/ts/routes/image-occlusion/ImageOcclusionPage.svelte index 4d4d38f3bbd..aad104ad656 100644 --- a/ts/routes/image-occlusion/ImageOcclusionPage.svelte +++ b/ts/routes/image-occlusion/ImageOcclusionPage.svelte @@ -40,7 +40,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html