support undo for (renamed) unbury_deck() action

This commit is contained in:
Damien Elmes 2021-04-30 20:03:20 +10:00
parent d0f3007fad
commit abab4826bb
16 changed files with 92 additions and 83 deletions

View file

@ -8,7 +8,7 @@ ignored-classes=
BrowserRow,
FormatTimespanIn,
AnswerCardIn,
UnburyCardsInCurrentDeckIn,
UnburyDeckIn,
BuryOrSuspendCardsIn,
NoteIsDuplicateOrEmptyOut,
BackendError,

View file

@ -7,7 +7,7 @@ import sys
import anki.scheduler.base as _base
UnburyCurrentDeck = _base.UnburyCurrentDeck
UnburyDeck = _base.UnburyDeck
CongratsInfo = _base.CongratsInfo
BuryOrSuspend = _base.BuryOrSuspend
FilteredDeckForUpdate = _base.FilteredDeckForUpdate

View file

@ -20,7 +20,7 @@ from anki.notes import NoteId
from anki.utils import ids2str, intTime
CongratsInfo = _pb.CongratsInfoOut
UnburyCurrentDeck = _pb.UnburyCardsInCurrentDeckIn
UnburyDeck = _pb.UnburyDeckIn
BuryOrSuspend = _pb.BuryOrSuspendCardsIn
FilteredDeckForUpdate = _pb.FilteredDeckForUpdate
@ -118,11 +118,12 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
def unbury_cards(self, ids: List[CardId]) -> OpChanges:
return self.col._backend.restore_buried_and_suspended_cards(ids)
def unbury_cards_in_current_deck(
def unbury_deck(
self,
mode: UnburyCurrentDeck.Mode.V = UnburyCurrentDeck.ALL,
) -> None:
self.col._backend.unbury_cards_in_current_deck(mode)
deck_id: DeckId,
mode: UnburyDeck.Mode.V = UnburyDeck.ALL,
) -> OpChanges:
return self.col._backend.unbury_deck(deck_id=deck_id, mode=mode)
def suspend_cards(self, ids: Sequence[CardId]) -> OpChangesWithCount:
return self.col._backend.bury_or_suspend_cards(

View file

@ -7,7 +7,7 @@ from anki.cards import Card, CardId
from anki.consts import CARD_TYPE_RELEARNING, QUEUE_TYPE_DAY_LEARN_RELEARN
from anki.decks import DeckConfigDict, DeckId
from anki.notes import NoteId
from anki.scheduler.base import SchedulerBase, UnburyCurrentDeck
from anki.scheduler.base import SchedulerBase, UnburyDeck
from anki.utils import from_json_bytes, ids2str
@ -24,22 +24,18 @@ class SchedulerBaseWithLegacy(SchedulerBase):
self.bury_cards(note.card_ids())
def unburyCards(self) -> None:
print(
"please use unbury_cards() or unbury_cards_in_current_deck instead of unburyCards()"
)
self.unbury_cards_in_current_deck()
print("please use unbury_cards() or unbury_deck() instead of unburyCards()")
self.unbury_deck(self.col.decks.get_current_id())
def unburyCardsForDeck(self, type: str = "all") -> None:
print(
"please use unbury_cards_in_current_deck() instead of unburyCardsForDeck()"
)
print("please use unbury_deck() instead of unburyCardsForDeck()")
if type == "all":
mode = UnburyCurrentDeck.ALL
mode = UnburyDeck.ALL
elif type == "manual":
mode = UnburyCurrentDeck.USER_ONLY
mode = UnburyDeck.USER_ONLY
else: # elif type == "siblings":
mode = UnburyCurrentDeck.SCHED_ONLY
self.unbury_cards_in_current_deck(mode)
mode = UnburyDeck.SCHED_ONLY
self.unbury_deck(self.col.decks.get_current_id(), mode)
def finishedMsg(self) -> str:
print("finishedMsg() is obsolete")

View file

@ -4,13 +4,14 @@
import copy
import time
from anki import Collection
from anki.consts import *
from anki.lang import without_unicode_isolation
from anki.utils import intTime
from tests.shared import getEmptyCol as getEmptyColOrig
def getEmptyCol():
def getEmptyCol() -> Collection:
col = getEmptyColOrig()
# only safe in test environment
col.set_config("schedVer", 1)
@ -505,7 +506,7 @@ def test_misc():
col.sched.bury_notes([note.id])
col.reset()
assert not col.sched.getCard()
col.sched.unbury_cards_in_current_deck()
col.sched.unbury_deck(deck_id=col.decks.get_current_id())
col.reset()
assert col.sched.getCard()

View file

@ -11,7 +11,7 @@ import pytest
from anki import hooks
from anki.consts import *
from anki.lang import without_unicode_isolation
from anki.scheduler import UnburyCurrentDeck
from anki.scheduler import UnburyDeck
from anki.utils import intTime
from tests.shared import getEmptyCol as getEmptyColOrig
@ -673,18 +673,20 @@ def test_bury():
col.reset()
assert not col.sched.getCard()
col.sched.unbury_cards_in_current_deck(UnburyCurrentDeck.USER_ONLY)
col.sched.unbury_deck(deck_id=col.decks.get_current_id(), mode=UnburyDeck.USER_ONLY)
c.load()
assert c.queue == QUEUE_TYPE_NEW
c2.load()
assert c2.queue == QUEUE_TYPE_SIBLING_BURIED
col.sched.unbury_cards_in_current_deck(UnburyCurrentDeck.SCHED_ONLY)
col.sched.unbury_deck(
deck_id=col.decks.get_current_id(), mode=UnburyDeck.SCHED_ONLY
)
c2.load()
assert c2.queue == QUEUE_TYPE_NEW
col.sched.bury_cards([c.id, c2.id])
col.sched.unbury_cards_in_current_deck()
col.sched.unbury_deck(deck_id=col.decks.get_current_id())
col.reset()

View file

@ -10,7 +10,8 @@ ignored-classes=
BrowserRow,
SearchNode,
Config,
OpChanges
OpChanges,
UnburyDeckIn,
[REPORTS]
output-format=colorized

View file

@ -16,7 +16,7 @@ from anki.collection import (
)
from anki.decks import DeckId
from anki.notes import NoteId
from anki.scheduler import FilteredDeckForUpdate
from anki.scheduler import FilteredDeckForUpdate, UnburyDeck
from aqt.operations import CollectionOp
from aqt.qt import *
from aqt.utils import disable_help_button, getText, tooltip, tr
@ -196,3 +196,14 @@ def add_or_update_filtered_deck(
deck: FilteredDeckForUpdate,
) -> CollectionOp[OpChangesWithId]:
return CollectionOp(parent, lambda col: col.sched.add_or_update_filtered_deck(deck))
def unbury_deck(
*,
parent: QWidget,
deck_id: DeckId,
mode: UnburyDeck.Mode.V = UnburyDeck.ALL,
) -> CollectionOp[OpChanges]:
return CollectionOp(
parent, lambda col: col.sched.unbury_deck(deck_id=deck_id, mode=mode)
)

View file

@ -7,9 +7,14 @@ from typing import Any, Callable, Dict, List, Optional, Tuple
import aqt
from anki.collection import OpChanges
from anki.scheduler import UnburyDeck
from aqt import gui_hooks
from aqt.deckdescription import DeckDescriptionDialog
from aqt.operations.scheduling import empty_filtered_deck, rebuild_filtered_deck
from aqt.operations.scheduling import (
empty_filtered_deck,
rebuild_filtered_deck,
unbury_deck,
)
from aqt.sound import av_player
from aqt.toolbar import BottomBar
from aqt.utils import askUserDialog, openLink, shortcut, tooltip, tr
@ -102,7 +107,7 @@ class Overview:
elif url == "studymore" or url == "customStudy":
self.onStudyMore()
elif url == "unbury":
self.onUnbury()
self.on_unbury()
elif url == "description":
self.edit_description()
elif url.lower().startswith("http"):
@ -115,7 +120,7 @@ class Overview:
("r", self.rebuild_current_filtered_deck),
("e", self.empty_current_filtered_deck),
("c", self.onCustomStudyKey),
("u", self.onUnbury),
("u", self.on_unbury),
]
def _current_deck_is_filtered(self) -> int:
@ -135,12 +140,9 @@ class Overview:
if not self._current_deck_is_filtered():
self.onStudyMore()
def onUnbury(self) -> None:
if self.mw.col.schedVer() == 1:
self.mw.col.sched.unburyCardsForDeck()
self.mw.reset()
return
def on_unbury(self) -> None:
mode = UnburyDeck.Mode.ALL
if self.mw.col.schedVer() != 1:
info = self.mw.col.sched.congratulations_info()
if info.have_sched_buried and info.have_user_buried:
opts = [
@ -154,15 +156,17 @@ class Overview:
diag.setDefault(0)
ret = diag.run()
if ret == opts[0]:
self.mw.col.sched.unburyCardsForDeck(type="manual")
mode = UnburyDeck.Mode.USER_ONLY
elif ret == opts[1]:
self.mw.col.sched.unburyCardsForDeck(type="siblings")
elif ret == opts[2]:
self.mw.col.sched.unburyCardsForDeck(type="all")
else:
self.mw.col.sched.unburyCardsForDeck(type="all")
mode = UnburyDeck.Mode.SCHED_ONLY
elif ret == opts[3]:
return
self.mw.reset()
unbury_deck(
parent=self.mw, deck_id=self.mw.col.decks.get_current_id(), mode=mode
).run_in_background()
onUnbury = on_unbury
# HTML
############################################################

View file

@ -119,7 +119,7 @@ service SchedulingService {
rpc CountsForDeckToday(DeckId) returns (CountsForDeckTodayOut);
rpc CongratsInfo(Empty) returns (CongratsInfoOut);
rpc RestoreBuriedAndSuspendedCards(CardIds) returns (OpChanges);
rpc UnburyCardsInCurrentDeck(UnburyCardsInCurrentDeckIn) returns (Empty);
rpc UnburyDeck(UnburyDeckIn) returns (OpChanges);
rpc BuryOrSuspendCards(BuryOrSuspendCardsIn) returns (OpChangesWithCount);
rpc EmptyFilteredDeck(DeckId) returns (OpChanges);
rpc RebuildFilteredDeck(DeckId) returns (OpChangesWithCount);
@ -1333,13 +1333,14 @@ message CongratsInfoOut {
string deck_description = 9;
}
message UnburyCardsInCurrentDeckIn {
message UnburyDeckIn {
enum Mode {
ALL = 0;
SCHED_ONLY = 1;
USER_ONLY = 2;
}
Mode mode = 1;
int64 deck_id = 1;
Mode mode = 2;
}
message BuryOrSuspendCardsIn {

View file

@ -77,12 +77,9 @@ impl SchedulingService for Backend {
self.with_col(|col| col.unbury_or_unsuspend_cards(&cids).map(Into::into))
}
fn unbury_cards_in_current_deck(
&self,
input: pb::UnburyCardsInCurrentDeckIn,
) -> Result<pb::Empty> {
fn unbury_deck(&self, input: pb::UnburyDeckIn) -> Result<pb::OpChanges> {
self.with_col(|col| {
col.unbury_cards_in_current_deck(input.mode())
col.unbury_deck(input.deck_id.into(), input.mode())
.map(Into::into)
})
}

View file

@ -5,9 +5,7 @@ use std::collections::HashMap;
use super::{CardGenContext, Notetype};
use crate::{
collection::Collection,
error::Result,
match_all,
prelude::*,
search::{Node, SortMode, TemplateKind},
};

View file

@ -12,6 +12,7 @@ pub use crate::{
decks::{Deck, DeckId, DeckKind, NativeDeckName},
error::{AnkiError, Result},
i18n::I18n,
match_all, match_any,
notes::{Note, NoteId},
notetype::{Notetype, NotetypeId},
ops::{Op, OpChanges, OpOutput},

View file

@ -4,15 +4,12 @@
use super::timing::SchedTimingToday;
use crate::{
backend_proto::{
bury_or_suspend_cards_in::Mode as BuryOrSuspendMode,
unbury_cards_in_current_deck_in::Mode as UnburyDeckMode,
bury_or_suspend_cards_in::Mode as BuryOrSuspendMode, unbury_deck_in::Mode as UnburyDeckMode,
},
card::{Card, CardId, CardQueue},
collection::Collection,
card::CardQueue,
config::SchedulerVersion,
error::Result,
prelude::*,
search::SortMode,
search::{SortMode, StateKind},
};
impl Card {
@ -73,14 +70,14 @@ impl Collection {
})
}
pub fn unbury_cards_in_current_deck(&mut self, mode: UnburyDeckMode) -> Result<()> {
let search = match mode {
UnburyDeckMode::All => "is:buried",
UnburyDeckMode::UserOnly => "is:buried-manually",
UnburyDeckMode::SchedOnly => "is:buried-sibling",
pub fn unbury_deck(&mut self, deck_id: DeckId, mode: UnburyDeckMode) -> Result<OpOutput<()>> {
let state = match mode {
UnburyDeckMode::All => StateKind::Buried,
UnburyDeckMode::UserOnly => StateKind::UserBuried,
UnburyDeckMode::SchedOnly => StateKind::SchedBuried,
};
self.transact_no_undo(|col| {
col.search_cards_into_table(&format!("deck:current {}", search), SortMode::NoOrder)?;
self.transact(Op::UnburyUnsuspend, |col| {
col.search_cards_into_table(match_all![deck_id, state], SortMode::NoOrder)?;
col.unsuspend_or_unbury_searched_cards()
})
}

View file

@ -8,9 +8,8 @@ use rand::seq::SliceRandom;
use crate::{
card::{CardQueue, CardType},
deckconfig::NewCardOrder,
match_all,
prelude::*,
search::{Node, SortMode, StateKind},
search::{SortMode, StateKind},
};
impl Card {

View file

@ -70,14 +70,14 @@ impl Node {
#[macro_export]
macro_rules! match_all {
($($param:expr),+ $(,)?) => {
Node::all(vec![$($param.into()),+])
$crate::search::Node::all(vec![$($param.into()),+])
};
}
#[macro_export]
macro_rules! match_any {
($($param:expr),+ $(,)?) => {
Node::any(vec![$($param.into()),+])
$crate::search::Node::any(vec![$($param.into()),+])
};
}