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(
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"

View file

@ -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;
}

View file

@ -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<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> {
let mut set = HashSet::with_capacity(4);
for field in &note.fields {
@ -1360,34 +1353,32 @@ impl BackendService for Backend {
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| {
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<pb::Bool> {
fn clear_unused_tags(&self, _input: pb::Empty) -> BackendResult<pb::Empty> {
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(&note_tags, col.usn()?, true)?;
col.update_tags_collapse(old_tags)?;
Ok(().into())
})
})
}
fn clear_tag(&self, tag: pb::String) -> BackendResult<pb::Bool> {
fn clear_tag(&self, tag: pb::String) -> BackendResult<pb::Empty> {
self.with_col(|col| {
col.transact(None, |col| {
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()?;
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

View file

@ -158,17 +158,10 @@ impl super::SqliteStorage {
}
// get distinct note tags
pub(crate) fn get_note_tags(&self, nids: Vec<NoteID>) -> Result<Vec<String>> {
if nids.is_empty() {
pub(crate) fn get_note_tags(&self) -> Result<Vec<String>> {
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()
}
}
}

View file

@ -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<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>(
&mut self,
nids: &[NoteID],