Implement file change watching and tray menu to trigger backup
This commit is contained in:
commit
dc557ec780
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
2940
Cargo.lock
generated
Normal file
2940
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "obsidian-git-backup"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
winit = "0.30.8"
|
||||
notify = "8.0.0"
|
||||
tray-icon = "0.19.2"
|
||||
git2 = "0.20.0"
|
||||
134
src/main.rs
Normal file
134
src/main.rs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
use notify::{Event, RecursiveMode, Watcher};
|
||||
use std::path::Path;
|
||||
use std::time::{Duration, Instant};
|
||||
use tray_icon::{
|
||||
menu::{Menu, MenuId, MenuItem},
|
||||
Icon, TrayIconBuilder,
|
||||
};
|
||||
use winit::event::StartCause;
|
||||
use winit::{
|
||||
application::ApplicationHandler,
|
||||
event::WindowEvent,
|
||||
event_loop::{ActiveEventLoop, ControlFlow, EventLoop},
|
||||
};
|
||||
|
||||
enum UserEvent {
|
||||
MenuEvent(tray_icon::menu::MenuEvent),
|
||||
FileEvent(Event),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct App {
|
||||
tray_icon: Option<tray_icon::TrayIcon>,
|
||||
menu_push_now_id: Option<MenuId>,
|
||||
menu_exit_id: Option<MenuId>,
|
||||
last_change_time: Option<Instant>,
|
||||
duration_threshold: Duration,
|
||||
}
|
||||
|
||||
impl ApplicationHandler<UserEvent> for App {
|
||||
fn resumed(&mut self, _event_loop: &ActiveEventLoop) {
|
||||
// Create and show the tray icon
|
||||
let menu_item_push_now = MenuItem::new("Push Now", true, None);
|
||||
let menu_item_exit = MenuItem::new("Exit", true, None);
|
||||
|
||||
let tray_menu = Menu::new();
|
||||
tray_menu.append(&menu_item_push_now).unwrap();
|
||||
tray_menu.append(&menu_item_exit).unwrap();
|
||||
|
||||
let icon_path = Path::new("D:/Dev/obsidian-git-backup/sync.ico");
|
||||
let icon = Icon::from_path(icon_path, None).unwrap();
|
||||
let tray_icon = TrayIconBuilder::new()
|
||||
.with_menu(Box::new(tray_menu))
|
||||
.with_tooltip("Obsidian Git Backup")
|
||||
.with_icon(icon)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
self.tray_icon = Some(tray_icon);
|
||||
self.menu_push_now_id = Some(menu_item_push_now.id().clone());
|
||||
self.menu_exit_id = Some(menu_item_exit.id().clone());
|
||||
|
||||
// Set the duration threshold (e.g., 5 minutes)
|
||||
self.last_change_time = None;
|
||||
self.duration_threshold = Duration::from_secs(15);
|
||||
}
|
||||
|
||||
fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) {
|
||||
match event {
|
||||
UserEvent::MenuEvent(menu_event) => {
|
||||
match menu_event.id() {
|
||||
id if id == self.menu_push_now_id.as_ref().unwrap() => {
|
||||
// Handle push now menu item
|
||||
self.last_change_time = None;
|
||||
backup_changes();
|
||||
}
|
||||
id if id == self.menu_exit_id.as_ref().unwrap() => {
|
||||
// Handle exit menu item
|
||||
event_loop.exit();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
UserEvent::FileEvent(_event) => {
|
||||
println!("File change detected");
|
||||
self.last_change_time = Some(Instant::now());
|
||||
println!("At: {:?}", self.last_change_time.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_events(&mut self, event_loop: &ActiveEventLoop, _cause: StartCause) {
|
||||
let now = Instant::now();
|
||||
|
||||
// Backup changes if last file change time exceeded threshold
|
||||
if let Some(last_change_time) = self.last_change_time {
|
||||
if now.duration_since(last_change_time) > self.duration_threshold {
|
||||
self.last_change_time = None;
|
||||
backup_changes();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset timer
|
||||
event_loop.set_control_flow(ControlFlow::WaitUntil(now + Duration::from_secs(5)));
|
||||
}
|
||||
|
||||
fn window_event(
|
||||
&mut self,
|
||||
_event_loop: &ActiveEventLoop,
|
||||
_window_id: winit::window::WindowId,
|
||||
_event: WindowEvent,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
fn backup_changes() {
|
||||
println!("Backup changes started");
|
||||
println!("Checking for changes...");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::<UserEvent>::with_user_event().build().unwrap();
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
|
||||
// Set up menu event handler
|
||||
let proxy = event_loop.create_proxy();
|
||||
tray_icon::menu::MenuEvent::set_event_handler(Some(move |event| {
|
||||
let _ = proxy.send_event(UserEvent::MenuEvent(event));
|
||||
}));
|
||||
|
||||
// Set up file change event handler
|
||||
let proxy = event_loop.create_proxy();
|
||||
let repo_path = Path::new("D:/test/obsidian-vault-test");
|
||||
let mut watcher = notify::recommended_watcher(move |event| {
|
||||
if let Ok(event) = event {
|
||||
let _ = proxy.send_event(UserEvent::FileEvent(event));
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
watcher.watch(repo_path, RecursiveMode::Recursive).unwrap();
|
||||
|
||||
// Start event loop
|
||||
let mut app = App::default();
|
||||
let _ = event_loop.run_app(&mut app);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user