From a52a393266744560c6c6b2cbd24da812d35562fb Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 11 Jun 2020 15:22:31 +0200 Subject: NotificationUtils: Extract preparation of notification object. --- src/modules/statuses.js | 41 ++------------------- .../notification_utils/notification_utils.js | 42 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 9a2e0df1..073b15f1 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -13,7 +13,7 @@ import { omitBy } from 'lodash' import { set } from 'vue' -import { isStatusNotification } from '../services/notification_utils/notification_utils.js' +import { isStatusNotification, prepareNotificationObject } from '../services/notification_utils/notification_utils.js' import apiService from '../services/api/api.service.js' import { muteWordHits } from '../services/status_parser/status_parser.js' @@ -344,42 +344,7 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot state.notifications.idStore[notification.id] = notification if ('Notification' in window && window.Notification.permission === 'granted') { - const notifObj = {} - const status = notification.status - const title = notification.from_profile.name - notifObj.icon = notification.from_profile.profile_image_url - let i18nString - switch (notification.type) { - case 'like': - i18nString = 'favorited_you' - break - case 'repeat': - i18nString = 'repeated_you' - break - case 'follow': - i18nString = 'followed_you' - break - case 'move': - i18nString = 'migrated_to' - break - case 'follow_request': - i18nString = 'follow_request' - break - } - - if (notification.type === 'pleroma:emoji_reaction') { - notifObj.body = rootGetters.i18n.t('notifications.reacted_with', [notification.emoji]) - } else if (i18nString) { - notifObj.body = rootGetters.i18n.t('notifications.' + i18nString) - } else if (isStatusNotification(notification.type)) { - notifObj.body = notification.status.text - } - - // Shows first attached non-nsfw image, if any. Should add configuration for this somehow... - if (status && status.attachments && status.attachments.length > 0 && !status.nsfw && - status.attachments[0].mimetype.startsWith('image/')) { - notifObj.image = status.attachments[0].url - } + const notifObj = prepareNotificationObject(notification, rootGetters.i18n) const reasonsToMuteNotif = ( notification.seen || @@ -393,7 +358,7 @@ const addNewNotifications = (state, { dispatch, notifications, older, visibleNot ) ) if (!reasonsToMuteNotif) { - let desktopNotification = new window.Notification(title, notifObj) + let desktopNotification = new window.Notification(notifObj.title, notifObj) // Chrome is known for not closing notifications automatically // according to MDN, anyway. setTimeout(desktopNotification.close.bind(desktopNotification), 5000) diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index eb479227..4576ea83 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -43,3 +43,45 @@ export const filteredNotificationsFromStore = (store, types) => { export const unseenNotificationsFromStore = store => filter(filteredNotificationsFromStore(store), ({ seen }) => !seen) + +export const prepareNotificationObject = (notification, i18n) => { + const notifObj = {} + const status = notification.status + const title = notification.from_profile.name + notifObj.title = title + notifObj.icon = notification.from_profile.profile_image_url + let i18nString + switch (notification.type) { + case 'like': + i18nString = 'favorited_you' + break + case 'repeat': + i18nString = 'repeated_you' + break + case 'follow': + i18nString = 'followed_you' + break + case 'move': + i18nString = 'migrated_to' + break + case 'follow_request': + i18nString = 'follow_request' + break + } + + if (notification.type === 'pleroma:emoji_reaction') { + notifObj.body = i18n.t('notifications.reacted_with', [notification.emoji]) + } else if (i18nString) { + notifObj.body = i18n.t('notifications.' + i18nString) + } else if (isStatusNotification(notification.type)) { + notifObj.body = notification.status.text + } + + // Shows first attached non-nsfw image, if any. Should add configuration for this somehow... + if (status && status.attachments && status.attachments.length > 0 && !status.nsfw && + status.attachments[0].mimetype.startsWith('image/')) { + notifObj.image = status.attachments[0].url + } + + return notifObj +} -- cgit v1.2.3-70-g09d2 From 5b0190bef5a9756453d0220b80a18469639c8fe9 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 11 Jun 2020 15:22:58 +0200 Subject: ServiceWorker: Grab the notification and display it with i18n. --- src/sw.js | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/sw.js b/src/sw.js index 6cecb3f3..0aab275b 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,6 +1,48 @@ /* eslint-env serviceworker */ import localForage from 'localforage' +import { parseNotification } from './services/entity_normalizer/entity_normalizer.service.js' +import { prepareNotificationObject } from './services/notification_utils/notification_utils.js' +import Vue from 'vue' +import VueI18n from 'vue-i18n' + +const messages = { + ar: require('./i18n/ar.json'), + ca: require('./i18n/ca.json'), + cs: require('./i18n/cs.json'), + de: require('./i18n/de.json'), + eo: require('./i18n/eo.json'), + es: require('./i18n/es.json'), + et: require('./i18n/et.json'), + eu: require('./i18n/eu.json'), + fi: require('./i18n/fi.json'), + fr: require('./i18n/fr.json'), + ga: require('./i18n/ga.json'), + he: require('./i18n/he.json'), + hu: require('./i18n/hu.json'), + it: require('./i18n/it.json'), + ja: require('./i18n/ja_pedantic.json'), + ja_easy: require('./i18n/ja_easy.json'), + ko: require('./i18n/ko.json'), + nb: require('./i18n/nb.json'), + nl: require('./i18n/nl.json'), + oc: require('./i18n/oc.json'), + pl: require('./i18n/pl.json'), + pt: require('./i18n/pt.json'), + ro: require('./i18n/ro.json'), + ru: require('./i18n/ru.json'), + te: require('./i18n/te.json'), + zh: require('./i18n/zh.json'), + en: require('./i18n/en.json') +} + +Vue.use(VueI18n) +const i18n = new VueI18n({ + // By default, use the browser locale, we will update it if neccessary + locale: 'en', + fallbackLocale: 'en', + messages +}) function isEnabled () { return localForage.getItem('vuex-lz') @@ -12,15 +54,33 @@ function getWindowClients () { .then((clientList) => clientList.filter(({ type }) => type === 'window')) } -self.addEventListener('push', (event) => { - if (event.data) { - event.waitUntil(isEnabled().then((isEnabled) => { - return isEnabled && getWindowClients().then((list) => { - const data = event.data.json() +const setLocale = async () => { + const state = await localForage.getItem('vuex-lz') + const locale = state.config.interfaceLanguage || 'en' + i18n.locale = locale +} + +const maybeShowNotification = async (event) => { + const enabled = await isEnabled() + const activeClients = await getWindowClients() + await setLocale() + if (enabled && activeClients) { + const data = event.data.json() - if (list.length === 0) return self.registration.showNotification(data.title, data) - }) - })) + const url = `${self.registration.scope}api/v1/notifications/${data.notification_id}` + const notification = await fetch(url, { headers: { Authorization: 'Bearer ' + data.access_token } }) + let nj = await notification.json() + nj = parseNotification(nj) + + const res = prepareNotificationObject(nj, i18n) + + self.registration.showNotification(res.title, res) + } +} + +self.addEventListener('push', async (event) => { + if (event.data) { + event.waitUntil(maybeShowNotification(event)) } }) -- cgit v1.2.3-70-g09d2 From e2ca107e01c5a0715aa1a1a68496fe514eb9e902 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 11 Jun 2020 15:24:01 +0200 Subject: ServiceWorker: Don't show message via sw if a client is active. --- src/sw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/sw.js b/src/sw.js index 0aab275b..d0050b24 100644 --- a/src/sw.js +++ b/src/sw.js @@ -64,7 +64,7 @@ const maybeShowNotification = async (event) => { const enabled = await isEnabled() const activeClients = await getWindowClients() await setLocale() - if (enabled && activeClients) { + if (enabled && (activeClients.length === 0)) { const data = event.data.json() const url = `${self.registration.scope}api/v1/notifications/${data.notification_id}` -- cgit v1.2.3-70-g09d2 From 98819ae32c6f3962df955ee280cd6cc271625852 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 11 Jun 2020 15:49:39 +0200 Subject: NotificationUtils: Add tag to notifications. --- src/services/notification_utils/notification_utils.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index 4576ea83..5cc19215 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -45,7 +45,9 @@ export const unseenNotificationsFromStore = store => filter(filteredNotificationsFromStore(store), ({ seen }) => !seen) export const prepareNotificationObject = (notification, i18n) => { - const notifObj = {} + const notifObj = { + tag: notification.id + } const status = notification.status const title = notification.from_profile.name notifObj.title = title -- cgit v1.2.3-70-g09d2 From 9bfb3754c1bc0d1033afda97f2884e721d1ab3d8 Mon Sep 17 00:00:00 2001 From: lain Date: Sat, 13 Jun 2020 11:47:34 +0200 Subject: ServiceWorker: Use loader to only notification messages. This keeps the translation size very small and makes it easy to integrate all the languages, as dynamically loading them isn't easy in the service worker. --- src/lib/notification-i18n-loader.js | 9 ++++++ src/sw.js | 55 +++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 27 deletions(-) create mode 100644 src/lib/notification-i18n-loader.js (limited to 'src') diff --git a/src/lib/notification-i18n-loader.js b/src/lib/notification-i18n-loader.js new file mode 100644 index 00000000..a61755c8 --- /dev/null +++ b/src/lib/notification-i18n-loader.js @@ -0,0 +1,9 @@ +// This somewhat mysterious module +module.exports = function(source) { + var object = JSON.parse(source) + var smol = { + notifications: object.notifications || {} + } + + return JSON.stringify(smol) +} diff --git a/src/sw.js b/src/sw.js index d0050b24..6e31516a 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,4 +1,5 @@ /* eslint-env serviceworker */ +/* eslint-disable import/no-webpack-loader-syntax */ import localForage from 'localforage' import { parseNotification } from './services/entity_normalizer/entity_normalizer.service.js' @@ -7,33 +8,33 @@ import Vue from 'vue' import VueI18n from 'vue-i18n' const messages = { - ar: require('./i18n/ar.json'), - ca: require('./i18n/ca.json'), - cs: require('./i18n/cs.json'), - de: require('./i18n/de.json'), - eo: require('./i18n/eo.json'), - es: require('./i18n/es.json'), - et: require('./i18n/et.json'), - eu: require('./i18n/eu.json'), - fi: require('./i18n/fi.json'), - fr: require('./i18n/fr.json'), - ga: require('./i18n/ga.json'), - he: require('./i18n/he.json'), - hu: require('./i18n/hu.json'), - it: require('./i18n/it.json'), - ja: require('./i18n/ja_pedantic.json'), - ja_easy: require('./i18n/ja_easy.json'), - ko: require('./i18n/ko.json'), - nb: require('./i18n/nb.json'), - nl: require('./i18n/nl.json'), - oc: require('./i18n/oc.json'), - pl: require('./i18n/pl.json'), - pt: require('./i18n/pt.json'), - ro: require('./i18n/ro.json'), - ru: require('./i18n/ru.json'), - te: require('./i18n/te.json'), - zh: require('./i18n/zh.json'), - en: require('./i18n/en.json') + ar: require('./lib/notification-i18n-loader.js!./i18n/ar.json'), + ca: require('./lib/notification-i18n-loader.js!./i18n/ca.json'), + cs: require('./lib/notification-i18n-loader.js!./i18n/cs.json'), + de: require('./lib/notification-i18n-loader.js!./i18n/de.json'), + eo: require('./lib/notification-i18n-loader.js!./i18n/eo.json'), + es: require('./lib/notification-i18n-loader.js!./i18n/es.json'), + et: require('./lib/notification-i18n-loader.js!./i18n/et.json'), + eu: require('./lib/notification-i18n-loader.js!./i18n/eu.json'), + fi: require('./lib/notification-i18n-loader.js!./i18n/fi.json'), + fr: require('./lib/notification-i18n-loader.js!./i18n/fr.json'), + ga: require('./lib/notification-i18n-loader.js!./i18n/ga.json'), + he: require('./lib/notification-i18n-loader.js!./i18n/he.json'), + hu: require('./lib/notification-i18n-loader.js!./i18n/hu.json'), + it: require('./lib/notification-i18n-loader.js!./i18n/it.json'), + ja: require('./lib/notification-i18n-loader.js!./i18n/ja_pedantic.json'), + ja_easy: require('./lib/notification-i18n-loader.js!./i18n/ja_easy.json'), + ko: require('./lib/notification-i18n-loader.js!./i18n/ko.json'), + nb: require('./lib/notification-i18n-loader.js!./i18n/nb.json'), + nl: require('./lib/notification-i18n-loader.js!./i18n/nl.json'), + oc: require('./lib/notification-i18n-loader.js!./i18n/oc.json'), + pl: require('./lib/notification-i18n-loader.js!./i18n/pl.json'), + pt: require('./lib/notification-i18n-loader.js!./i18n/pt.json'), + ro: require('./lib/notification-i18n-loader.js!./i18n/ro.json'), + ru: require('./lib/notification-i18n-loader.js!./i18n/ru.json'), + te: require('./lib/notification-i18n-loader.js!./i18n/te.json'), + zh: require('./lib/notification-i18n-loader.js!./i18n/zh.json'), + en: require('./lib/notification-i18n-loader.js!./i18n/en.json') } Vue.use(VueI18n) -- cgit v1.2.3-70-g09d2 From 1e57adf6d4a46ab5be677bba7ae3c7f0ba0fc520 Mon Sep 17 00:00:00 2001 From: lain Date: Sat, 13 Jun 2020 11:53:16 +0200 Subject: Linting + docs --- src/lib/notification-i18n-loader.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib/notification-i18n-loader.js b/src/lib/notification-i18n-loader.js index a61755c8..71f9156a 100644 --- a/src/lib/notification-i18n-loader.js +++ b/src/lib/notification-i18n-loader.js @@ -1,5 +1,8 @@ -// This somewhat mysterious module -module.exports = function(source) { +// This somewhat mysterious module will load a json string +// and then extract only the 'notifications' part. This is +// meant to be used to load the partial i18n we need for +// the service worker. +module.exports = function (source) { var object = JSON.parse(source) var smol = { notifications: object.notifications || {} -- cgit v1.2.3-70-g09d2 From 14540e2a078bd59ca8f13cd5c0b894acad3d639f Mon Sep 17 00:00:00 2001 From: lain Date: Tue, 16 Jun 2020 13:27:36 +0200 Subject: Service Worker: Extract messages to own module. --- src/i18n/service_worker_messages.js | 35 +++++++++++++++++++++++++++++++++++ src/sw.js | 32 +------------------------------- 2 files changed, 36 insertions(+), 31 deletions(-) create mode 100644 src/i18n/service_worker_messages.js (limited to 'src') diff --git a/src/i18n/service_worker_messages.js b/src/i18n/service_worker_messages.js new file mode 100644 index 00000000..270ed043 --- /dev/null +++ b/src/i18n/service_worker_messages.js @@ -0,0 +1,35 @@ +/* eslint-disable import/no-webpack-loader-syntax */ +// This module exports only the notification part of the i18n, +// which is useful for the service worker + +const messages = { + ar: require('../lib/notification-i18n-loader.js!./ar.json'), + ca: require('../lib/notification-i18n-loader.js!./ca.json'), + cs: require('../lib/notification-i18n-loader.js!./cs.json'), + de: require('../lib/notification-i18n-loader.js!./de.json'), + eo: require('../lib/notification-i18n-loader.js!./eo.json'), + es: require('../lib/notification-i18n-loader.js!./es.json'), + et: require('../lib/notification-i18n-loader.js!./et.json'), + eu: require('../lib/notification-i18n-loader.js!./eu.json'), + fi: require('../lib/notification-i18n-loader.js!./fi.json'), + fr: require('../lib/notification-i18n-loader.js!./fr.json'), + ga: require('../lib/notification-i18n-loader.js!./ga.json'), + he: require('../lib/notification-i18n-loader.js!./he.json'), + hu: require('../lib/notification-i18n-loader.js!./hu.json'), + it: require('../lib/notification-i18n-loader.js!./it.json'), + ja: require('../lib/notification-i18n-loader.js!./ja_pedantic.json'), + ja_easy: require('../lib/notification-i18n-loader.js!./ja_easy.json'), + ko: require('../lib/notification-i18n-loader.js!./ko.json'), + nb: require('../lib/notification-i18n-loader.js!./nb.json'), + nl: require('../lib/notification-i18n-loader.js!./nl.json'), + oc: require('../lib/notification-i18n-loader.js!./oc.json'), + pl: require('../lib/notification-i18n-loader.js!./pl.json'), + pt: require('../lib/notification-i18n-loader.js!./pt.json'), + ro: require('../lib/notification-i18n-loader.js!./ro.json'), + ru: require('../lib/notification-i18n-loader.js!./ru.json'), + te: require('../lib/notification-i18n-loader.js!./te.json'), + zh: require('../lib/notification-i18n-loader.js!./zh.json'), + en: require('../lib/notification-i18n-loader.js!./en.json') +} + +export default messages diff --git a/src/sw.js b/src/sw.js index 6e31516a..c971222e 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,41 +1,11 @@ /* eslint-env serviceworker */ -/* eslint-disable import/no-webpack-loader-syntax */ import localForage from 'localforage' import { parseNotification } from './services/entity_normalizer/entity_normalizer.service.js' import { prepareNotificationObject } from './services/notification_utils/notification_utils.js' import Vue from 'vue' import VueI18n from 'vue-i18n' - -const messages = { - ar: require('./lib/notification-i18n-loader.js!./i18n/ar.json'), - ca: require('./lib/notification-i18n-loader.js!./i18n/ca.json'), - cs: require('./lib/notification-i18n-loader.js!./i18n/cs.json'), - de: require('./lib/notification-i18n-loader.js!./i18n/de.json'), - eo: require('./lib/notification-i18n-loader.js!./i18n/eo.json'), - es: require('./lib/notification-i18n-loader.js!./i18n/es.json'), - et: require('./lib/notification-i18n-loader.js!./i18n/et.json'), - eu: require('./lib/notification-i18n-loader.js!./i18n/eu.json'), - fi: require('./lib/notification-i18n-loader.js!./i18n/fi.json'), - fr: require('./lib/notification-i18n-loader.js!./i18n/fr.json'), - ga: require('./lib/notification-i18n-loader.js!./i18n/ga.json'), - he: require('./lib/notification-i18n-loader.js!./i18n/he.json'), - hu: require('./lib/notification-i18n-loader.js!./i18n/hu.json'), - it: require('./lib/notification-i18n-loader.js!./i18n/it.json'), - ja: require('./lib/notification-i18n-loader.js!./i18n/ja_pedantic.json'), - ja_easy: require('./lib/notification-i18n-loader.js!./i18n/ja_easy.json'), - ko: require('./lib/notification-i18n-loader.js!./i18n/ko.json'), - nb: require('./lib/notification-i18n-loader.js!./i18n/nb.json'), - nl: require('./lib/notification-i18n-loader.js!./i18n/nl.json'), - oc: require('./lib/notification-i18n-loader.js!./i18n/oc.json'), - pl: require('./lib/notification-i18n-loader.js!./i18n/pl.json'), - pt: require('./lib/notification-i18n-loader.js!./i18n/pt.json'), - ro: require('./lib/notification-i18n-loader.js!./i18n/ro.json'), - ru: require('./lib/notification-i18n-loader.js!./i18n/ru.json'), - te: require('./lib/notification-i18n-loader.js!./i18n/te.json'), - zh: require('./lib/notification-i18n-loader.js!./i18n/zh.json'), - en: require('./lib/notification-i18n-loader.js!./i18n/en.json') -} +import messages from './i18n/service_worker_messages.js' Vue.use(VueI18n) const i18n = new VueI18n({ -- cgit v1.2.3-70-g09d2 From aa725010c5a3eeeb2dae3e6618b057e08fc5fd49 Mon Sep 17 00:00:00 2001 From: lain Date: Fri, 19 Jun 2020 15:24:06 +0200 Subject: ServiceWorker: Use clearer variable names --- src/sw.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/sw.js b/src/sw.js index c971222e..f5e34dd6 100644 --- a/src/sw.js +++ b/src/sw.js @@ -40,10 +40,10 @@ const maybeShowNotification = async (event) => { const url = `${self.registration.scope}api/v1/notifications/${data.notification_id}` const notification = await fetch(url, { headers: { Authorization: 'Bearer ' + data.access_token } }) - let nj = await notification.json() - nj = parseNotification(nj) + const notificationJson = await notification.json() + const parsedNotification = parseNotification(notificationJson) - const res = prepareNotificationObject(nj, i18n) + const res = prepareNotificationObject(parsedNotification, i18n) self.registration.showNotification(res.title, res) } -- cgit v1.2.3-70-g09d2