From e25ca42a3f2d521a82ce375d67b32f9112a31e07 Mon Sep 17 00:00:00 2001 From: Marcel Robitaille Date: Thu, 21 Jul 2022 22:54:11 -0400 Subject: [PATCH 1/3] Add notification support to timers Signed-off-by: Marcel Robitaille --- src/components/RecipeTimer.vue | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/components/RecipeTimer.vue b/src/components/RecipeTimer.vue index 35b00d53a..eb3a60c75 100644 --- a/src/components/RecipeTimer.vue +++ b/src/components/RecipeTimer.vue @@ -63,6 +63,9 @@ export default { this.resetTimeDisplay() }, }, + async created() { + this.notificationPermission = await Notification.requestPermission() + }, mounted() { this.resetTimeDisplay() // Start loading the sound early so it's ready to go when we need to @@ -92,12 +95,20 @@ export default { // Start playing audio to alert the user that the timer is up this.audio.play() - await showSimpleAlertModal(t("cookbook", "Cooking time is up!")) + const message = t("cookbook", "Cooking time is up!") + + if (this.notificationPermission === "granted") { + const notification = new Notification(message) + notification.addEventListener("error", (error) => { + // eslint-disable-next-line no-console + console.error("Error showing notification:", error) + }) + } + + await showSimpleAlertModal(message) // Stop audio after the alert is confirmed this.audio.pause() - - // cookbook.notify(t('cookbook', 'Cooking time is up!')) $this.countdown = null $this.showFullTime = false $this.resetTimeDisplay() From 2a631219a9281d06f958a39e6a329d2508ca6543 Mon Sep 17 00:00:00 2001 From: Marcel Robitaille Date: Fri, 30 Dec 2022 21:52:43 -0400 Subject: [PATCH 2/3] Update changelog Signed-off-by: Marcel Robitaille --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf6dc924e..b91e63499 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## [Unreleased] +### Added +- Add browser notification support for timers + [1409](https://github.com/nextcloud/cookbook/pull/1409) @MarcelRobitaille + ### Fixed - Make "None" category string translatable [1323](https://github.com/nextcloud/cookbook/pull/1344) @seyfeb From 5bc2768313f4cd13a00b153e2b5e674d7a96f9d7 Mon Sep 17 00:00:00 2001 From: Marcel Robitaille Date: Fri, 30 Dec 2022 22:32:13 -0400 Subject: [PATCH 3/3] Improve browser notification permission request - Only request permission when the timer is started. Don't be annoying if the user isn't even going to use the feature - Add a justification for why the permission is requested and how to disable the notifications - Handle case of no browser notification support - Move all desktop notification related code into its own file Signed-off-by: Marcel Robitaille --- src/components/RecipeTimer.vue | 24 +++++++++--------- src/components/SimpleAlertModal.vue | 8 +++++- src/js/browser_notifications.js | 38 +++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 src/js/browser_notifications.js diff --git a/src/components/RecipeTimer.vue b/src/components/RecipeTimer.vue index eb3a60c75..db9d31006 100644 --- a/src/components/RecipeTimer.vue +++ b/src/components/RecipeTimer.vue @@ -16,6 +16,8 @@ import { linkTo } from "@nextcloud/router" import { showSimpleAlertModal } from "cookbook/js/modals" +import * as browserNotifications from "cookbook/js/browser_notifications" + export default { name: "RecipeTimer", props: { @@ -63,9 +65,6 @@ export default { this.resetTimeDisplay() }, }, - async created() { - this.notificationPermission = await Notification.requestPermission() - }, mounted() { this.resetTimeDisplay() // Start loading the sound early so it's ready to go when we need to @@ -82,6 +81,14 @@ export default { this.audio.loop = true }, methods: { + onTimerStart() { + browserNotifications.requestPermission({ + justification: [ + t("cookbook", "Please enable browser notifications to receive an alert when the timer is over."), + t("cookbook", "You can disable these notifications at any time in the \"Cookbook settings\" dialog."), + ], + }) + }, onTimerEnd() { window.clearInterval(this.countdown) const $this = this @@ -96,15 +103,7 @@ export default { this.audio.play() const message = t("cookbook", "Cooking time is up!") - - if (this.notificationPermission === "granted") { - const notification = new Notification(message) - notification.addEventListener("error", (error) => { - // eslint-disable-next-line no-console - console.error("Error showing notification:", error) - }) - } - + await browserNotifications.notify(message) await showSimpleAlertModal(message) // Stop audio after the alert is confirmed @@ -137,6 +136,7 @@ export default { if (this.countdown === null) { // Pass this to callback function const $this = this + $this.onTimerStart() this.countdown = window.setInterval(() => { $this.seconds -= 1 if ($this.seconds < 0) { diff --git a/src/components/SimpleAlertModal.vue b/src/components/SimpleAlertModal.vue index bc6f48e49..49fb2ec46 100644 --- a/src/components/SimpleAlertModal.vue +++ b/src/components/SimpleAlertModal.vue @@ -1,7 +1,8 @@