feat(desktop): Windows taskbar overlay icon for unread badge
Red-dot overlay drawn as raw RGBA (no extra resource bundled). Shown on Windows when unread count > 0, cleared when 0. macOS keeps numeric Dock badge; Linux has no cross-DE badge API. Bumps version 0.10.0 -> 0.10.1.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@chat-app/desktop",
|
"name": "@chat-app/desktop",
|
||||||
"version": "0.10.0",
|
"version": "0.10.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Tauri v2 desktop client (Windows / macOS / Linux)",
|
"description": "Tauri v2 desktop client (Windows / macOS / Linux)",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
Generated
+1
-1
@@ -726,7 +726,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chat-app-desktop"
|
name = "chat-app-desktop"
|
||||||
version = "0.10.0"
|
version = "0.10.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"dryoc",
|
"dryoc",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "chat-app-desktop"
|
name = "chat-app-desktop"
|
||||||
version = "0.10.0"
|
version = "0.10.1"
|
||||||
description = "ChatApp desktop client"
|
description = "ChatApp desktop client"
|
||||||
authors = ["Dennis"]
|
authors = ["Dennis"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -22,6 +22,33 @@ struct TrayUnreadPayload {
|
|||||||
count: u32,
|
count: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Red-dot overlay icon for the Windows taskbar. Drawn as raw RGBA instead of
|
||||||
|
// shipping a PNG so we don't add another resource to the bundle. Kept small
|
||||||
|
// (32x32) since Windows scales the overlay down anyway.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn unread_overlay_rgba() -> Vec<u8> {
|
||||||
|
const SIZE: u32 = 32;
|
||||||
|
let r = SIZE as f32 / 2.0;
|
||||||
|
let mut buf = Vec::with_capacity((SIZE * SIZE * 4) as usize);
|
||||||
|
for y in 0..SIZE {
|
||||||
|
for x in 0..SIZE {
|
||||||
|
let dx = x as f32 - r + 0.5;
|
||||||
|
let dy = y as f32 - r + 0.5;
|
||||||
|
let d = (dx * dx + dy * dy).sqrt();
|
||||||
|
let edge = r - 1.0;
|
||||||
|
if d <= edge {
|
||||||
|
buf.extend_from_slice(&[0xDC, 0x26, 0x26, 0xFF]);
|
||||||
|
} else if d <= r {
|
||||||
|
let alpha = (255.0 * (r - d)).clamp(0.0, 255.0) as u8;
|
||||||
|
buf.extend_from_slice(&[0xDC, 0x26, 0x26, alpha]);
|
||||||
|
} else {
|
||||||
|
buf.extend_from_slice(&[0, 0, 0, 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
fn show_main_window(app: &AppHandle) {
|
fn show_main_window(app: &AppHandle) {
|
||||||
if let Some(win) = app.get_webview_window("main") {
|
if let Some(win) = app.get_webview_window("main") {
|
||||||
@@ -171,9 +198,9 @@ pub fn run() {
|
|||||||
format!("ChatApp · {} neu", payload.count)
|
format!("ChatApp · {} neu", payload.count)
|
||||||
};
|
};
|
||||||
let _ = tray_handle.set_tooltip(Some(tooltip));
|
let _ = tray_handle.set_tooltip(Some(tooltip));
|
||||||
// Dock/taskbar badge. `set_badge_label` is macOS-only.
|
// Dock/taskbar badge. macOS uses a numeric label; Windows uses
|
||||||
// Windows taskbar uses an overlay icon (different API).
|
// an overlay icon (red dot = unread). Linux has no cross-DE
|
||||||
// Linux has no cross-DE badge API — skip.
|
// badge API — skip.
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if let Some(win) = badge_window.as_ref() {
|
if let Some(win) = badge_window.as_ref() {
|
||||||
let badge = if payload.count == 0 {
|
let badge = if payload.count == 0 {
|
||||||
@@ -183,7 +210,17 @@ pub fn run() {
|
|||||||
};
|
};
|
||||||
let _ = win.set_badge_label(badge);
|
let _ = win.set_badge_label(badge);
|
||||||
}
|
}
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(target_os = "windows")]
|
||||||
|
if let Some(win) = badge_window.as_ref() {
|
||||||
|
if payload.count == 0 {
|
||||||
|
let _ = win.set_overlay_icon(None);
|
||||||
|
} else {
|
||||||
|
let rgba = unread_overlay_rgba();
|
||||||
|
let img = tauri::image::Image::new_owned(rgba, 32, 32);
|
||||||
|
let _ = win.set_overlay_icon(Some(img));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||||
let _ = &badge_window;
|
let _ = &badge_window;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "ChatApp",
|
"productName": "ChatApp",
|
||||||
"version": "0.10.0",
|
"version": "0.10.1",
|
||||||
"identifier": "com.meinname.chatapp",
|
"identifier": "com.meinname.chatapp",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "pnpm vite:dev",
|
"beforeDevCommand": "pnpm vite:dev",
|
||||||
|
|||||||
Reference in New Issue
Block a user