mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-10-26 09:58:16 +03:00
feat: add notification sound (#7269)
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.studio> Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
parent
c272e4afbf
commit
6c408b736c
6
.changes/notification-sound.md
Normal file
6
.changes/notification-sound.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
'tauri': 'minor:feat'
|
||||
'@tauri-apps/api': 'minor:feat'
|
||||
---
|
||||
|
||||
Add option to specify notification sound.
|
5
.github/workflows/check-generated-files.yml
vendored
5
.github/workflows/check-generated-files.yml
vendored
@ -32,7 +32,6 @@ jobs:
|
||||
filters: |
|
||||
api:
|
||||
- 'tooling/api/src/**'
|
||||
- 'tooling/api/docs/js-api.json'
|
||||
- 'core/tauri/scripts/bundle.global.js'
|
||||
schema:
|
||||
- 'core/tauri-utils/src/config.rs'
|
||||
@ -50,9 +49,7 @@ jobs:
|
||||
working-directory: tooling/api
|
||||
run: yarn && yarn build
|
||||
- name: check api
|
||||
run: |
|
||||
git restore tooling/api/docs/js-api.json
|
||||
./.scripts/ci/has-diff.sh
|
||||
run: ./.scripts/ci/has-diff.sh
|
||||
|
||||
schema:
|
||||
runs-on: ubuntu-latest
|
||||
|
2
.github/workflows/test-core.yml
vendored
2
.github/workflows/test-core.yml
vendored
@ -99,7 +99,7 @@ jobs:
|
||||
cargo update -p is-terminal --precise 0.4.7
|
||||
cargo update -p colored --precise 2.0.2
|
||||
cargo update -p tempfile --precise 3.6.0
|
||||
cargo update -p serde_with:3.1.0 --precise 3.0.0
|
||||
cargo update -p serde_with:3.2.0 --precise 3.0.0
|
||||
|
||||
- name: test
|
||||
run: cargo test --target ${{ matrix.platform.target }} ${{ matrix.features.args }}
|
||||
|
@ -9,5 +9,4 @@ dist
|
||||
/tooling/cli/templates
|
||||
/tooling/cli/node
|
||||
/tooling/cli/schema.json
|
||||
/tooling/api/docs/js-api.json
|
||||
/core/tauri-config-schema/schema.json
|
||||
|
@ -103,7 +103,7 @@ objc = "0.2"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
webview2-com = "0.19.1"
|
||||
win7-notifications = { version = "0.3.1", optional = true }
|
||||
win7-notifications = { version = "0.4", optional = true }
|
||||
|
||||
[target."cfg(windows)".dependencies.windows]
|
||||
version = "0.39.0"
|
||||
|
@ -40,6 +40,50 @@ pub struct Notification {
|
||||
icon: Option<String>,
|
||||
/// The notification identifier
|
||||
identifier: String,
|
||||
/// The notification sound
|
||||
sound: Option<Sound>,
|
||||
}
|
||||
|
||||
/// Notification sound.
|
||||
#[derive(Debug)]
|
||||
pub enum Sound {
|
||||
/// The default notification sound.
|
||||
Default,
|
||||
/// A custom notification sound.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// Each OS has a different sound name so you will need to conditionally specify an appropriate sound
|
||||
/// based on the OS in use, for a list of sounds see:
|
||||
/// - **Linux**: can be one of the sounds listed in <https://0pointer.de/public/sound-naming-spec.html>
|
||||
/// - **Windows**: can be one of the sounds listed in <https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-audio>
|
||||
/// but without the prefix, for example, if `ms-winsoundevent:Notification.Default` you would use `Default` and
|
||||
/// if `ms-winsoundevent:Notification.Looping.Alarm2`, you would use `Alarm2`.
|
||||
/// Windows 7 is not supported, if a sound is provided, it will play the default sound, otherwise it will be silent.
|
||||
/// - **macOS**: you can specify the name of the sound you'd like to play when the notification is shown.
|
||||
/// Any of the default sounds (under System Preferences > Sound) can be used, in addition to custom sound files.
|
||||
/// Be sure that the sound file is under one of the following locations:
|
||||
/// - `~/Library/Sounds`
|
||||
/// - `/Library/Sounds`
|
||||
/// - `/Network/Library/Sounds`
|
||||
/// - `/System/Library/Sounds`
|
||||
///
|
||||
/// See the [`NSSound`] docs for more information.
|
||||
///
|
||||
/// [`NSSound`]: https://developer.apple.com/documentation/appkit/nssound
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
impl From<String> for Sound {
|
||||
fn from(value: String) -> Self {
|
||||
Self::Custom(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Sound {
|
||||
fn from(value: &str) -> Self {
|
||||
Self::Custom(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Notification {
|
||||
@ -72,6 +116,15 @@ impl Notification {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the notification sound. By default the notification has no sound.
|
||||
///
|
||||
/// See [`Sound`] for more information.
|
||||
#[must_use]
|
||||
pub fn sound(mut self, sound: impl Into<Sound>) -> Self {
|
||||
self.sound.replace(sound.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Shows the notification.
|
||||
///
|
||||
/// # Examples
|
||||
@ -108,6 +161,17 @@ impl Notification {
|
||||
} else {
|
||||
notification.auto_icon();
|
||||
}
|
||||
if let Some(sound) = self.sound {
|
||||
notification.sound_name(&match sound {
|
||||
#[cfg(target_os = "macos")]
|
||||
Sound::Default => "NSUserNotificationDefaultSoundName".to_string(),
|
||||
#[cfg(windows)]
|
||||
Sound::Default => "Default".to_string(),
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
Sound::Default => "message-new-instant".to_string(),
|
||||
Sound::Custom(c) => c,
|
||||
});
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let exe = tauri_utils::platform::current_exe()?;
|
||||
@ -191,6 +255,7 @@ impl Notification {
|
||||
if let Some(title) = self.title {
|
||||
notification.summary(&title);
|
||||
}
|
||||
notification.silent(self.sound.is_none());
|
||||
if let Some(crate::Icon::Rgba {
|
||||
rgba,
|
||||
width,
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use super::InvokeContext;
|
||||
use crate::Runtime;
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use tauri_macros::{command_enum, module_command_handler, CommandModule};
|
||||
|
||||
#[cfg(notification_all)]
|
||||
@ -17,6 +17,36 @@ const PERMISSION_GRANTED: &str = "granted";
|
||||
// `Denied` response from `request_permission`. Matches the Web API return value.
|
||||
const PERMISSION_DENIED: &str = "denied";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SoundDto {
|
||||
Default,
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
#[cfg(notification_all)]
|
||||
impl From<SoundDto> for crate::api::notification::Sound {
|
||||
fn from(sound: SoundDto) -> Self {
|
||||
match sound {
|
||||
SoundDto::Default => crate::api::notification::Sound::Default,
|
||||
SoundDto::Custom(s) => crate::api::notification::Sound::Custom(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SoundDto {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
if s.to_lowercase() == "default" {
|
||||
Ok(Self::Default)
|
||||
} else {
|
||||
Ok(Self::Custom(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The options for the notification API.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct NotificationOptions {
|
||||
@ -26,6 +56,8 @@ pub struct NotificationOptions {
|
||||
pub body: Option<String>,
|
||||
/// The notification icon.
|
||||
pub icon: Option<String>,
|
||||
/// The notification sound.
|
||||
pub sound: Option<SoundDto>,
|
||||
}
|
||||
|
||||
/// The API descriptor.
|
||||
@ -56,6 +88,9 @@ impl Cmd {
|
||||
if let Some(icon) = options.icon {
|
||||
notification = notification.icon(icon);
|
||||
}
|
||||
if let Some(sound) = options.sound {
|
||||
notification = notification.sound(sound);
|
||||
}
|
||||
#[cfg(feature = "windows7-compat")]
|
||||
{
|
||||
notification.notify(&context.window.app_handle)?;
|
||||
@ -84,16 +119,27 @@ impl Cmd {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::NotificationOptions;
|
||||
use super::{NotificationOptions, SoundDto};
|
||||
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
|
||||
impl Arbitrary for SoundDto {
|
||||
fn arbitrary(g: &mut Gen) -> Self {
|
||||
if bool::arbitrary(g) {
|
||||
Self::Default
|
||||
} else {
|
||||
Self::Custom(String::arbitrary(g))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for NotificationOptions {
|
||||
fn arbitrary(g: &mut Gen) -> Self {
|
||||
Self {
|
||||
title: String::arbitrary(g),
|
||||
body: Option::arbitrary(g),
|
||||
icon: Option::arbitrary(g),
|
||||
sound: Option::arbitrary(g),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
Versions/Current/Headers
|
1
core/tests/app-updater/frameworks/test.framework/Headers
Normal file
1
core/tests/app-updater/frameworks/test.framework/Headers
Normal file
@ -0,0 +1 @@
|
||||
Versions/Current/Headers
|
@ -1 +0,0 @@
|
||||
Versions/Current/Resources
|
@ -0,0 +1 @@
|
||||
Versions/Current/Resources
|
0
core/tests/app-updater/frameworks/test.framework/Versions/A/test
Executable file → Normal file
0
core/tests/app-updater/frameworks/test.framework/Versions/A/test
Executable file → Normal file
@ -0,0 +1 @@
|
||||
A
|
@ -1 +0,0 @@
|
||||
Versions/Current/test
|
1
core/tests/app-updater/frameworks/test.framework/test
Normal file
1
core/tests/app-updater/frameworks/test.framework/test
Normal file
@ -0,0 +1 @@
|
||||
Versions/Current/test
|
62
examples/api/dist/assets/index.js
vendored
62
examples/api/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
1423
examples/api/src-tauri/Cargo.lock
generated
1423
examples/api/src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,15 @@
|
||||
<script>
|
||||
import { sendNotification as notify } from '@tauri-apps/api/notification'
|
||||
|
||||
export let onMessage
|
||||
|
||||
// send the notification directly
|
||||
// the backend is responsible for checking the permission
|
||||
function _sendNotification() {
|
||||
new Notification('Notification title', {
|
||||
body: 'This is the notification body'
|
||||
async function _sendNotification() {
|
||||
notify({
|
||||
title: 'Notification title',
|
||||
body: 'This is the notification body',
|
||||
sound: 'default'
|
||||
})
|
||||
}
|
||||
|
||||
@ -29,6 +33,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<button class="btn" id="notification" on:click={_sendNotification}>
|
||||
<button class="btn" id="notification" on:click={sendNotification}>
|
||||
Send test notification
|
||||
</button>
|
||||
|
1
tooling/api/.gitignore
vendored
1
tooling/api/.gitignore
vendored
@ -65,4 +65,3 @@ package-lock.json
|
||||
|
||||
# Documentation output
|
||||
docs/*
|
||||
!docs/js-api.json
|
||||
|
@ -38,6 +38,31 @@ interface Options {
|
||||
body?: string
|
||||
/** Optional notification icon. */
|
||||
icon?: string
|
||||
/**
|
||||
* Optional notification sound.
|
||||
*
|
||||
* #### Platform-specific
|
||||
*
|
||||
* Each OS has a different sound name so you will need to conditionally specify an appropriate sound
|
||||
* based on the OS in use, 'default' represents the default system sound. For a list of sounds see:
|
||||
* - **Linux**: can be one of the sounds listed in {@link https://0pointer.de/public/sound-naming-spec.html}
|
||||
* - **Windows**: can be one of the sounds listed in {@link https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-audio}
|
||||
* but without the prefix, for example, if `ms-winsoundevent:Notification.Default` you would use `Default` and
|
||||
* if `ms-winsoundevent:Notification.Looping.Alarm2`, you would use `Alarm2`.
|
||||
* Windows 7 is not supported, if a sound is provided, it will play the default sound, otherwise it will be silent.
|
||||
* - **macOS**: you can specify the name of the sound you'd like to play when the notification is shown.
|
||||
* Any of the default sounds (under System Preferences > Sound) can be used, in addition to custom sound files.
|
||||
* Be sure that the sound file is copied under the app bundle (e.g., `YourApp.app/Contents/Resources`), or one of the following locations:
|
||||
* - `~/Library/Sounds`
|
||||
* - `/Library/Sounds`
|
||||
* - `/Network/Library/Sounds`
|
||||
* - `/System/Library/Sounds`
|
||||
*
|
||||
* See the {@link https://developer.apple.com/documentation/appkit/nssound | NSSound} docs for more information.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
sound?: 'default' | string
|
||||
}
|
||||
|
||||
/** Possible permission values. */
|
||||
|
Loading…
Reference in New Issue
Block a user