mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-02-06 15:56:51 +00:00
feat: Implement Badging API (#11661)
This commit is contained in:
parent
a09e48e396
commit
020ea05561
11
.changes/overlay.md
Normal file
11
.changes/overlay.md
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
"tauri": minor:feat
|
||||
"tauri-runtime-wry": minor:feat
|
||||
"tauri-runtime": minor:feat
|
||||
'@tauri-apps/api': minor:feat
|
||||
---
|
||||
|
||||
Add badging APIs:
|
||||
- `Window/WebviewWindow::set_badge_count` for Linux, macOS and IOS.
|
||||
- `Window/WebviewWindow::set_overlay_icon` for Windows Only.
|
||||
- `Window/WebviewWindow::set_badge_label`for macOS Only.
|
||||
@ -23,7 +23,7 @@ wry = { version = "0.47", default-features = false, features = [
|
||||
"os-webview",
|
||||
"linux-body",
|
||||
] }
|
||||
tao = { version = "0.30.6", default-features = false, features = ["rwh_06"] }
|
||||
tao = { version = "0.30.8", default-features = false, features = ["rwh_06"] }
|
||||
tauri-runtime = { version = "2.2.0", path = "../tauri-runtime" }
|
||||
tauri-utils = { version = "2.1.0", path = "../tauri-utils" }
|
||||
raw-window-handle = "0.6"
|
||||
|
||||
@ -95,6 +95,8 @@ use wry::{
|
||||
)))]
|
||||
use wry::{WebViewBuilderExtUnix, WebViewExtUnix};
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
pub use tao::platform::ios::WindowExtIOS;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use tao::platform::macos::{
|
||||
ActivationPolicy as TaoActivationPolicy, EventLoopExtMacOS, WindowExtMacOS,
|
||||
@ -1263,6 +1265,9 @@ pub enum WindowMessage {
|
||||
SetCursorIcon(CursorIcon),
|
||||
SetCursorPosition(Position),
|
||||
SetIgnoreCursorEvents(bool),
|
||||
SetBadgeCount(Option<i64>, Option<String>),
|
||||
SetBadgeLabel(Option<String>),
|
||||
SetOverlayIcon(Option<TaoIcon>),
|
||||
SetProgressBar(ProgressBarState),
|
||||
SetTitleBarStyle(tauri_utils::TitleBarStyle),
|
||||
SetTheme(Option<Theme>),
|
||||
@ -2125,6 +2130,32 @@ impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
|
||||
)
|
||||
}
|
||||
|
||||
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) -> Result<()> {
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::Window(
|
||||
self.window_id,
|
||||
WindowMessage::SetBadgeCount(count, desktop_filename),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn set_badge_label(&self, label: Option<String>) -> Result<()> {
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::Window(self.window_id, WindowMessage::SetBadgeLabel(label)),
|
||||
)
|
||||
}
|
||||
|
||||
fn set_overlay_icon(&self, icon: Option<Icon>) -> Result<()> {
|
||||
let icon: Result<Option<TaoIcon>> = icon.map_or(Ok(None), |x| Ok(Some(TaoIcon::try_from(x)?)));
|
||||
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::Window(self.window_id, WindowMessage::SetOverlayIcon(icon?)),
|
||||
)
|
||||
}
|
||||
|
||||
fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()> {
|
||||
send_user_message(
|
||||
&self.context,
|
||||
@ -3096,6 +3127,32 @@ fn handle_user_message<T: UserEvent>(
|
||||
WindowMessage::RequestRedraw => {
|
||||
window.request_redraw();
|
||||
}
|
||||
WindowMessage::SetBadgeCount(_count, _desktop_filename) => {
|
||||
#[cfg(target_os = "ios")]
|
||||
window.set_badge_count(
|
||||
_count.map_or(0, |x| x.clamp(i32::MIN as i64, i32::MAX as i64) as i32),
|
||||
);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
window.set_badge_label(_count.map(|x| x.to_string()));
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
window.set_badge_count(_count, _desktop_filename);
|
||||
}
|
||||
WindowMessage::SetBadgeLabel(_label) => {
|
||||
#[cfg(target_os = "macos")]
|
||||
window.set_badge_label(_label);
|
||||
}
|
||||
WindowMessage::SetOverlayIcon(_icon) => {
|
||||
#[cfg(windows)]
|
||||
window.set_overlay_icon(_icon.map(|x| x.0).as_ref());
|
||||
}
|
||||
WindowMessage::SetProgressBar(progress_state) => {
|
||||
window.set_progress_bar(ProgressBarStateWrapper::from(progress_state).0);
|
||||
}
|
||||
@ -3431,7 +3488,6 @@ fn handle_user_message<T: UserEvent>(
|
||||
}
|
||||
#[cfg(target_os = "ios")]
|
||||
{
|
||||
use tao::platform::ios::WindowExtIOS;
|
||||
use wry::WebViewExtIOS;
|
||||
|
||||
f(Webview {
|
||||
|
||||
@ -816,6 +816,24 @@ pub trait WindowDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 's
|
||||
/// Starts resize-dragging the window.
|
||||
fn start_resize_dragging(&self, direction: ResizeDirection) -> Result<()>;
|
||||
|
||||
/// Sets the badge count on the taskbar
|
||||
/// The badge count appears as a whole for the application
|
||||
/// Using `0` or using `None` will remove the badge
|
||||
///
|
||||
/// ## Platform-specific
|
||||
/// - **Windows:** Unsupported, use [`WindowDispatch::set_overlay_icon`] instead.
|
||||
/// - **Android:** Unsupported.
|
||||
/// - **iOS:** iOS expects i32, if the value is larger than i32::MAX, it will be clamped to i32::MAX.
|
||||
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) -> Result<()>;
|
||||
|
||||
/// Sets the badge count on the taskbar **macOS only**. Using `None` will remove the badge
|
||||
fn set_badge_label(&self, label: Option<String>) -> Result<()>;
|
||||
|
||||
/// Sets the overlay icon on the taskbar **Windows only**. Using `None` will remove the icon
|
||||
///
|
||||
/// The overlay icon can be unique for each window.
|
||||
fn set_overlay_icon(&self, icon: Option<Icon>) -> Result<()>;
|
||||
|
||||
/// Sets the taskbar progress state.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
|
||||
@ -105,6 +105,9 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
|
||||
("start_dragging", false),
|
||||
("start_resize_dragging", false),
|
||||
("set_progress_bar", false),
|
||||
("set_badge_count", false),
|
||||
("set_overlay_icon", false),
|
||||
("set_badge_label", false),
|
||||
("set_icon", false),
|
||||
("set_title_bar_style", false),
|
||||
("set_theme", false),
|
||||
|
||||
@ -898,6 +898,58 @@ Denies the set_always_on_top command without any pre-configured scope.
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-badge-count`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the set_badge_count command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:deny-set-badge-count`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the set_badge_count command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-badge-label`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the set_badge_label command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:deny-set-badge-label`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the set_badge_label command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-closable`
|
||||
|
||||
</td>
|
||||
@ -1340,6 +1392,32 @@ Denies the set_minimizable command without any pre-configured scope.
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-overlay-icon`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the set_overlay_icon command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:deny-set-overlay-icon`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the set_overlay_icon command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-position`
|
||||
|
||||
</td>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -977,6 +977,18 @@ impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_badge_label(&self, label: Option<String>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_overlay_icon(&self, icon: Option<Icon<'_>>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1716,6 +1716,32 @@ impl<R: Runtime> WebviewWindow<R> {
|
||||
self.window.start_dragging()
|
||||
}
|
||||
|
||||
/// Sets the overlay icon on the taskbar **Windows only**. Using `None` will remove the icon
|
||||
///
|
||||
/// The overlay icon can be unique for each window.
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg_attr(docsrs, doc(cfg(target_os = "windows")))]
|
||||
pub fn set_overlay_icon(&self, icon: Option<Image<'_>>) -> crate::Result<()> {
|
||||
self.window.set_overlay_icon(icon)
|
||||
}
|
||||
|
||||
/// Sets the taskbar badge count. Using `0` or `None` will remove the badge
|
||||
///
|
||||
/// ## Platform-specific
|
||||
/// - **Windows:** Unsupported, use [`WebviewWindow::set_overlay_icon`] instead.
|
||||
/// - **iOS:** iOS expects i32, the value will be clamped to i32::MIN, i32::MAX.
|
||||
/// - **Android:** Unsupported.
|
||||
pub fn set_badge_count(&self, count: Option<i64>) -> crate::Result<()> {
|
||||
self.window.set_badge_count(count)
|
||||
}
|
||||
|
||||
/// Sets the taskbar badge label **macOS only**. Using `None` will remove the badge
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
|
||||
pub fn set_badge_label(&self, label: Option<String>) -> crate::Result<()> {
|
||||
self.window.set_badge_label(label)
|
||||
}
|
||||
|
||||
/// Sets the taskbar progress state.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
|
||||
@ -2014,6 +2014,44 @@ tauri::Builder::default()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Sets the overlay icon on the taskbar **Windows only**. Using `None` to remove the overlay icon
|
||||
///
|
||||
/// The overlay icon can be unique for each window.
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg_attr(docsrs, doc(cfg(target_os = "windows")))]
|
||||
pub fn set_overlay_icon(&self, icon: Option<Image<'_>>) -> crate::Result<()> {
|
||||
self
|
||||
.window
|
||||
.dispatcher
|
||||
.set_overlay_icon(icon.map(|x| x.into()))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Sets the taskbar badge count. Using `0` or `None` will remove the badge
|
||||
///
|
||||
/// ## Platform-specific
|
||||
/// - **Windows:** Unsupported, use [`Window::set_overlay_icon`] instead.
|
||||
/// - **iOS:** iOS expects i32, the value will be clamped to i32::MIN, i32::MAX.
|
||||
/// - **Android:** Unsupported.
|
||||
pub fn set_badge_count(&self, count: Option<i64>) -> crate::Result<()> {
|
||||
self
|
||||
.window
|
||||
.dispatcher
|
||||
.set_badge_count(count, Some(format!("{}.desktop", self.package_info().name)))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Sets the taskbar badge label **macOS only**. Using `None` will remove the badge
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
|
||||
pub fn set_badge_label(&self, label: Option<String>) -> crate::Result<()> {
|
||||
self
|
||||
.window
|
||||
.dispatcher
|
||||
.set_badge_label(label)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Sets the taskbar progress state.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
|
||||
@ -138,12 +138,34 @@ mod desktop_commands {
|
||||
setter!(start_dragging);
|
||||
setter!(start_resize_dragging, ResizeDirection);
|
||||
setter!(set_progress_bar, ProgressBarState);
|
||||
setter!(set_badge_count, Option<i64>);
|
||||
#[cfg(target_os = "macos")]
|
||||
setter!(set_badge_label, Option<String>);
|
||||
setter!(set_visible_on_all_workspaces, bool);
|
||||
setter!(set_title_bar_style, TitleBarStyle);
|
||||
setter!(set_size_constraints, WindowSizeConstraints);
|
||||
setter!(set_theme, Option<Theme>);
|
||||
setter!(set_enabled, bool);
|
||||
|
||||
#[command(root = "crate")]
|
||||
#[cfg(target_os = "windows")]
|
||||
pub async fn set_overlay_icon<R: Runtime>(
|
||||
webview: Webview<R>,
|
||||
window: Window<R>,
|
||||
label: Option<String>,
|
||||
value: Option<crate::image::JsImage>,
|
||||
) -> crate::Result<()> {
|
||||
let window = get_window(window, label)?;
|
||||
let resources_table = webview.resources_table();
|
||||
|
||||
let value = match value {
|
||||
Some(value) => Some(value.into_img(&resources_table)?.as_ref().clone()),
|
||||
None => None,
|
||||
};
|
||||
|
||||
window.set_overlay_icon(value).map_err(Into::into)
|
||||
}
|
||||
|
||||
#[command(root = "crate")]
|
||||
pub async fn set_icon<R: Runtime>(
|
||||
webview: Webview<R>,
|
||||
@ -290,7 +312,12 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
desktop_commands::set_ignore_cursor_events,
|
||||
desktop_commands::start_dragging,
|
||||
desktop_commands::start_resize_dragging,
|
||||
desktop_commands::set_badge_count,
|
||||
#[cfg(target_os = "macos")]
|
||||
desktop_commands::set_badge_label,
|
||||
desktop_commands::set_progress_bar,
|
||||
#[cfg(target_os = "windows")]
|
||||
desktop_commands::set_overlay_icon,
|
||||
desktop_commands::set_icon,
|
||||
desktop_commands::set_visible_on_all_workspaces,
|
||||
desktop_commands::set_background_color,
|
||||
|
||||
@ -56,7 +56,6 @@
|
||||
"globals": "^15.4.0",
|
||||
"rollup": "4.27.3",
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^8.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1605,6 +1605,79 @@ class Window {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the badge count. It is app wide and not specific to this window.
|
||||
*
|
||||
* #### Platform-specific
|
||||
*
|
||||
* - **Windows**: Unsupported. Use @{linkcode Window.setOverlayIcon} instead.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
* await getCurrentWindow().setBadgeCount(5);
|
||||
* ```
|
||||
*
|
||||
* @param count The badge count. Use `undefined` to remove the badge.
|
||||
* @return A promise indicating the success or failure of the operation.
|
||||
*/
|
||||
async setBadgeCount(count?: number): Promise<void> {
|
||||
return invoke('plugin:window|set_badge_count', {
|
||||
label: this.label,
|
||||
value: count
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the badge cont **macOS only**.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
* await getCurrentWindow().setBadgeLabel("Hello");
|
||||
* ```
|
||||
*
|
||||
* @param label The badge label. Use `undefined` to remove the badge.
|
||||
* @return A promise indicating the success or failure of the operation.
|
||||
*/
|
||||
async setBadgeLabel(label?: string): Promise<void> {
|
||||
return invoke('plugin:window|set_badge_label', {
|
||||
label: this.label,
|
||||
value: label
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the overlay icon. **Windows only**
|
||||
* The overlay icon can be set for every window.
|
||||
*
|
||||
*
|
||||
* Note that you may need the `image-ico` or `image-png` Cargo features to use this API.
|
||||
* To enable it, change your Cargo.toml file:
|
||||
*
|
||||
* ```toml
|
||||
* [dependencies]
|
||||
* tauri = { version = "...", features = ["...", "image-png"] }
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
* await getCurrentWindow().setOverlayIcon("/tauri/awesome.png");
|
||||
* ```
|
||||
*
|
||||
* @param icon Icon bytes or path to the icon file. Use `undefined` to remove the overlay icon.
|
||||
* @return A promise indicating the success or failure of the operation.
|
||||
*/
|
||||
async setOverlayIcon(
|
||||
icon?: string | Image | Uint8Array | ArrayBuffer | number[]
|
||||
): Promise<void> {
|
||||
return invoke('plugin:window|set_overlay_icon', {
|
||||
label: this.label,
|
||||
value: icon ? transformImage(icon) : undefined
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the taskbar progress state.
|
||||
*
|
||||
|
||||
@ -95,9 +95,6 @@ importers:
|
||||
tslib:
|
||||
specifier: ^2.6.3
|
||||
version: 2.8.1
|
||||
typescript:
|
||||
specifier: ^5.4.5
|
||||
version: 5.6.3
|
||||
typescript-eslint:
|
||||
specifier: ^8.1.0
|
||||
version: 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user