mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Merge pull request #1138 from RumovZ/introduced
Add search keyword for "first review in x days"
This commit is contained in:
commit
2cc23ce2bc
7 changed files with 53 additions and 4 deletions
|
@ -146,6 +146,7 @@ browsing-studied-today = Studied
|
|||
browsing-added-today = Added
|
||||
browsing-again-today = Again
|
||||
browsing-edited-today = Edited
|
||||
browsing-sidebar-first-review = First Review
|
||||
browsing-sidebar-due-today = Due
|
||||
browsing-sidebar-untagged = Untagged
|
||||
browsing-sidebar-overdue = Overdue
|
||||
|
|
|
@ -513,6 +513,12 @@ class SidebarTreeView(QTreeView):
|
|||
type=type,
|
||||
search_node=SearchNode(rated=SearchNode.Rated(days=1)),
|
||||
)
|
||||
root.add_simple(
|
||||
name=tr.browsing_sidebar_first_review(),
|
||||
icon=icon,
|
||||
type=type,
|
||||
search_node=SearchNode(introduced_in_days=1),
|
||||
)
|
||||
root.add_simple(
|
||||
name=tr.browsing_again_today(),
|
||||
icon=icon,
|
||||
|
|
|
@ -872,6 +872,7 @@ message SearchNode {
|
|||
int32 due_on_day = 16;
|
||||
string tag = 17;
|
||||
string note = 18;
|
||||
uint32 introduced_in_days = 19;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ impl TryFrom<pb::SearchNode> for Node {
|
|||
ease: rated.rating().into(),
|
||||
}),
|
||||
Filter::AddedInDays(u) => Node::Search(SearchNode::AddedInDays(u)),
|
||||
Filter::IntroducedInDays(u) => Node::Search(SearchNode::IntroducedInDays(u)),
|
||||
Filter::DueInDays(i) => Node::Search(SearchNode::Property {
|
||||
operator: "<=".to_string(),
|
||||
kind: PropertyKind::Due(i),
|
||||
|
|
|
@ -74,6 +74,7 @@ pub enum SearchNode {
|
|||
CardTemplate(TemplateKind),
|
||||
Deck(String),
|
||||
DeckId(DeckId),
|
||||
IntroducedInDays(u32),
|
||||
NotetypeId(NotetypeId),
|
||||
Notetype(String),
|
||||
Rated {
|
||||
|
@ -334,6 +335,7 @@ fn search_node_for_text_with_argument<'a>(
|
|||
"prop" => parse_prop(val)?,
|
||||
"added" => parse_added(val)?,
|
||||
"edited" => parse_edited(val)?,
|
||||
"introduced" => parse_introduced(val)?,
|
||||
"rated" => parse_rated(val)?,
|
||||
"is" => parse_state(val)?,
|
||||
"did" => parse_did(val)?,
|
||||
|
@ -528,6 +530,11 @@ fn parse_edited(s: &str) -> ParseResult<SearchNode> {
|
|||
parse_u32(s, "edited:").map(|n| SearchNode::EditedInDays(n.max(1)))
|
||||
}
|
||||
|
||||
/// eg introduced:1
|
||||
fn parse_introduced(s: &str) -> ParseResult<SearchNode> {
|
||||
parse_u32(s, "introduced:").map(|n| SearchNode::IntroducedInDays(n.max(1)))
|
||||
}
|
||||
|
||||
/// eg rated:3 or rated:10:2
|
||||
/// second arg must be between 1-4
|
||||
fn parse_rated(s: &str) -> ParseResult<SearchNode> {
|
||||
|
|
|
@ -129,6 +129,7 @@ impl SqlWriter<'_> {
|
|||
// other
|
||||
SearchNode::AddedInDays(days) => self.write_added(*days)?,
|
||||
SearchNode::EditedInDays(days) => self.write_edited(*days)?,
|
||||
SearchNode::IntroducedInDays(days) => self.write_introduced(*days)?,
|
||||
SearchNode::CardTemplate(template) => match template {
|
||||
TemplateKind::Ordinal(_) => self.write_template(template),
|
||||
TemplateKind::Name(name) => {
|
||||
|
@ -479,20 +480,37 @@ impl SqlWriter<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_added(&mut self, days: u32) -> Result<()> {
|
||||
fn previous_day_cutoff(&mut self, days_back: u32) -> Result<TimestampSecs> {
|
||||
let timing = self.col.timing_today()?;
|
||||
let cutoff = (timing.next_day_at.0 - (86_400 * (days as i64))) * 1_000;
|
||||
Ok(timing.next_day_at.adding_secs(-86_400 * days_back as i64))
|
||||
}
|
||||
|
||||
fn write_added(&mut self, days: u32) -> Result<()> {
|
||||
let cutoff = self.previous_day_cutoff(days)?.as_millis();
|
||||
write!(self.sql, "c.id > {}", cutoff).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_edited(&mut self, days: u32) -> Result<()> {
|
||||
let timing = self.col.timing_today()?;
|
||||
let cutoff = timing.next_day_at.0 - (86_400 * (days as i64));
|
||||
let cutoff = self.previous_day_cutoff(days)?;
|
||||
write!(self.sql, "n.mod > {}", cutoff).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_introduced(&mut self, days: u32) -> Result<()> {
|
||||
let cutoff = self.previous_day_cutoff(days)?.as_millis();
|
||||
write!(
|
||||
self.sql,
|
||||
concat!(
|
||||
"(select min(id) > {cutoff} from revlog where cid = c.id)",
|
||||
"and c.id in (select cid from revlog where id > {cutoff})"
|
||||
),
|
||||
cutoff = cutoff,
|
||||
)
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_regex(&mut self, word: &str) {
|
||||
self.sql.push_str("n.flds regexp ?");
|
||||
self.args.push(format!(r"(?i){}", word));
|
||||
|
@ -547,6 +565,7 @@ impl SearchNode {
|
|||
fn required_table(&self) -> RequiredTable {
|
||||
match self {
|
||||
SearchNode::AddedInDays(_) => RequiredTable::Cards,
|
||||
SearchNode::IntroducedInDays(_) => RequiredTable::Cards,
|
||||
SearchNode::Deck(_) => RequiredTable::Cards,
|
||||
SearchNode::DeckId(_) => RequiredTable::Cards,
|
||||
SearchNode::Rated { .. } => RequiredTable::Cards,
|
||||
|
@ -652,6 +671,19 @@ mod test {
|
|||
);
|
||||
assert_eq!(s(ctx, "added:0").0, s(ctx, "added:1").0,);
|
||||
|
||||
// introduced
|
||||
assert_eq!(
|
||||
s(ctx, "introduced:3").0,
|
||||
format!(
|
||||
concat!(
|
||||
"((select min(id) > {cutoff} from revlog where cid = c.id)",
|
||||
"and c.id in (select cid from revlog where id > {cutoff}))"
|
||||
),
|
||||
cutoff = (timing.next_day_at.0 - (86_400 * 3)) * 1_000,
|
||||
)
|
||||
);
|
||||
assert_eq!(s(ctx, "introduced:0").0, s(ctx, "introduced:1").0,);
|
||||
|
||||
// deck
|
||||
assert_eq!(
|
||||
s(ctx, "deck:default"),
|
||||
|
|
|
@ -84,6 +84,7 @@ fn write_search_node(node: &SearchNode) -> String {
|
|||
SingleField { field, text, is_re } => write_single_field(field, text, *is_re),
|
||||
AddedInDays(u) => format!("added:{}", u),
|
||||
EditedInDays(u) => format!("edited:{}", u),
|
||||
IntroducedInDays(u) => format!("introduced:{}", u),
|
||||
CardTemplate(t) => write_template(t),
|
||||
Deck(s) => maybe_quote(&format!("deck:{}", s)),
|
||||
DeckId(DeckIdType(i)) => format!("did:{}", i),
|
||||
|
|
Loading…
Reference in a new issue