diff --git a/pylib/anki/tags.py b/pylib/anki/tags.py index 2fd52375e..bb48e47c3 100644 --- a/pylib/anki/tags.py +++ b/pylib/anki/tags.py @@ -42,30 +42,14 @@ class TagManager: def register( self, tags: Collection[str], usn: Optional[int] = None, clear=False ) -> None: - if usn is None: - 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 - ) + print("tags.register() is deprecated and no longer works") def registerNotes(self, nids: Optional[List[int]] = None) -> None: - "Add any missing tags from notes to the tags list." - # when called without an argument, the old list is cleared first. - if nids: - lim = " where id in " + ids2str(nids) - clear = False - else: - lim = "" - clear = True - self.register( - self.col.backend.get_note_tags(nids), - clear=clear, - ) + "Clear unused tags and add any missing tags from notes to the tag list." + self.clear_unused_tags() + + def clear_unused_tags(self): + self.col.backend.clear_unused_tags() def byDeck(self, did, children=False) -> List[str]: basequery = "select n.tags from cards c, notes n WHERE c.nid = n.id" diff --git a/rslib/backend.proto b/rslib/backend.proto index 974e9d759..1bfecfbce 100644 --- a/rslib/backend.proto +++ b/rslib/backend.proto @@ -165,7 +165,6 @@ service BackendService { rpc RemoveNotes(RemoveNotesIn) returns (Empty); rpc AddNoteTags(AddNoteTagsIn) returns (UInt32); rpc UpdateNoteTags(UpdateNoteTagsIn) returns (UInt32); - rpc GetNoteTags(GetNoteTagsIn) returns (GetNoteTagsOut); rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteOut); rpc AfterNoteUpdates(AfterNoteUpdatesIn) returns (Empty); rpc FieldNamesForNotes(FieldNamesForNotesIn) returns (FieldNamesForNotesOut); @@ -208,10 +207,10 @@ service BackendService { // tags - rpc RegisterTags(RegisterTagsIn) returns (Bool); + rpc ClearUnusedTags(Empty) returns (Empty); rpc AllTags(Empty) returns (AllTagsOut); - rpc SetTagCollapsed(SetTagCollapsedIn) returns (Bool); - rpc ClearTag(String) returns (Bool); + rpc SetTagCollapsed(SetTagCollapsedIn) returns (Empty); + rpc ClearTag(String) returns (Empty); rpc TagTree(Empty) returns (TagTreeNode); // config/preferences @@ -811,13 +810,6 @@ message AddOrUpdateDeckConfigLegacyIn { bool preserve_usn_and_mtime = 2; } -message RegisterTagsIn { - string tags = 1; - bool preserve_usn = 2; - int32 usn = 3; - bool clear_first = 4; -} - message AllTagsOut { repeated Tag tags = 1; } @@ -950,14 +942,6 @@ message UpdateNoteTagsIn { bool regex = 4; } -message GetNoteTagsIn { - repeated int64 nids = 1; -} - -message GetNoteTagsOut { - repeated string tags = 1; -} - message CheckDatabaseOut { repeated string problems = 1; } diff --git a/rslib/src/backend/mod.rs b/rslib/src/backend/mod.rs index 170f978f9..15863b5dc 100644 --- a/rslib/src/backend/mod.rs +++ b/rslib/src/backend/mod.rs @@ -44,6 +44,7 @@ use crate::{ get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress, SyncActionRequired, SyncAuth, SyncMeta, SyncOutput, SyncStage, }, + tags::join_tags, template::RenderedNode, text::{escape_anki_wildcards, extract_av_tags, strip_av_tags, AVTag}, timestamp::TimestampSecs, @@ -974,14 +975,6 @@ impl BackendService for Backend { }) } - fn get_note_tags(&self, input: pb::GetNoteTagsIn) -> BackendResult { - 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 { let mut set = HashSet::with_capacity(4); for field in ¬e.fields { @@ -1360,34 +1353,32 @@ impl BackendService for Backend { Ok(pb::AllTagsOut { tags }) } - fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult { + fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult { self.with_col(|col| { col.transact(None, |col| { col.set_tag_collapsed(&input.name, input.collapsed)?; - Ok(pb::Bool { val: true }) + Ok(().into()) }) }) } - fn register_tags(&self, input: pb::RegisterTagsIn) -> BackendResult { + fn clear_unused_tags(&self, _input: pb::Empty) -> BackendResult { self.with_col(|col| { col.transact(None, |col| { - let usn = if input.preserve_usn { - Usn(input.usn) - } else { - col.usn()? - }; - col.register_tags(&input.tags, usn, input.clear_first) - .map(|val| pb::Bool { val }) + let old_tags = col.storage.all_tags()?; + let note_tags = join_tags(&col.storage.get_note_tags()?); + col.register_tags(¬e_tags, col.usn()?, true)?; + col.update_tags_collapse(old_tags)?; + Ok(().into()) }) }) } - fn clear_tag(&self, tag: pb::String) -> BackendResult { + fn clear_tag(&self, tag: pb::String) -> BackendResult { self.with_col(|col| { col.transact(None, |col| { col.storage.clear_tag(tag.val.as_str())?; - Ok(pb::Bool { val: true }) + Ok(().into()) }) }) } diff --git a/rslib/src/dbcheck.rs b/rslib/src/dbcheck.rs index 80cccbc30..ac76b0147 100644 --- a/rslib/src/dbcheck.rs +++ b/rslib/src/dbcheck.rs @@ -295,17 +295,8 @@ impl Collection { } } - 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, new.collapsed)?; - break; - } else if new.name.starts_with(&old.name) { - self.set_tag_collapsed(&old.name, old.collapsed)?; - } - } - } + // restore tags collapse state and re-register old tags that are parents of used ones + self.update_tags_collapse(old_tags)?; // if the collection is empty and the user has deleted all note types, ensure at least // one note type exists diff --git a/rslib/src/storage/note/mod.rs b/rslib/src/storage/note/mod.rs index e109d9f33..b2d582a93 100644 --- a/rslib/src/storage/note/mod.rs +++ b/rslib/src/storage/note/mod.rs @@ -158,17 +158,10 @@ impl super::SqliteStorage { } // get distinct note tags - pub(crate) fn get_note_tags(&self, nids: Vec) -> Result> { - if nids.is_empty() { - self.db - .prepare_cached("select distinct tags from notes")? - .query_and_then(NO_PARAMS, |r| Ok(r.get_raw(0).as_str()?.to_owned()))? - .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() - } + pub(crate) fn get_note_tags(&self) -> Result> { + self.db + .prepare_cached("select distinct tags from notes")? + .query_and_then(NO_PARAMS, |r| Ok(r.get_raw(0).as_str()?.to_owned()))? + .collect() } } diff --git a/rslib/src/tags.rs b/rslib/src/tags.rs index 6de9d2031..f7c61ace4 100644 --- a/rslib/src/tags.rs +++ b/rslib/src/tags.rs @@ -272,6 +272,22 @@ impl Collection { 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) -> 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( &mut self, nids: &[NoteID],