feat(windows): implement explorer shell integration, auto drive allocation, auto-open, and system tray icon

This commit is contained in:
2026-09-08 10:04:24 +02:00
parent 1c8a860184
commit 38df3d3845
6 changed files with 561 additions and 23 deletions
+57 -8
View File
@@ -81,6 +81,8 @@ pub async fn mount_container(
drive_letter: char,
requested_port: Option<u16>,
auth: ContainerAuth,
open_explorer: bool,
enable_tray: bool,
) -> Result<()> {
let drive_str = format_drive(drive_letter);
@@ -207,6 +209,45 @@ pub async fn mount_container(
return Err(e);
}
// Optional automatisch im Windows Explorer öffnen
if open_explorer {
let _ = crate::windows::open_in_explorer(drive_letter);
}
// System-Tray Initialisierung
let (tray_shutdown_tx, mut tray_shutdown_rx) = tokio::sync::mpsc::channel::<()>(1);
#[cfg(windows)]
let _tray = if enable_tray {
let icon_source = crate::windows::get_default_system_icon()
.unwrap_or(tray_item::IconSource::Resource(""));
let title = format!("Sanctum ({drive_str})");
match tray_item::TrayItem::new(&title, icon_source) {
Ok(mut tray) => {
let container_name = container_path
.file_name()
.unwrap_or_default()
.to_string_lossy()
.to_string();
let _ = tray.add_label(&format!("Sanctum: {drive_str} ({container_name})"));
let dl = drive_letter;
let _ = tray.add_menu_item("Im Explorer öffnen", move || {
let _ = crate::windows::open_in_explorer(dl);
});
let s_tx = tray_shutdown_tx.clone();
let _ = tray.add_menu_item("Trennen & Beenden", move || {
let _ = s_tx.blocking_send(());
});
Some(tray)
}
Err(e) => {
debug!("System-Tray Icon konnte nicht erstellt werden: {e}");
None
}
}
} else {
None
};
println!();
println!("┌─────────────────────────────────────────────────────────────┐");
println!("│ ✔ Sanctum Container erfolgreich gemountet │");
@@ -215,17 +256,25 @@ pub async fn mount_container(
println!(" • Container: {}", container_path.display());
println!(" • Netzlaufwerk: {} (im Windows Explorer bereit)", ui::cyan(&drive_str));
println!(" • WebDAV-URL: http://127.0.0.1:{}/", bound_port);
if enable_tray {
println!(" • System-Tray: Icon aktiv (Rechtsklick für Explorer/Trennen)");
}
println!();
println!(" [{}] Drücke [Ctrl+C] zum sicheren Trennen und Schließen.", ui::yellow("Tipp"));
println!(" [{}] Drücke [Ctrl+C] oder nutze das Tray-Icon zum Beenden.", ui::yellow("Tipp"));
println!();
// Warten auf Strg+C
tokio::signal::ctrl_c()
.await
.context("Fehler beim Registrieren des Ctrl+C Signalhandlers")?;
println!();
println!(" {} Beendigungssignal (Ctrl+C) empfangen.", ui::yellow("[!]"));
// Warten auf Strg+C ODER Signal aus dem System-Tray
tokio::select! {
res = tokio::signal::ctrl_c() => {
let _ = res;
println!();
println!(" {} Beendigungssignal (Ctrl+C) empfangen.", ui::yellow("[!]"));
}
_ = tray_shutdown_rx.recv() => {
println!();
println!(" {} Beendigungssignal aus System-Tray empfangen.", ui::yellow("[!]"));
}
}
print!(" {} Trenne Windows-Netzlaufwerk {} ... ", ui::dim("[-]"), drive_str);
let _ = std::io::Write::flush(&mut std::io::stdout());