fix: Durchsuchen-Button, Tray-Icon, Minimize statt Close, .cloud Handler
1. Durchsuchen-Button: dialog:allow-open Permission in capabilities
2. Tray-Icon: Nutzt das App-Icon (32x32.png) statt leer
3. Close = Minimize: Fenster wird versteckt statt App beendet,
Doppelklick auf Tray-Icon oeffnet wieder
4. .cloud Datei-Handler:
- fileAssociations in tauri.conf.json registriert .cloud Extension
- NSIS-Installer registriert den Handler automatisch
- Doppelklick auf .cloud -> App startet, laedt Datei runter,
oeffnet mit Standard-App (Word/Excel/etc.)
- Wenn App laeuft: Event wird emitted, Frontend verarbeitet es
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,9 @@
|
|||||||
"windows": ["main"],
|
"windows": ["main"],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"core:default",
|
"core:default",
|
||||||
"opener:default"
|
"opener:default",
|
||||||
|
"dialog:default",
|
||||||
|
"dialog:allow-open",
|
||||||
|
"notification:default"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -402,13 +402,40 @@ pub fn run() {
|
|||||||
locked_files: Mutex::new(Vec::new()),
|
locked_files: Mutex::new(Vec::new()),
|
||||||
sync_paths: Mutex::new(Vec::new()),
|
sync_paths: Mutex::new(Vec::new()),
|
||||||
})
|
})
|
||||||
|
.on_window_event(|window, event| {
|
||||||
|
// Close button = minimize to tray instead of quit
|
||||||
|
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
|
||||||
|
api.prevent_close();
|
||||||
|
let _ = window.hide();
|
||||||
|
}
|
||||||
|
})
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let quit = MenuItem::with_id(app, "quit", "Beenden", true, None::<&str>)?;
|
let quit = MenuItem::with_id(app, "quit", "Beenden", true, None::<&str>)?;
|
||||||
let show = MenuItem::with_id(app, "show", "Oeffnen", true, None::<&str>)?;
|
let show = MenuItem::with_id(app, "show", "Oeffnen", true, None::<&str>)?;
|
||||||
let sync_now = MenuItem::with_id(app, "sync", "Jetzt synchronisieren", true, None::<&str>)?;
|
let sync_now = MenuItem::with_id(app, "sync", "Jetzt synchronisieren", true, None::<&str>)?;
|
||||||
let menu = Menu::with_items(app, &[&show, &sync_now, &quit])?;
|
let menu = Menu::with_items(app, &[&show, &sync_now, &quit])?;
|
||||||
|
|
||||||
|
// Use bundled icon for tray
|
||||||
|
let icon = app.default_window_icon().cloned()
|
||||||
|
.unwrap_or_else(|| tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png")).unwrap());
|
||||||
|
|
||||||
|
// Handle .cloud file opened via file association (double-click)
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() > 1 {
|
||||||
|
let file_arg = &args[1];
|
||||||
|
if file_arg.ends_with(".cloud") {
|
||||||
|
let cloud_path = file_arg.to_string();
|
||||||
|
let app_handle = app.handle().clone();
|
||||||
|
// Open the .cloud file after app is ready
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
std::thread::sleep(Duration::from_secs(2));
|
||||||
|
let _ = app_handle.emit("open-cloud-file", cloud_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TrayIconBuilder::new()
|
TrayIconBuilder::new()
|
||||||
|
.icon(icon)
|
||||||
.tooltip("Mini-Cloud Sync")
|
.tooltip("Mini-Cloud Sync")
|
||||||
.menu(&menu)
|
.menu(&menu)
|
||||||
.on_menu_event(|app, event| {
|
.on_menu_event(|app, event| {
|
||||||
@@ -424,6 +451,15 @@ pub fn run() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on_tray_icon_event(|tray, event| {
|
||||||
|
// Double-click on tray icon = show window
|
||||||
|
if let tauri::tray::TrayIconEvent::DoubleClick { .. } = event {
|
||||||
|
if let Some(w) = tray.app_handle().get_webview_window("main") {
|
||||||
|
let _ = w.show();
|
||||||
|
let _ = w.set_focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
.build(app)?;
|
.build(app)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -32,6 +32,20 @@
|
|||||||
"icons/128x128@2x.png",
|
"icons/128x128@2x.png",
|
||||||
"icons/icon.icns",
|
"icons/icon.icns",
|
||||||
"icons/icon.ico"
|
"icons/icon.ico"
|
||||||
]
|
],
|
||||||
|
"fileAssociations": [
|
||||||
|
{
|
||||||
|
"ext": ["cloud"],
|
||||||
|
"mimeType": "application/x-minicloud",
|
||||||
|
"description": "Mini-Cloud Platzhalter"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"windows": {
|
||||||
|
"nsis": {
|
||||||
|
"installerIcon": "icons/icon.ico",
|
||||||
|
"headerImage": null,
|
||||||
|
"sidebarImage": null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const newPathServerId = ref(null);
|
|||||||
const newPathMode = ref("virtual");
|
const newPathMode = ref("virtual");
|
||||||
const serverFolders = ref([]);
|
const serverFolders = ref([]);
|
||||||
|
|
||||||
let unlistenStatus, unlistenLog, unlistenError, unlistenFileChange, unlistenTrigger;
|
let unlistenStatus, unlistenLog, unlistenError, unlistenFileChange, unlistenTrigger, unlistenCloudOpen;
|
||||||
|
|
||||||
async function handleLogin() {
|
async function handleLogin() {
|
||||||
loginError.value = "";
|
loginError.value = "";
|
||||||
@@ -166,8 +166,18 @@ onMounted(async () => {
|
|||||||
fileChanges.value = [`[${ts()}] ${e.payload}`, ...fileChanges.value].slice(0, 50);
|
fileChanges.value = [`[${ts()}] ${e.payload}`, ...fileChanges.value].slice(0, 50);
|
||||||
});
|
});
|
||||||
unlistenTrigger = await listen("trigger-sync", () => syncNow());
|
unlistenTrigger = await listen("trigger-sync", () => syncNow());
|
||||||
|
unlistenCloudOpen = await listen("open-cloud-file", async (e) => {
|
||||||
|
const cloudPath = e.payload;
|
||||||
|
syncLog.value = [`[${ts()}] Oeffne: ${cloudPath}`, ...syncLog.value].slice(0, 200);
|
||||||
|
try {
|
||||||
|
const realPath = await invoke("open_cloud_file", { cloudPath });
|
||||||
|
syncLog.value = [`[${ts()}] Geoeffnet: ${realPath}`, ...syncLog.value].slice(0, 200);
|
||||||
|
} catch (err) {
|
||||||
|
syncLog.value = [`[${ts()}] Fehler: ${err}`, ...syncLog.value].slice(0, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
onUnmounted(() => { unlistenStatus?.(); unlistenLog?.(); unlistenError?.(); unlistenFileChange?.(); unlistenTrigger?.(); });
|
onUnmounted(() => { unlistenStatus?.(); unlistenLog?.(); unlistenError?.(); unlistenFileChange?.(); unlistenTrigger?.(); unlistenCloudOpen?.(); });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
Reference in New Issue
Block a user