Revert bury restriction (#2432)

* Remove outdated comment.

* Revert removal of independent bury rules

* Revert 'hierarchical bury modes'

It's now again allowed to bury new, but not review cards e.g., but
siblings of previously gathered card queues will not be buried.

* Tweak docs (dae)

* Add missing Learn and PreviewRepeat queues
This commit is contained in:
RumovZ 2023-03-11 08:49:18 +01:00 committed by GitHub
parent 9b5148185a
commit c4d5eeb7a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 130 additions and 96 deletions

View file

@ -104,22 +104,28 @@ deck-config-leech-action-tooltip =
## Burying section
deck-config-bury-title = Burying
deck-config-bury-siblings = Bury siblings
deck-config-do-not-bury = Do not bury siblings
deck-config-bury-if-new = Bury if new
deck-config-bury-if-new-or-review = Bury if new or review
deck-config-bury-if-new-review-or-interday = Bury if new, review, or interday learning
deck-config-bury-tooltip =
Siblings are other cards from the same note (eg forward/reverse cards, or
other cloze deletions from the same text).
deck-config-bury-new-siblings = Bury new siblings
deck-config-bury-review-siblings = Bury review siblings
deck-config-bury-interday-learning-siblings = Bury interday learning siblings
deck-config-bury-new-tooltip =
Whether other `new` cards of the same note (eg reverse cards, adjacent cloze deletions)
will be delayed until the next day.
deck-config-bury-review-tooltip = Whether other `review` cards of the same note will be delayed until the next day.
deck-config-bury-interday-learning-tooltip =
Whether other `learning` cards of the same note with intervals > 1 day
will be delayed until the next day.
deck-config-bury-priority-tooltip =
When Anki gathers cards, it first gathers intraday learning cards, then
interday learning cards, then reviews, and finally new cards. This affects
how burying works:
When this option is off, multiple cards from the same note may be seen on the same
day. When enabled, Anki will automatically *bury* siblings, hiding them until the next
day. This option allows you to choose which kinds of cards may be buried when you answer
one of their siblings.
When using the V3 scheduler, interday learning cards can also be buried. Interday
learning cards are cards with a current learning step of one or more days.
- If you have all burying options enabled, the sibling that comes earliest in
that list will be shown. For example, a review card will be shown in preference
to a new card.
- Siblings later in the list can not bury earlier card types. For example, if you
disable burying of new cards, and study a new card, it will not bury any interday
learning or review cards, and you may see both a review sibling and new sibling in the
same session.
## Ordering section
@ -304,13 +310,19 @@ deck-config-which-deck = Which deck would you like?
## NO NEED TO TRANSLATE. This text is no longer used by Anki, and will be removed in the future.
deck-config-bury-new-siblings = Bury new siblings
deck-config-bury-review-siblings = Bury review siblings
deck-config-bury-interday-learning-siblings = Bury interday learning siblings
deck-config-bury-new-tooltip =
Whether other `new` cards of the same note (eg reverse cards, adjacent cloze deletions)
will be delayed until the next day.
deck-config-bury-review-tooltip = Whether other `review` cards of the same note will be delayed until the next day.
deck-config-bury-interday-learning-tooltip =
Whether other `learning` cards of the same note with intervals > 1 day
will be delayed until the next day.
deck-config-bury-siblings = Bury siblings
deck-config-do-not-bury = Do not bury siblings
deck-config-bury-if-new = Bury if new
deck-config-bury-if-new-or-review = Bury if new or review
deck-config-bury-if-new-review-or-interday = Bury if new, review, or interday learning
deck-config-bury-tooltip =
Siblings are other cards from the same note (eg forward/reverse cards, or
other cloze deletions from the same text).
When this option is off, multiple cards from the same note may be seen on the same
day. When enabled, Anki will automatically *bury* siblings, hiding them until the next
day. This option allows you to choose which kinds of cards may be buried when you answer
one of their siblings.
When using the V3 scheduler, interday learning cards can also be buried. Interday
learning cards are cards with a current learning step of one or more days.

View file

@ -124,13 +124,8 @@ message DeckConfig {
bool show_timer = 25;
bool skip_question_when_replaying_answer = 26;
// the new scheduler doesn't allow toggling these booleans freely anymore,
// but they are continued to be used for reasons of backwards compatibility
bool bury_new = 27;
// only respected if bury_new
bool bury_reviews = 28;
// only respected if bury_new and bury_reviews
bool bury_interday_learning = 29;
bytes other = 255;

View file

@ -288,7 +288,7 @@ impl Collection {
fn maybe_bury_siblings(&mut self, card: &Card, config: &DeckConfig) -> Result<()> {
let bury_mode = BuryMode::from_deck_config(config);
if bury_mode.any_burying() {
self.bury_siblings(card.id, card.note_id, bury_mode)?;
self.bury_siblings(card, card.note_id, bury_mode)?;
}
Ok(())
}

View file

@ -80,7 +80,6 @@ impl Collection {
})
}
/// Bury/suspend cards in search table, and clear it.
/// Marks the cards as modified.
fn bury_or_suspend_cards_inner(
&mut self,
@ -139,15 +138,39 @@ impl Collection {
pub(crate) fn bury_siblings(
&mut self,
cid: CardId,
card: &Card,
nid: NoteId,
bury_mode: BuryMode,
mut bury_mode: BuryMode,
) -> Result<usize> {
let cards = self.storage.all_siblings_for_bury(cid, nid, bury_mode)?;
bury_mode.exclude_earlier_gathered_queues(card.queue);
let cards = self
.storage
.all_siblings_for_bury(card.id, nid, bury_mode)?;
self.bury_or_suspend_cards_inner(cards, BuryOrSuspendMode::BurySched)
}
}
impl BuryMode {
/// Disables burying for queues gathered before `queue`.
fn exclude_earlier_gathered_queues(&mut self, queue: CardQueue) {
self.bury_interday_learning &= queue.gather_ord() <= CardQueue::DayLearn.gather_ord();
self.bury_reviews &= queue.gather_ord() <= CardQueue::Review.gather_ord();
}
}
impl CardQueue {
fn gather_ord(self) -> u8 {
match self {
CardQueue::Learn | CardQueue::PreviewRepeat => 0,
CardQueue::DayLearn => 1,
CardQueue::Review => 2,
CardQueue::New => 3,
// not gathered
CardQueue::Suspended | CardQueue::SchedBuried | CardQueue::UserBuried => u8::MAX,
}
}
}
#[cfg(test)]
mod test {
use crate::card::Card;

View file

@ -56,15 +56,10 @@ impl Context {
impl BuryMode {
pub(crate) fn from_deck_config(config: &DeckConfig) -> BuryMode {
let cfg = &config.inner;
// Since cards are gathered in a certain order (learning > review > new) and
// a card can only bury siblings that are gathered later, only the four bury
// modes following this order are allowed.
// Booleans are continued to be used for reasons of backwards compatibility.
// https://github.com/ankitects/anki/issues/2352
BuryMode {
bury_new: cfg.bury_new,
bury_reviews: cfg.bury_new && cfg.bury_reviews,
bury_interday_learning: cfg.bury_new && cfg.bury_reviews && cfg.bury_interday_learning,
bury_reviews: cfg.bury_reviews,
bury_interday_learning: cfg.bury_interday_learning,
}
}

View file

@ -456,7 +456,7 @@ mod test {
#[test]
fn new_card_potentially_burying_review_card() {
let mut col = open_test_collection();
let mut col = Collection::new_v3();
// add one new and one review card
CardAdder::new().siblings(2).due_dates(["0"]).add(&mut col);
// Potentially problematic config: New cards are shown first and would bury

View file

@ -3,7 +3,6 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import type { anki } from "@tslib/backend_proto";
import * as tr from "@tslib/ftl";
import type Carousel from "bootstrap/js/dist/carousel";
import type Modal from "bootstrap/js/dist/modal";
@ -11,10 +10,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import DynamicallySlottable from "../components/DynamicallySlottable.svelte";
import Item from "../components/Item.svelte";
import TitledContainer from "../components/TitledContainer.svelte";
import EnumSelectorRow from "./EnumSelectorRow.svelte";
import HelpModal from "./HelpModal.svelte";
import type { DeckOptionsState } from "./lib";
import SettingTitle from "./SettingTitle.svelte";
import SwitchRow from "./SwitchRow.svelte";
import type { DeckOption } from "./types";
export let state: DeckOptionsState;
@ -23,54 +22,33 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const config = state.currentConfig;
const defaults = state.defaults;
const burySiblings: DeckOption = {
title: tr.deckConfigBurySiblings(),
help: tr.deckConfigBuryTooltip(),
const priorityTooltip = state.v3Scheduler
? "\n\n" + tr.deckConfigBuryPriorityTooltip()
: "";
const settings = {
buryNewSiblings: {
title: tr.deckConfigBuryNewSiblings(),
help: tr.deckConfigBuryNewTooltip() + priorityTooltip,
},
buryReviewSiblings: {
title: tr.deckConfigBuryReviewSiblings(),
help: tr.deckConfigBuryReviewTooltip() + priorityTooltip,
},
buryInterdayLearningSiblings: {
title: tr.deckConfigBuryInterdayLearningSiblings(),
help: tr.deckConfigBuryInterdayLearningTooltip() + priorityTooltip,
},
};
const helpSections = Object.values(settings) as DeckOption[];
let modal: Modal;
let carousel: Carousel;
function openHelpModal(): void {
function openHelpModal(index: number): void {
modal.show();
carousel.to(0);
carousel.to(index);
}
const enum BuryMode {
NONE,
NEW,
NEW_REVIEW,
NEW_REVIEW_LEARNING,
}
const buryModeChoices = [
tr.deckConfigDoNotBury(),
tr.deckConfigBuryIfNew(),
tr.deckConfigBuryIfNewOrReview(),
];
if (state.v3Scheduler) {
buryModeChoices.push(tr.deckConfigBuryIfNewReviewOrInterday());
}
function buryModeFromConfig(config: anki.deckconfig.DeckConfig.Config): BuryMode {
// burying review cards is only allowed if also burying new cards
const buryReviews = config.buryNew && config.buryReviews;
// burying learning cards is only allowed if also burying review and new cards
const buryInterdayLearning =
buryReviews && config.buryInterdayLearning && state.v3Scheduler;
return (
Number(config.buryNew) + Number(buryReviews) + Number(buryInterdayLearning)
);
}
function buryModeToConfig(mode: BuryMode) {
$config.buryNew = mode >= 1;
$config.buryReviews = mode >= 2;
$config.buryInterdayLearning = mode >= 3;
}
let mode = buryModeFromConfig($config);
$: buryModeToConfig(mode);
</script>
<TitledContainer title={tr.deckConfigBuryTitle()}>
@ -78,7 +56,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
title={tr.deckConfigBuryTitle()}
url="https://docs.ankiweb.net/studying.html#siblings-and-burying"
slot="tooltip"
helpSections={[burySiblings]}
{helpSections}
on:mount={(e) => {
modal = e.detail.modal;
carousel = e.detail.carousel;
@ -86,15 +64,46 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/>
<DynamicallySlottable slotHost={Item} {api}>
<Item>
<EnumSelectorRow
bind:value={mode}
defaultValue={buryModeFromConfig(defaults)}
choices={buryModeChoices}
<SwitchRow bind:value={$config.buryNew} defaultValue={defaults.buryNew}>
<SettingTitle
on:click={() =>
openHelpModal(Object.keys(settings).indexOf("buryNewSiblings"))}
>{settings.buryNewSiblings.title}</SettingTitle
>
<SettingTitle on:click={() => openHelpModal()}
>{tr.deckConfigBurySiblings()}</SettingTitle
>
</EnumSelectorRow>
</SwitchRow>
</Item>
<Item>
<SwitchRow
bind:value={$config.buryReviews}
defaultValue={defaults.buryReviews}
>
<SettingTitle
on:click={() =>
openHelpModal(
Object.keys(settings).indexOf("buryReviewSiblings"),
)}>{settings.buryReviewSiblings.title}</SettingTitle
>
</SwitchRow>
</Item>
{#if state.v3Scheduler}
<Item>
<SwitchRow
bind:value={$config.buryInterdayLearning}
defaultValue={defaults.buryInterdayLearning}
>
<SettingTitle
on:click={() =>
openHelpModal(
Object.keys(settings).indexOf(
"buryInterdayLearningSiblings",
),
)}
>{settings.buryInterdayLearningSiblings.title}</SettingTitle
>
</SwitchRow>
</Item>
{/if}
</DynamicallySlottable>
</TitledContainer>