Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add browser notification support to timers #1409

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
17 changes: 14 additions & 3 deletions src/components/RecipeTimer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -79,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
Expand All @@ -92,12 +102,12 @@ 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!")
await browserNotifications.notify(message)
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()
Expand Down Expand Up @@ -126,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) {
Expand Down
8 changes: 7 additions & 1 deletion src/components/SimpleAlertModal.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<template>
<NcModal :title="title" @close="$close">
<div class="modal__wrapper">
<div class="modal__content">{{ content }}</div>
<div v-if="!multiline" class="modal__content">{{ content }}</div>
<p v-else v-for="line in content" class="modal__content">{{ line }}</p>
<div class="modal__button-bar">
<NcButton type="primary" @click="$close">{{
t("cookbook", "Dismiss")
Expand All @@ -21,6 +22,11 @@ export default {
NcModal,
NcButton,
},
computed: {
multiline() {
return Array.isArray(this.content)
},
},
}
</script>

Expand Down
38 changes: 38 additions & 0 deletions src/js/browser_notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { showSimpleAlertModal } from "cookbook/js/modals"

export const requestPermission = async ({ justification }) => {

// Exit early if browser doesn't support notifications
if (!("Notification" in window)) {
return
}

// Exit early if already granted
if (Notification.permission === 'granted') {
return
}

await showSimpleAlertModal(justification)
await Notification.requestPermission()
}

export const notify = async (title, options) => {

// Exit early if browser doesn't support notifications
if (!("Notification" in window)) {
return
}

// Try one more time to get permission (maybe the caller forgot to call
// requestPermission first)
// If it's still not granted, exit early
if (Notification.permission !== 'granted' && (await Notification.requestPermission() !== 'granted')) {
return
}

const notification = new Notification(title, options)
notification.addEventListener("error", (error) => {
// eslint-disable-next-line no-console
console.error("Error showing notification:", error)
})
}