feat(tray): "Restart to update" item and tooltip (#6)
Build Lotus Chat Desktop / prepare (push) Successful in 6s
Build Lotus Chat Desktop / build-windows (push) Successful in 32m18s
Build Lotus Chat Desktop / build-linux (push) Successful in 39m16s
Build Lotus Chat Desktop / build-arch (push) Successful in 17s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
Build Lotus Chat Desktop / prepare (push) Successful in 6s
Build Lotus Chat Desktop / build-windows (push) Successful in 32m18s
Build Lotus Chat Desktop / build-linux (push) Successful in 39m16s
Build Lotus Chat Desktop / build-arch (push) Successful in 17s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
`set_tray_update_ready(version | null)` inserts a "Restart to update (vX)" item at the top of the tray menu and sets the tooltip to "Lotus Chat — update ready"; null removes both. The item only exists while an update is pending. Clicking it reveals the window and emits `lotus-tray-install-update`, and cinny runs its normal install flow (progress, retries, failure toast). No icon dot: the unread dot already uses that corner. Bump cinny to 6edfe700 (the web half). Closes #6 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
96cdbcd512
commit
687642a096
+1
-1
Submodule cinny updated: d9e7f77402...6edfe70020
@@ -564,6 +564,53 @@ fn set_tray_unread(unread: bool, state: tauri::State<'_, TrayUnreadState>) -> Re
|
|||||||
state.tray.set_icon(Some(icon)).map_err(|e| e.to_string())
|
state.tray.set_icon(Some(icon)).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// cinny-desktop #6: the tray's "Restart to update" item. Inserted at the top
|
||||||
|
/// of the menu only while an update is available, so it isn't a dead entry the
|
||||||
|
/// rest of the time.
|
||||||
|
struct TrayUpdateState {
|
||||||
|
menu: Menu<tauri::Wry>,
|
||||||
|
item: MenuItem<tauri::Wry>,
|
||||||
|
shown: std::sync::Mutex<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Show (`Some(version)`) or clear (`None`) the tray's update affordance: the
|
||||||
|
/// menu item and the tooltip. The web client drives it from its update status,
|
||||||
|
/// and clicking the item hands the install back to the web flow
|
||||||
|
/// (`lotus-tray-install-update`) so progress and failures are shown in-app.
|
||||||
|
#[tauri::command]
|
||||||
|
fn set_tray_update_ready(app: tauri::AppHandle, version: Option<String>) -> Result<(), String> {
|
||||||
|
let Some(state) = app.try_state::<TrayUpdateState>() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let unread = app.try_state::<TrayUnreadState>();
|
||||||
|
let mut shown = state.shown.lock().map_err(|e| e.to_string())?;
|
||||||
|
match version {
|
||||||
|
Some(version) => {
|
||||||
|
state
|
||||||
|
.item
|
||||||
|
.set_text(format!("Restart to update (v{version})"))
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
if !*shown {
|
||||||
|
state.menu.insert(&state.item, 0).map_err(|e| e.to_string())?;
|
||||||
|
*shown = true;
|
||||||
|
}
|
||||||
|
if let Some(u) = unread {
|
||||||
|
let _ = u.tray.set_tooltip(Some("Lotus Chat — update ready"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if *shown {
|
||||||
|
state.menu.remove(&state.item).map_err(|e| e.to_string())?;
|
||||||
|
*shown = false;
|
||||||
|
}
|
||||||
|
if let Some(u) = unread {
|
||||||
|
let _ = u.tray.set_tooltip(Some("Lotus Chat"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Flash the taskbar button to draw attention (e.g. a new mention while the
|
/// Flash the taskbar button to draw attention (e.g. a new mention while the
|
||||||
/// window is unfocused). Clears automatically once the window is focused.
|
/// window is unfocused). Clears automatically once the window is focused.
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -611,6 +658,7 @@ pub fn run() {
|
|||||||
set_badge_count,
|
set_badge_count,
|
||||||
set_tray_unread,
|
set_tray_unread,
|
||||||
get_tray_dnd,
|
get_tray_dnd,
|
||||||
|
set_tray_update_ready,
|
||||||
flash_window,
|
flash_window,
|
||||||
focus_main_window,
|
focus_main_window,
|
||||||
send_notification,
|
send_notification,
|
||||||
@@ -695,6 +743,12 @@ pub fn run() {
|
|||||||
.on_menu_event(move |app, event| match event.id.as_ref() {
|
.on_menu_event(move |app, event| match event.id.as_ref() {
|
||||||
"open" => show_main(app),
|
"open" => show_main(app),
|
||||||
"quit" => app.exit(0),
|
"quit" => app.exit(0),
|
||||||
|
"update" => {
|
||||||
|
// Show the window so the download progress (and any
|
||||||
|
// failure) is visible; the web side runs the install.
|
||||||
|
show_main(app);
|
||||||
|
native::emit_to_web(app, "lotus-tray-install-update", "{}");
|
||||||
|
}
|
||||||
"dnd" => {
|
"dnd" => {
|
||||||
let checked = dnd_for_event.is_checked().unwrap_or(false);
|
let checked = dnd_for_event.is_checked().unwrap_or(false);
|
||||||
native::emit_to_web(
|
native::emit_to_web(
|
||||||
@@ -739,6 +793,12 @@ pub fn run() {
|
|||||||
// Keep a handle to the DND CheckMenuItem so `get_tray_dnd` can
|
// Keep a handle to the DND CheckMenuItem so `get_tray_dnd` can
|
||||||
// report its live checkstate for web re-hydration after reload.
|
// report its live checkstate for web re-hydration after reload.
|
||||||
app.manage(TrayDndState(dnd_item));
|
app.manage(TrayDndState(dnd_item));
|
||||||
|
|
||||||
|
app.manage(TrayUpdateState {
|
||||||
|
menu: tray_menu.clone(),
|
||||||
|
item: MenuItem::with_id(app, "update", "Restart to update", true, None::<&str>)?,
|
||||||
|
shown: std::sync::Mutex::new(false),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
eprintln!("tray: no bundled window icon; skipping system tray setup");
|
eprintln!("tray: no bundled window icon; skipping system tray setup");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user