Skip to content

Commit

Permalink
feat: Implement Badging API (#11661)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahqsoftwares authored Nov 20, 2024
1 parent a09e48e commit 020ea05
Show file tree
Hide file tree
Showing 14 changed files with 345 additions and 7 deletions.
11 changes: 11 additions & 0 deletions .changes/overlay.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion crates/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
58 changes: 57 additions & 1 deletion crates/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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>),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -3431,7 +3488,6 @@ fn handle_user_message<T: UserEvent>(
}
#[cfg(target_os = "ios")]
{
use tao::platform::ios::WindowExtIOS;
use wry::WebViewExtIOS;

f(Webview {
Expand Down
18 changes: 18 additions & 0 deletions crates/tauri-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions crates/tauri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
78 changes: 78 additions & 0 deletions crates/tauri/permissions/window/autogenerated/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri/scripts/bundle.global.js

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions crates/tauri/src/test/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
26 changes: 26 additions & 0 deletions crates/tauri/src/webview/webview_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 38 additions & 0 deletions crates/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions crates/tauri/src/window/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
Loading

0 comments on commit 020ea05

Please sign in to comment.