summaryrefslogtreecommitdiffstats
path: root/src/context
diff options
context:
space:
mode:
authorDLFW <daniel@llin.info>2021-12-17 01:42:35 +0100
committerGitHub <noreply@github.com>2021-12-16 19:42:35 -0500
commitae77a0fa7594dcf1a61954d0b0e2de7aac6961ce (patch)
treeb0d72ae427c43b1f4515ea1be02cb92351de0ffa /src/context
parent2f3b4423a9e9c6f57bdf9e83052bbcda9ad121c1 (diff)
Update view on filesystem changes (#112)
* Update view on filesystem changes AppContext owns an INotifyWatcher, which watches the visible directories (max. three). The list of directories to watch is updated on every event. If a filesystem change is announced, a "soft-update" of the current view is issued. * Specific "watchers" for Linux and MacOS For supervision of filesystem changes, specific `notify::Watcher` implementations are used for Linux and MacOS. Builds will likely fail for other OSes as `notify::recommended_watcher` may return some specific watcher implementation but the code just expects a `NullWatcher`. * remove dead code
Diffstat (limited to 'src/context')
-rw-r--r--src/context/app_context.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/context/app_context.rs b/src/context/app_context.rs
index 4834a36..07620b3 100644
--- a/src/context/app_context.rs
+++ b/src/context/app_context.rs
@@ -7,6 +7,8 @@ use crate::context::{
use crate::event::{AppEvent, Events};
use crate::util::search::SearchPattern;
use crate::Args;
+use notify::{RecursiveMode, Watcher};
+use std::path;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum QuitType {
@@ -39,6 +41,15 @@ pub struct AppContext {
preview_context: PreviewContext,
// context related to command line
commandline_context: CommandLineContext,
+ // filesystem watcher to inform about changes in shown directories
+ #[cfg(target_os = "linux")]
+ watcher: notify::INotifyWatcher,
+ #[cfg(target_os = "macos")]
+ watcher: notify::FsEventWatcher,
+ #[cfg(not(any(target_os = "linux", target_os = "macos")))]
+ watcher: notify::NullWatcher,
+ // list of watched paths; seems not to be possible to get them from a notify::Watcher
+ watched_paths: Vec<path::PathBuf>,
}
impl AppContext {
@@ -48,6 +59,17 @@ impl AppContext {
let mut commandline_context = CommandLineContext::new();
commandline_context.history_mut().set_max_len(20);
+
+ let event_tx_for_fs_notification = event_tx.clone();
+ let watcher = notify::recommended_watcher(move |res| match res {
+ Ok(event) => {
+ let _ = event_tx_for_fs_notification.send(AppEvent::Filesystem(event));
+ }
+ Err(_) => {}
+ })
+ .unwrap();
+ let watched_paths: Vec<path::PathBuf> = Vec::with_capacity(3);
+
Self {
quit: QuitType::DoNot,
events,
@@ -60,6 +82,41 @@ impl AppContext {
preview_context: PreviewContext::new(),
commandline_context,
config,
+ watcher,
+ watched_paths,
+ }
+ }
+
+ pub fn update_watcher(&mut self) {
+ // collect the paths that shall be watched...
+ let mut new_paths_to_watch: Vec<path::PathBuf> = Vec::with_capacity(3);
+ if let Some(dir_list) = self.tab_context_ref().curr_tab_ref().curr_list_ref() {
+ new_paths_to_watch.push(dir_list.file_path().to_path_buf())
+ }
+ if let Some(dir_list) = self.tab_context_ref().curr_tab_ref().parent_list_ref() {
+ new_paths_to_watch.push(dir_list.file_path().to_path_buf())
+ }
+ if let Some(dir_list) = self.tab_context_ref().curr_tab_ref().child_list_ref() {
+ new_paths_to_watch.push(dir_list.file_path().to_path_buf())
+ }
+ // remove paths from watcher which don't need to be watched anymore...
+ for old_watched_path in &self.watched_paths {
+ if !new_paths_to_watch.contains(&old_watched_path) {
+ let _ = self.watcher.unwatch(old_watched_path.as_path());
+ }
+ }
+ // add paths to watcher which need to be watched...
+ for new_watched_path in &new_paths_to_watch {
+ if !self.watched_paths.contains(&new_watched_path) {
+ let _ = self
+ .watcher
+ .watch(new_watched_path.as_path(), RecursiveMode::NonRecursive);
+ }
+ }
+ // update own list of watched paths
+ self.watched_paths.clear();
+ for new_watched_path in new_paths_to_watch {
+ self.watched_paths.push(new_watched_path);
}
}