diff options
author | DLFW <daniel@llin.info> | 2021-12-17 01:42:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-16 19:42:35 -0500 |
commit | ae77a0fa7594dcf1a61954d0b0e2de7aac6961ce (patch) | |
tree | b0d72ae427c43b1f4515ea1be02cb92351de0ffa /src/context | |
parent | 2f3b4423a9e9c6f57bdf9e83052bbcda9ad121c1 (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.rs | 57 |
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); } } |