Fix desktop crate build; simplify tray/menu and telemetry reconnect

Real bugs found by actually compiling the Tauri crate for the first time:
- Cargo.toml declared a [lib] with no src/lib.rs (cargo refused to parse
  the manifest) — added the standard Tauri 2 main.rs/lib.rs split.
- generate_context!() needs real icon files; icons/ only had a .gitkeep.
  Added placeholder PNG/ICO/ICNS icons.

Also simplified: dropped the tray icon + menu (one more moving part not
needed yet), and the telemetry store's exponential backoff is now a fixed
3s retry, matching the same simplification made to continuum-proxy's
uplink client.

Fixed two real TS bugs while typechecking apps/web for the first time
(missing @types/node for nuxt.config.ts's process.env access, untyped
useFetch call inferring 'never'). Verified: cargo check (desktop),
vue-tsc --noEmit (web + ui packages) all clean.
This commit is contained in:
2026-08-28 18:33:40 +00:00
parent 4cb2e82a92
commit 9cb59d723e
15 changed files with 11910 additions and 46 deletions
+4751
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -9,7 +9,7 @@ rust-version = "1.77"
tauri-build = { version = "2.0", features = [] } tauri-build = { version = "2.0", features = [] }
[dependencies] [dependencies]
tauri = { version = "2.1", features = ["tray-icon"] } tauri = "2.1"
tauri-plugin-fs = "2.0" tauri-plugin-fs = "2.0"
tauri-plugin-shell = "2.0" tauri-plugin-shell = "2.0"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

+12
View File
@@ -0,0 +1,12 @@
// This is intentionally the plainest possible Tauri shell: load the two
// plugins the desktop app needs (filesystem access, opening external links)
// and show the window. A tray icon with a menu is a natural next addition
// once this makes sense — see Tauri's tray-icon docs when you're ready.
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_shell::init())
.run(tauri::generate_context!())
.expect("error while running the Continuum desktop shell");
}
+1 -34
View File
@@ -1,39 +1,6 @@
// Prevents an additional console window on Windows in release builds. // Prevents an additional console window on Windows in release builds.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::{
menu::{Menu, MenuItem},
tray::TrayIconBuilder,
Manager,
};
fn main() { fn main() {
tauri::Builder::default() continuum_desktop_lib::run();
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_shell::init())
.setup(|app| {
let show = MenuItem::with_id(app, "show", "Show Continuum", true, None::<&str>)?;
let quit = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
let menu = Menu::with_items(app, &[&show, &quit])?;
TrayIconBuilder::new()
.icon(app.default_window_icon().unwrap().clone())
.menu(&menu)
.tooltip("Continuum — print farm console")
.on_menu_event(|app, event| match event.id.as_ref() {
"show" => {
if let Some(window) = app.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
"quit" => app.exit(0),
_ => {}
})
.build(app)?;
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running the Continuum desktop shell");
} }
-4
View File
@@ -23,10 +23,6 @@
], ],
"security": { "security": {
"csp": null "csp": null
},
"trayIcon": {
"iconPath": "icons/icon.png",
"iconAsTemplate": true
} }
}, },
"bundle": { "bundle": {
+1
View File
@@ -21,6 +21,7 @@
"vue-router": "^4.4.3" "vue-router": "^4.4.3"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.7.4",
"typescript": "^5.6.2" "typescript": "^5.6.2"
} }
} }
+8 -1
View File
@@ -2,10 +2,17 @@
import { PrinterCard } from "@continuum/ui"; import { PrinterCard } from "@continuum/ui";
import { useTelemetryStore } from "~/stores/telemetry"; import { useTelemetryStore } from "~/stores/telemetry";
interface Printer {
id: string;
name: string;
model: string;
farmId: string;
}
const telemetry = useTelemetryStore(); const telemetry = useTelemetryStore();
const config = useRuntimeConfig(); const config = useRuntimeConfig();
const { data: printers } = await useFetch(`${config.public.apiBase}/printers`, { const { data: printers } = await useFetch<Printer[]>(`${config.public.apiBase}/printers`, {
headers: useRequestHeaders(["cookie"]), headers: useRequestHeaders(["cookie"]),
}); });
</script> </script>
+3 -6
View File
@@ -14,15 +14,15 @@ interface TelemetryState {
socket: WebSocket | null; socket: WebSocket | null;
connected: boolean; connected: boolean;
printers: Record<string, PrinterTelemetry>; printers: Record<string, PrinterTelemetry>;
reconnectAttempt: number;
} }
const RECONNECT_DELAY_MS = 3_000;
export const useTelemetryStore = defineStore("telemetry", { export const useTelemetryStore = defineStore("telemetry", {
state: (): TelemetryState => ({ state: (): TelemetryState => ({
socket: null, socket: null,
connected: false, connected: false,
printers: {}, printers: {},
reconnectAttempt: 0,
}), }),
getters: { getters: {
@@ -48,7 +48,6 @@ export const useTelemetryStore = defineStore("telemetry", {
socket.onopen = () => { socket.onopen = () => {
this.connected = true; this.connected = true;
this.reconnectAttempt = 0;
}; };
socket.onmessage = (event) => { socket.onmessage = (event) => {
@@ -65,9 +64,7 @@ export const useTelemetryStore = defineStore("telemetry", {
socket.onclose = () => { socket.onclose = () => {
this.connected = false; this.connected = false;
this.socket = null; this.socket = null;
const delay = Math.min(30_000, 1_000 * 2 ** this.reconnectAttempt); setTimeout(() => this.connect(), RECONNECT_DELAY_MS);
this.reconnectAttempt += 1;
setTimeout(() => this.connect(), delay);
}; };
socket.onerror = () => { socket.onerror = () => {
+7133
View File
File diff suppressed because it is too large Load Diff