diff --git a/web/src/notifications.js b/web/src/notifications.js index f3d4793f1b5dfd..fd22e0e4c7dc40 100644 --- a/web/src/notifications.js +++ b/web/src/notifications.js @@ -22,6 +22,7 @@ import * as spoilers from "./spoilers"; import * as stream_data from "./stream_data"; import * as stream_ui_updates from "./stream_ui_updates"; import * as ui from "./ui"; +import * as ui_util from "./ui_util"; import * as unread from "./unread"; import * as unread_ops from "./unread_ops"; import {user_settings} from "./user_settings"; @@ -508,7 +509,7 @@ export function received_messages(messages) { }); } if (should_send_audible_notification(message)) { - $("#user-notification-sound-audio")[0].play(); + ui_util.play_audio($("#user-notification-sound-audio")[0]); } } } diff --git a/web/src/settings_notifications.js b/web/src/settings_notifications.js index d11f30606a8cb4..a8362a2586b5a5 100644 --- a/web/src/settings_notifications.js +++ b/web/src/settings_notifications.js @@ -14,6 +14,7 @@ import * as stream_edit from "./stream_edit"; import * as stream_settings_data from "./stream_settings_data"; import * as stream_settings_ui from "./stream_settings_ui"; import * as sub_store from "./sub_store"; +import * as ui_util from "./ui_util"; import * as unread_ui from "./unread_ui"; import {user_settings} from "./user_settings"; @@ -123,7 +124,7 @@ export function set_up(settings_panel) { $container.find(".play_notification_sound").on("click", () => { if (settings_object.notification_sound !== "none") { - $notification_sound_elem[0].play(); + ui_util.play_audio($notification_sound_elem[0]); } }); diff --git a/web/src/ui_util.ts b/web/src/ui_util.ts index c3a0960d8ecf0f..394c4bc3843bed 100644 --- a/web/src/ui_util.ts +++ b/web/src/ui_util.ts @@ -1,5 +1,6 @@ import $ from "jquery"; +import * as blueslip from "./blueslip"; import * as keydown_util from "./keydown_util"; // Add functions to this that have no non-trivial @@ -75,3 +76,21 @@ export function parse_html(html: string): DocumentFragment { template.innerHTML = html; return template.content; } + +/* + * Handle permission denied to play audio by the browser. + * This can happen due to two reasons: user denied permission to play audio + * unconditionally and browser denying permission to play audio without + * any interactive trigger like a button. See + * https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play for more details. + */ +export async function play_audio(elem: HTMLVideoElement): Promise { + try { + await elem.play(); + } catch (error) { + if (!(error instanceof DOMException)) { + throw error; + } + blueslip.debug(`Unable to play audio. ${error.name}: ${error.message}`); + } +}