Skip to content
Snippets Groups Projects
Commit 09147cac authored by minibikini's avatar minibikini
Browse files

add service worker and push notifications

parent 3fa9b391
No related branches found
No related tags found
No related merge requests found
......@@ -17,16 +17,17 @@ import FollowRequests from '../components/follow_requests/follow_requests.vue'
import OAuthCallback from '../components/oauth_callback/oauth_callback.vue'
import UserSearch from '../components/user_search/user_search.vue'
const afterStoreSetup = ({store, i18n}) => {
const afterStoreSetup = ({ store, i18n }) => {
window.fetch('/api/statusnet/config.json')
.then((res) => res.json())
.then((data) => {
const {name, closed: registrationClosed, textlimit, server} = data.site
const { name, closed: registrationClosed, textlimit, server, vapidPublicKey } = data.site
store.dispatch('setInstanceOption', { name: 'name', value: name })
store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) })
store.dispatch('setInstanceOption', { name: 'server', value: server })
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
var apiConfig = data.site.pleromafe
......
......@@ -2,6 +2,8 @@ import backendInteractorService from '../services/backend_interactor_service/bac
import { compact, map, each, merge } from 'lodash'
import { set } from 'vue'
import registerPushNotifications from '../services/push/push.js'
// TODO: Unify with mergeOrAdd in statuses.js
export const mergeOrAdd = (arr, obj, item) => {
if (!item) { return false }
......@@ -125,6 +127,8 @@ const users = {
// Fetch our friends
store.rootState.api.backendInteractor.fetchFriends({id: user.id})
.then((friends) => commit('addNewUsers', friends))
registerPushNotifications(store)
})
} else {
// Authentication failed
......
function urlBase64ToUint8Array (base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4)
const base64 = (base64String + padding)
.replace(/-/g, '+')
.replace(/_/g, '/')
const rawData = window.atob(base64)
return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)))
}
function isPushSupported () {
return 'serviceWorker' in navigator && 'PushManager' in window
}
function registerServiceWorker () {
return navigator.serviceWorker.register('/static/sw.js')
.then(function (registration) {
console.log('Service worker successfully registered.')
return registration
})
.catch(function (err) {
console.error('Unable to register service worker.', err)
})
}
function askPermission () {
return new Promise(function (resolve, reject) {
if (!window.Notification) return resolve('Notifications disabled')
const permissionResult = window.Notification.requestPermission(function (result) {
resolve(result)
})
if (permissionResult) permissionResult.then(resolve, reject)
}).then(function (permissionResult) {
if (permissionResult !== 'granted') {
throw new Error('We weren\'t granted permission.')
}
return permissionResult
})
}
function subscribe (registration, store) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(store.rootState.instance.vapidPublicKey)
}
return registration.pushManager.subscribe(subscribeOptions)
}
function sendSubscriptionToBackEnd (subscription, store) {
return window.fetch('/api/v1/push/subscription/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${store.rootState.oauth.token}`
},
body: JSON.stringify({
subscription,
data: {
alerts: {
follow: true,
favourite: true,
mention: true,
reblog: true
}
}
})
})
.then(function (response) {
if (!response.ok) {
throw new Error('Bad status code from server.')
}
return response.json()
})
.then(function (responseData) {
if (!responseData.id) {
throw new Error('Bad response from server.')
}
return responseData
})
}
export default function registerPushNotifications (store) {
if (isPushSupported()) {
registerServiceWorker()
.then(function (registration) {
return askPermission()
.then(() => subscribe(registration, store))
.then((subscription) => sendSubscriptionToBackEnd(subscription, store))
.catch((e) => console.warn(`Failed to setup Web Push Notifications: ${e.message}`))
})
}
}
/* eslint-env serviceworker */
self.addEventListener('push', function (event) {
if (event.data) {
const data = event.data.json()
const promiseChain = clients.matchAll({
includeUncontrolled: true
}).then(function (clientList) {
const list = clientList.filter((item) => item.type === 'window')
if (list.length) return
return self.registration.showNotification(data.title, data)
})
event.waitUntil(promiseChain)
}
})
self.addEventListener('notificationclick', function (event) {
event.notification.close()
event.waitUntil(clients.matchAll({
includeUncontrolled: true
}).then(function (clientList) {
const list = clientList.filter((item) => item.type === 'window')
for (var i = 0; i < list.length; i++) {
var client = list[i]
if (client.url === '/' && 'focus' in client) { return client.focus() }
}
if (clients.openWindow) { return clients.openWindow('/') }
}))
})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment