Refactor code for clearing unused tags and saving collapse state

This commit is contained in:
abdo 2021-01-14 02:53:52 +03:00
parent 72e8f9d640
commit 9c1d7c522a
6 changed files with 43 additions and 84 deletions

View file

@ -42,30 +42,14 @@ class TagManager:
def register( def register(
self, tags: Collection[str], usn: Optional[int] = None, clear=False self, tags: Collection[str], usn: Optional[int] = None, clear=False
) -> None: ) -> None:
if usn is None: print("tags.register() is deprecated and no longer works")
preserve_usn = False
usn_ = 0
else:
usn_ = usn
preserve_usn = True
self.col.backend.register_tags(
tags=" ".join(tags), preserve_usn=preserve_usn, usn=usn_, clear_first=clear
)
def registerNotes(self, nids: Optional[List[int]] = None) -> None: def registerNotes(self, nids: Optional[List[int]] = None) -> None:
"Add any missing tags from notes to the tags list." "Clear unused tags and add any missing tags from notes to the tag list."
# when called without an argument, the old list is cleared first. self.clear_unused_tags()
if nids:
lim = " where id in " + ids2str(nids) def clear_unused_tags(self):
clear = False self.col.backend.clear_unused_tags()
else:
lim = ""
clear = True
self.register(
self.col.backend.get_note_tags(nids),
clear=clear,
)
def byDeck(self, did, children=False) -> List[str]: def byDeck(self, did, children=False) -> List[str]:
basequery = "select n.tags from cards c, notes n WHERE c.nid = n.id" basequery = "select n.tags from cards c, notes n WHERE c.nid = n.id"

View file

@ -165,7 +165,6 @@ service BackendService {
rpc RemoveNotes(RemoveNotesIn) returns (Empty); rpc RemoveNotes(RemoveNotesIn) returns (Empty);
rpc AddNoteTags(AddNoteTagsIn) returns (UInt32); rpc AddNoteTags(AddNoteTagsIn) returns (UInt32);
rpc UpdateNoteTags(UpdateNoteTagsIn) returns (UInt32); rpc UpdateNoteTags(UpdateNoteTagsIn) returns (UInt32);
rpc GetNoteTags(GetNoteTagsIn) returns (GetNoteTagsOut);
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteOut); rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteOut);
rpc AfterNoteUpdates(AfterNoteUpdatesIn) returns (Empty); rpc AfterNoteUpdates(AfterNoteUpdatesIn) returns (Empty);
rpc FieldNamesForNotes(FieldNamesForNotesIn) returns (FieldNamesForNotesOut); rpc FieldNamesForNotes(FieldNamesForNotesIn) returns (FieldNamesForNotesOut);
@ -208,10 +207,10 @@ service BackendService {
// tags // tags
rpc RegisterTags(RegisterTagsIn) returns (Bool); rpc ClearUnusedTags(Empty) returns (Empty);
rpc AllTags(Empty) returns (AllTagsOut); rpc AllTags(Empty) returns (AllTagsOut);
rpc SetTagCollapsed(SetTagCollapsedIn) returns (Bool); rpc SetTagCollapsed(SetTagCollapsedIn) returns (Empty);
rpc ClearTag(String) returns (Bool); rpc ClearTag(String) returns (Empty);
rpc TagTree(Empty) returns (TagTreeNode); rpc TagTree(Empty) returns (TagTreeNode);
// config/preferences // config/preferences
@ -811,13 +810,6 @@ message AddOrUpdateDeckConfigLegacyIn {
bool preserve_usn_and_mtime = 2; bool preserve_usn_and_mtime = 2;
} }
message RegisterTagsIn {
string tags = 1;
bool preserve_usn = 2;
int32 usn = 3;
bool clear_first = 4;
}
message AllTagsOut { message AllTagsOut {
repeated Tag tags = 1; repeated Tag tags = 1;
} }
@ -950,14 +942,6 @@ message UpdateNoteTagsIn {
bool regex = 4; bool regex = 4;
} }
message GetNoteTagsIn {
repeated int64 nids = 1;
}
message GetNoteTagsOut {
repeated string tags = 1;
}
message CheckDatabaseOut { message CheckDatabaseOut {
repeated string problems = 1; repeated string problems = 1;
} }

View file

@ -44,6 +44,7 @@ use crate::{
get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress, get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress,
SyncActionRequired, SyncAuth, SyncMeta, SyncOutput, SyncStage, SyncActionRequired, SyncAuth, SyncMeta, SyncOutput, SyncStage,
}, },
tags::join_tags,
template::RenderedNode, template::RenderedNode,
text::{escape_anki_wildcards, extract_av_tags, strip_av_tags, AVTag}, text::{escape_anki_wildcards, extract_av_tags, strip_av_tags, AVTag},
timestamp::TimestampSecs, timestamp::TimestampSecs,
@ -974,14 +975,6 @@ impl BackendService for Backend {
}) })
} }
fn get_note_tags(&self, input: pb::GetNoteTagsIn) -> BackendResult<pb::GetNoteTagsOut> {
self.with_col(|col| {
Ok(pb::GetNoteTagsOut {
tags: col.storage.get_note_tags(to_nids(input.nids))?,
})
})
}
fn cloze_numbers_in_note(&self, note: pb::Note) -> BackendResult<pb::ClozeNumbersInNoteOut> { fn cloze_numbers_in_note(&self, note: pb::Note) -> BackendResult<pb::ClozeNumbersInNoteOut> {
let mut set = HashSet::with_capacity(4); let mut set = HashSet::with_capacity(4);
for field in &note.fields { for field in &note.fields {
@ -1360,34 +1353,32 @@ impl BackendService for Backend {
Ok(pb::AllTagsOut { tags }) Ok(pb::AllTagsOut { tags })
} }
fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult<pb::Bool> { fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult<pb::Empty> {
self.with_col(|col| { self.with_col(|col| {
col.transact(None, |col| { col.transact(None, |col| {
col.set_tag_collapsed(&input.name, input.collapsed)?; col.set_tag_collapsed(&input.name, input.collapsed)?;
Ok(pb::Bool { val: true }) Ok(().into())
}) })
}) })
} }
fn register_tags(&self, input: pb::RegisterTagsIn) -> BackendResult<pb::Bool> { fn clear_unused_tags(&self, _input: pb::Empty) -> BackendResult<pb::Empty> {
self.with_col(|col| { self.with_col(|col| {
col.transact(None, |col| { col.transact(None, |col| {
let usn = if input.preserve_usn { let old_tags = col.storage.all_tags()?;
Usn(input.usn) let note_tags = join_tags(&col.storage.get_note_tags()?);
} else { col.register_tags(&note_tags, col.usn()?, true)?;
col.usn()? col.update_tags_collapse(old_tags)?;
}; Ok(().into())
col.register_tags(&input.tags, usn, input.clear_first)
.map(|val| pb::Bool { val })
}) })
}) })
} }
fn clear_tag(&self, tag: pb::String) -> BackendResult<pb::Bool> { fn clear_tag(&self, tag: pb::String) -> BackendResult<pb::Empty> {
self.with_col(|col| { self.with_col(|col| {
col.transact(None, |col| { col.transact(None, |col| {
col.storage.clear_tag(tag.val.as_str())?; col.storage.clear_tag(tag.val.as_str())?;
Ok(pb::Bool { val: true }) Ok(().into())
}) })
}) })
} }

View file

@ -295,17 +295,8 @@ impl Collection {
} }
} }
let new_tags = self.storage.all_tags_sorted()?; // restore tags collapse state and re-register old tags that are parents of used ones
for old in old_tags.into_iter() { self.update_tags_collapse(old_tags)?;
for new in new_tags.iter() {
if new.name == old.name {
self.storage.set_tag_collapsed(&new.name, new.collapsed)?;
break;
} else if new.name.starts_with(&old.name) {
self.set_tag_collapsed(&old.name, old.collapsed)?;
}
}
}
// if the collection is empty and the user has deleted all note types, ensure at least // if the collection is empty and the user has deleted all note types, ensure at least
// one note type exists // one note type exists

View file

@ -158,17 +158,10 @@ impl super::SqliteStorage {
} }
// get distinct note tags // get distinct note tags
pub(crate) fn get_note_tags(&self, nids: Vec<NoteID>) -> Result<Vec<String>> { pub(crate) fn get_note_tags(&self) -> Result<Vec<String>> {
if nids.is_empty() { self.db
self.db .prepare_cached("select distinct tags from notes")?
.prepare_cached("select distinct tags from notes")? .query_and_then(NO_PARAMS, |r| Ok(r.get_raw(0).as_str()?.to_owned()))?
.query_and_then(NO_PARAMS, |r| Ok(r.get_raw(0).as_str()?.to_owned()))? .collect()
.collect()
} else {
self.db
.prepare_cached("select distinct tags from notes where id in ?")?
.query_and_then(nids, |r| Ok(r.get_raw(0).as_str()?.to_owned()))?
.collect()
}
} }
} }

View file

@ -272,6 +272,22 @@ impl Collection {
self.storage.set_tag_collapsed(name, collapsed) self.storage.set_tag_collapsed(name, collapsed)
} }
/// Update collapse state of existing tags and register tags in old_tags that are parents of those tags
pub(crate) fn update_tags_collapse(&self, old_tags: Vec<Tag>) -> Result<()> {
let new_tags = self.storage.all_tags_sorted()?;
for old in old_tags.into_iter() {
for new in new_tags.iter() {
if new.name == old.name {
self.storage.set_tag_collapsed(&new.name, old.collapsed)?;
break;
} else if new.name.starts_with(&old.name) {
self.set_tag_collapsed(&old.name, old.collapsed)?;
}
}
}
Ok(())
}
fn replace_tags_for_notes_inner<R: Replacer>( fn replace_tags_for_notes_inner<R: Replacer>(
&mut self, &mut self,
nids: &[NoteID], nids: &[NoteID],