| 1 | //! The badge: what needs the person, on the app's icon and in the tray's |
| 2 | //! hover text. macOS and Linux draw a count on the icon; Windows has no |
| 3 | //! count, so it gets a lavender dot over the taskbar icon instead. |
| 4 | |
| 5 | use tauri::{AppHandle, Manager}; |
| 6 | |
| 7 | use crate::{WINDOW, config, tray}; |
| 8 | |
| 9 | pub fn set(app: &AppHandle, count: i64) { |
| 10 | *app.state::<config::State>().waiting.lock().unwrap() = count; |
| 11 | if let Some(window) = app.get_webview_window(WINDOW) { |
| 12 | #[cfg(target_os = "windows")] |
| 13 | let _ = window.set_overlay_icon(if count > 0 { Some(dot()) } else { None }); |
| 14 | #[cfg(not(target_os = "windows"))] |
| 15 | let _ = window.set_badge_count(if count > 0 { Some(count) } else { None }); |
| 16 | } |
| 17 | if let Some(tray) = app.tray_by_id(tray::TRAY) { |
| 18 | let text = match count { |
| 19 | 0 => "g1t".to_string(), |
| 20 | 1 => "g1t · 1 thing waiting for you".to_string(), |
| 21 | n => format!("g1t · {n} things waiting for you"), |
| 22 | }; |
| 23 | let _ = tray.set_tooltip(Some(text)); |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | /// A lavender dot with a dark edge, 32 pixels square, drawn here so |
| 28 | /// nothing needs loading. |
| 29 | #[cfg(target_os = "windows")] |
| 30 | fn dot() -> tauri::image::Image<'static> { |
| 31 | const SIZE: usize = 32; |
| 32 | let mut rgba = vec![0u8; SIZE * SIZE * 4]; |
| 33 | let centre = (SIZE as f32 - 1.0) / 2.0; |
| 34 | let radius = SIZE as f32 / 2.0; |
| 35 | for y in 0..SIZE { |
| 36 | for x in 0..SIZE { |
| 37 | let dx = x as f32 - centre; |
| 38 | let dy = y as f32 - centre; |
| 39 | let distance = (dx * dx + dy * dy).sqrt(); |
| 40 | // Lavender inside, a thin dark ring, then nothing; the edges blend. |
| 41 | let (colour, alpha) = if distance <= radius - 3.0 { |
| 42 | ([0xb6, 0xa8, 0xff], 1.0) |
| 43 | } else if distance <= radius - 0.5 { |
| 44 | ([0x0f, 0x0f, 0x11], 1.0) |
| 45 | } else if distance <= radius + 0.5 { |
| 46 | ([0x0f, 0x0f, 0x11], radius + 0.5 - distance) |
| 47 | } else { |
| 48 | ([0, 0, 0], 0.0) |
| 49 | }; |
| 50 | let at = (y * SIZE + x) * 4; |
| 51 | rgba[at] = colour[0]; |
| 52 | rgba[at + 1] = colour[1]; |
| 53 | rgba[at + 2] = colour[2]; |
| 54 | rgba[at + 3] = (alpha.clamp(0.0, 1.0) * 255.0) as u8; |
| 55 | } |
| 56 | } |
| 57 | tauri::image::Image::new_owned(rgba, SIZE as u32, SIZE as u32) |
| 58 | } |