improve notification subscription

This commit is contained in:
Egor Kislitsyn 2018-12-13 18:04:09 +07:00
parent 02c0e15781
commit b3455649c5
4 changed files with 50 additions and 32 deletions

View file

@ -50,6 +50,32 @@ const persistedStateOptions = {
'oauth' 'oauth'
] ]
} }
const registerPushNotifications = store => {
store.subscribe((mutation, state) => {
const vapidPublicKey = state.instance.vapidPublicKey
const permission = state.interface.notificationPermission === 'granted'
const isUserMutation = mutation.type === 'setCurrentUser'
if (isUserMutation && vapidPublicKey && permission) {
return store.dispatch('registerPushNotifications')
}
const user = state.users.currentUser
const isVapidMutation = mutation.type === 'setInstanceOption' && mutation.payload.name === 'vapidPublicKey'
if (isVapidMutation && user && permission) {
return store.dispatch('registerPushNotifications')
}
const isPermMutation = mutation.type === 'setNotificationPermission' && mutation.payload === 'granted'
if (isPermMutation && user && vapidPublicKey) {
return store.dispatch('registerPushNotifications')
}
})
}
createPersistedState(persistedStateOptions).then((persistedState) => { createPersistedState(persistedStateOptions).then((persistedState) => {
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: { modules: {
@ -62,17 +88,10 @@ createPersistedState(persistedStateOptions).then((persistedState) => {
chat: chatModule, chat: chatModule,
oauth: oauthModule oauth: oauthModule
}, },
plugins: [persistedState], plugins: [persistedState, registerPushNotifications],
strict: false // Socket modifies itself, let's ignore this for now. strict: false // Socket modifies itself, let's ignore this for now.
// strict: process.env.NODE_ENV !== 'production' // strict: process.env.NODE_ENV !== 'production'
}) })
store.subscribe((mutation, state) => {
if ((mutation.type === 'setCurrentUser' && state.instance.vapidPublicKey) || // Login + existing key
(mutation.type === 'setInstanceOption' && mutation.payload.name === 'vapidPublicKey' && state.users.currentUser)) { // Logged in, key arrives late
store.dispatch('registerPushNotifications')
}
})
afterStoreSetup({ store, i18n }) afterStoreSetup({ store, i18n })
}) })

View file

@ -3,7 +3,8 @@ import { set, delete as del } from 'vue'
const defaultState = { const defaultState = {
settings: { settings: {
currentSaveStateNotice: null, currentSaveStateNotice: null,
noticeClearTimeout: null noticeClearTimeout: null,
notificationPermission: null
} }
} }
@ -21,6 +22,9 @@ const interfaceMod = {
} else { } else {
set(state.settings, 'currentSaveStateNotice', { error: true, errorData: error }) set(state.settings, 'currentSaveStateNotice', { error: true, errorData: error })
} }
},
setNotificationPermission (state, permission) {
state.notificationPermission = permission
} }
}, },
actions: { actions: {
@ -29,6 +33,9 @@ const interfaceMod = {
}, },
settingsSaved ({ commit, dispatch }, { success, error }) { settingsSaved ({ commit, dispatch }, { success, error }) {
commit('settingsSaved', { success, error }) commit('settingsSaved', { success, error })
},
setNotificationPermission ({ commit }, permission) {
commit('setNotificationPermission', permission)
} }
} }
} }

View file

@ -19,6 +19,14 @@ export const mergeOrAdd = (arr, obj, item) => {
} }
} }
const getNotificationPermission = () => {
const Notification = window.Notification
if (!Notification) return Promise.resolve(null)
if (Notification.permission === 'default') return Notification.requestPermission()
return Promise.resolve(Notification.permission)
}
export const mutations = { export const mutations = {
setMuted (state, { user: {id}, muted }) { setMuted (state, { user: {id}, muted }) {
const user = state.usersObject[id] const user = state.usersObject[id]
@ -108,6 +116,9 @@ const users = {
commit('setCurrentUser', user) commit('setCurrentUser', user)
commit('addNewUsers', [user]) commit('addNewUsers', [user])
getNotificationPermission()
.then(permission => commit('setNotificationPermission', permission))
// Set our new backend interactor // Set our new backend interactor
commit('setBackendInteractor', backendInteractorService(accessToken)) commit('setBackendInteractor', backendInteractorService(accessToken))

View file

@ -19,22 +19,6 @@ function registerServiceWorker () {
.catch((err) => console.error('Unable to register service worker.', err)) .catch((err) => console.error('Unable to register service worker.', err))
} }
function askPermission () {
return new Promise((resolve, reject) => {
const Notification = window.Notification
if (!Notification) return reject(new Error('Notifications disabled'))
if (Notification.permission !== 'default') return resolve(Notification.permission)
const permissionResult = Notification.requestPermission(resolve)
if (permissionResult) permissionResult.then(resolve, reject)
}).then((permissionResult) => {
if (permissionResult !== 'granted') throw new Error('We weren\'t granted permission.')
return permissionResult
})
}
function subscribe (registration, isEnabled, vapidPublicKey) { function subscribe (registration, isEnabled, vapidPublicKey) {
if (!isEnabled) return Promise.reject(new Error('Web Push is disabled in config')) if (!isEnabled) return Promise.reject(new Error('Web Push is disabled in config'))
if (!vapidPublicKey) return Promise.reject(new Error('VAPID public key is not found')) if (!vapidPublicKey) return Promise.reject(new Error('VAPID public key is not found'))
@ -78,11 +62,8 @@ function sendSubscriptionToBackEnd (subscription, token) {
export default function registerPushNotifications (isEnabled, vapidPublicKey, token) { export default function registerPushNotifications (isEnabled, vapidPublicKey, token) {
if (isPushSupported()) { if (isPushSupported()) {
registerServiceWorker() registerServiceWorker()
.then((registration) => { .then((registration) => subscribe(registration, isEnabled, vapidPublicKey))
return askPermission()
.then(() => subscribe(registration, isEnabled, vapidPublicKey))
.then((subscription) => sendSubscriptionToBackEnd(subscription, token)) .then((subscription) => sendSubscriptionToBackEnd(subscription, token))
.catch((e) => console.warn(`Failed to setup Web Push Notifications: ${e.message}`)) .catch((e) => console.warn(`Failed to setup Web Push Notifications: ${e.message}`))
})
} }
} }