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

Implement service worker for offline notifications #480

Closed
wants to merge 4 commits into from
Closed

Implement service worker for offline notifications #480

wants to merge 4 commits into from

Conversation

MexHigh
Copy link
Contributor

@MexHigh MexHigh commented May 2, 2022

This is a draft

Fixes #344

How does it work

After logging in, a new service worker is created. The gotify-login-key gets passed to it via query parameter so that it can subscribe to the Websocket /stream endpoint. On incoming messages, it creates a notification. This way, no third party server must be used (e.g. a vendor server for the Webpush API).

The worker keeps running until the user logs out and the client is removed. It keeps running when the browser is closed.

It also seems like notifications work on android from within the browser now, as android only supports notifications via Service Worker (source).

(When testing, do not forget applying this workaround when not testing over HTTPS or localhost.)

Todos

  • Currently, when the UI is open, you get two notifications - one from the UI and one from the worker
  • Worker notification sound (?)
  • Stability testing (does the worker really persist? How about browser or OS restarts?)

Please add your changes if necessary. I've kept the console.log statements for easier testing. They need to be removed before merging, of course.

@MexHigh
Copy link
Contributor Author

MexHigh commented May 2, 2022

Now, the service worker only displays a message, when no gotify window is open (implemented in 5aca059).

I wasn't able to find a way to play custom sounds with service worker notifications, sadly.

Copy link
Member

@jmattheis jmattheis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @MexHigh, looks good so far, I've added some remarks in sub comments.

Comment on lines +64 to +71
stores.currentUser.tryAuthenticate().then(() => {
// always request notification permission when logged in
Notification.requestPermission()
.then(perm => console.log("Notification permissions " + perm))
.catch(console.error)
// reregister worker
registerNotificationWorker(stores.currentUser.token());
}).catch(() => {});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add another button under the enable notifications button, something like "enable background notifications". Should probably only visible if the notification permission was given. Gotify must not request this permission without user interaction, see #264

The button should be a toggle, enabling and disabling the notifications.

const ws = new WebSocket(`${wsProto}//${host}/stream?token=${gotifyKey}`)
console.log("Notification worker connected to websocket, waiting for messages")

ws.onmessage = (event) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need some reconnect logic here, otherwise the connection can break in the background and then the user doesn't get notifications anymore.

@MexHigh
Copy link
Contributor Author

MexHigh commented May 8, 2022

I'm afraid I have some bad news. After testing this for a while now, I have come to the conclusion several times that the service worker is unfortunately not persistent. It stays online for a few minutes up to about half an hour after the last Gotify tab is closed.

I have read in some resources that you can keep Service worker "alive" by having it send itself regular messages via postMessage, however this is far from a stable solution.

The onpush event on the other hand seems to be able to "wake up" a service worker again, but so far this can only be used with the Push API. This in turn forces the use of vendor servers.

So I think this will not work here as intended. I'm closing the pull request now, but maybe it will be useful in the future if there is a way to actually use the Push API with a self-hosted server, or the "push" event can be triggered otherwise.

My sources are attached, in case someone wants to do some more research or to follow the whole thing.

@jmattheis
Copy link
Member

@MexHigh thanks for your research!

@jmattheis jmattheis closed this May 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Webpush API for offline notifications?
2 participants