From 9f38b1a4d3f526d0969beeec9332fc997fb98fcc Mon Sep 17 00:00:00 2001 From: David Buckley Date: Mon, 15 Nov 2021 19:01:28 -0500 Subject: [PATCH 1/2] allow identifier string to be searched --- crates/core/src/metadata.rs | 4 ++++ doc/MANUAL.md | 1 + 2 files changed, 5 insertions(+) diff --git a/crates/core/src/metadata.rs b/crates/core/src/metadata.rs index 4103d468..5ab8aa7a 100644 --- a/crates/core/src/metadata.rs +++ b/crates/core/src/metadata.rs @@ -468,6 +468,7 @@ pub struct BookQuery { pub edition: Option, pub volume: Option, pub number: Option, + pub identifier: Option, pub reading: Option, pub new: Option, pub finished: Option, @@ -501,6 +502,7 @@ impl BookQuery { Some('e') => { buf.reverse(); query.edition = make_query(&buf.join(" ")); buf.clear(); }, Some('v') => { buf.reverse(); query.volume = make_query(&buf.join(" ")); buf.clear(); }, Some('n') => { buf.reverse(); query.number = make_query(&buf.join(" ")); buf.clear(); }, + Some('i') => { buf.reverse(); query.identifier = make_query(&buf.join(" ")); buf.clear(); }, Some('R') => query.reading = Some(!invert), Some('N') => query.new = Some(!invert), Some('F') => query.finished = Some(!invert), @@ -540,6 +542,7 @@ impl BookQuery { query.edition.is_none() && query.volume.is_none() && query.number.is_none() && + query.identifier.is_none() && query.reading.is_none() && query.new.is_none() && query.finished.is_none() && @@ -571,6 +574,7 @@ impl BookQuery { self.edition.as_ref().map(|re| re.is_match(&info.edition)) != Some(false) && self.volume.as_ref().map(|re| re.is_match(&info.volume)) != Some(false) && self.number.as_ref().map(|re| re.is_match(&info.number)) != Some(false) && + self.identifier.as_ref().map(|re| re.is_match(&info.identifier)) != Some(false) && self.reading.as_ref().map(|eq| info.simple_status().eq(&SimpleStatus::Reading) == *eq) != Some(false) && self.new.as_ref().map(|eq| info.simple_status().eq(&SimpleStatus::New) == *eq) != Some(false) && self.finished.as_ref().map(|eq| info.simple_status().eq(&SimpleStatus::Finished) == *eq) != Some(false) && diff --git a/doc/MANUAL.md b/doc/MANUAL.md index 79601f18..80eb3d0a 100644 --- a/doc/MANUAL.md +++ b/doc/MANUAL.md @@ -52,6 +52,7 @@ The text that will be searched for is given after the selector. - *e*: edition. - *v*: volume. - *n*: number. +- *i*: identifier. ### State selectors From f293a3f096c01dd2be19c30fa73a20c35334545b Mon Sep 17 00:00:00 2001 From: David Buckley Date: Mon, 15 Nov 2021 22:33:39 -0500 Subject: [PATCH 2/2] add updateDocument event --- crates/core/src/emulator.rs | 1 + crates/core/src/library.rs | 27 +++++++++++++++++++++++++++ crates/core/src/view/home/mod.rs | 23 +++++++++++++++++++++++ crates/core/src/view/mod.rs | 1 + crates/plato/src/app.rs | 1 + 5 files changed, 53 insertions(+) diff --git a/crates/core/src/emulator.rs b/crates/core/src/emulator.rs index d5ac330a..3b8d95c2 100644 --- a/crates/core/src/emulator.rs +++ b/crates/core/src/emulator.rs @@ -543,6 +543,7 @@ fn main() -> Result<(), Error> { Event::CheckFetcher(..) | Event::FetcherAddDocument(..) | Event::FetcherRemoveDocument(..) | + Event::FetcherUpdateDocument(..) | Event::FetcherSearch { .. } if !view.is::() => { if let Some(home) = history.get_mut(0).filter(|view| view.is::()) { let (tx, _rx) = mpsc::channel(); diff --git a/crates/core/src/library.rs b/crates/core/src/library.rs index b26c6b2e..4f0d9d98 100644 --- a/crates/core/src/library.rs +++ b/crates/core/src/library.rs @@ -449,6 +449,33 @@ impl Library { Ok(()) } + pub fn update>(&mut self, path: P, info: Info) -> Result<(), Error> { + let full_path = self.home.join(path.as_ref()); + + let md = full_path.metadata()?; + let fp = self.paths.get(path.as_ref()).cloned().or_else(|| { + full_path.metadata().ok() + .and_then(|md| md.fingerprint(self.fat32_epoch).ok()) + }).ok_or_else(|| format_err!("can't get fingerprint of {}", path.as_ref().display()))?; + let fp2 = self.paths.get(path.as_ref()).cloned().ok_or_else(|| format_err!("can't get fingerprint of {}", path.as_ref().display()))?; + + println!("Update fingerprint for {}: {} → {}.", path.as_ref().display(), fp2, fp); + self.db.remove(&fp).unwrap(); + self.db.insert(fp, info); + self.db[&fp].file.size = md.len(); + self.paths.insert(path.as_ref().to_path_buf(), fp); + let rp1 = self.reading_state_path(fp2); + let rp2 = self.reading_state_path(fp); + fs::rename(rp1, rp2).ok(); + let tpp = self.thumbnail_preview_path(fp2); + if tpp.exists() { + fs::remove_file(tpp).ok(); + } + self.has_db_changed = true; + Ok(()) + } + + pub fn copy_to>(&mut self, path: P, other: &mut Library) -> Result<(), Error> { let src = self.home.join(path.as_ref()); diff --git a/crates/core/src/view/home/mod.rs b/crates/core/src/view/home/mod.rs index 0ca9563e..e67b34d3 100644 --- a/crates/core/src/view/home/mod.rs +++ b/crates/core/src/view/home/mod.rs @@ -1051,6 +1051,13 @@ impl Home { self.refresh_visibles(true, false, hub, rq, context); } + fn update_document(&mut self, path: &Path, info: Info, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) -> Result<(), Error> { + let full_path = context.library.home.join(path); + context.library.update(full_path, info)?; + self.refresh_visibles(true, false, hub, rq, context); + Ok(()) + } + fn set_status(&mut self, path: &Path, status: SimpleStatus, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) { context.library.set_status(path, status); @@ -1355,6 +1362,16 @@ impl Home { hub2.send(Event::FetcherRemoveDocument(id, PathBuf::from(path))).ok(); } }, + Some("updateDocument") => { + if let Some(info) = event.get("info") + .map(ToString::to_string) + .and_then(|v| serde_json::from_str(&v).ok()) { + if let Some(path) = event.get("path") + .and_then(JsonValue::as_str) { + hub2.send(Event::FetcherUpdateDocument(id, PathBuf::from(path), Box::new(info))).ok(); + } + } + }, Some("search") => { let path = event.get("path") .and_then(JsonValue::as_str) @@ -1638,6 +1655,12 @@ impl View for Home { .ok(); true }, + Event::FetcherUpdateDocument(_, ref path, ref info) => { + self.update_document(path, *info.clone(), hub, rq, context) + .map_err(|e| eprintln!("Can't remove document: {:#}.", e)) + .ok(); + true + }, Event::Select(EntryId::CopyTo(ref path, index)) => { self.copy_to(path, index, context) .map_err(|e| eprintln!("Can't copy document: {:#}.", e)) diff --git a/crates/core/src/view/mod.rs b/crates/core/src/view/mod.rs index 4efb369f..3a347b0d 100644 --- a/crates/core/src/view/mod.rs +++ b/crates/core/src/view/mod.rs @@ -333,6 +333,7 @@ pub enum Event { SearchResult(usize, Vec), FetcherAddDocument(u32, Box), FetcherRemoveDocument(u32, PathBuf), + FetcherUpdateDocument(u32, PathBuf, Box), FetcherSearch { id: u32, path: Option, diff --git a/crates/plato/src/app.rs b/crates/plato/src/app.rs index 912464df..1e735b11 100644 --- a/crates/plato/src/app.rs +++ b/crates/plato/src/app.rs @@ -948,6 +948,7 @@ pub fn run() -> Result<(), Error> { Event::CheckFetcher(..) | Event::FetcherAddDocument(..) | Event::FetcherRemoveDocument(..) | + Event::FetcherUpdateDocument(..) | Event::FetcherSearch { .. } if !view.is::() => { if let Some(entry) = history.get_mut(0).filter(|entry| entry.view.is::()) { let (tx, _rx) = mpsc::channel();