diff --git a/src/config/locales/de/translation.missing.json b/src/config/locales/de/translation.missing.json index ab7630c0..04aa5bc5 100644 --- a/src/config/locales/de/translation.missing.json +++ b/src/config/locales/de/translation.missing.json @@ -97,5 +97,19 @@ "new_toot": { "poll_invalid": "Invalid poll choices" } + }, + "notification": { + "favourite": { + "title": "Favourite", + "body": "{{username}} favourited your status" + }, + "follow": { + "title": "Follow", + "body": "{{username}} is now following you" + }, + "reblog": { + "title": "Reblog", + "body": "{{username}} boosted your status" + } } } diff --git a/src/config/locales/en/translation.json b/src/config/locales/en/translation.json index 2c398bd7..8c549ad6 100644 --- a/src/config/locales/en/translation.json +++ b/src/config/locales/en/translation.json @@ -409,5 +409,19 @@ "attach_image": "You can only attach images or videos", "poll_invalid": "Invalid poll choices" } + }, + "notification": { + "favourite": { + "title": "Favourite", + "body": "{{username}} favourited your status" + }, + "follow": { + "title": "Follow", + "body": "{{username}} is now following you" + }, + "reblog": { + "title": "Reblog", + "body": "{{username}} boosted your status" + } } } diff --git a/src/config/locales/fr/translation.missing.json b/src/config/locales/fr/translation.missing.json index a657fa57..2951da4c 100644 --- a/src/config/locales/fr/translation.missing.json +++ b/src/config/locales/fr/translation.missing.json @@ -64,5 +64,19 @@ "new_toot": { "poll_invalid": "Invalid poll choices" } + }, + "notification": { + "favourite": { + "title": "Favourite", + "body": "{{username}} favourited your status" + }, + "follow": { + "title": "Follow", + "body": "{{username}} is now following you" + }, + "reblog": { + "title": "Reblog", + "body": "{{username}} boosted your status" + } } } diff --git a/src/config/locales/it/translation.missing.json b/src/config/locales/it/translation.missing.json index 3c972902..dd0eef53 100644 --- a/src/config/locales/it/translation.missing.json +++ b/src/config/locales/it/translation.missing.json @@ -53,5 +53,19 @@ "new_toot": { "poll_invalid": "Invalid poll choices" } + }, + "notification": { + "favourite": { + "title": "Favourite", + "body": "{{username}} favourited your status" + }, + "follow": { + "title": "Follow", + "body": "{{username}} is now following you" + }, + "reblog": { + "title": "Reblog", + "body": "{{username}} boosted your status" + } } } diff --git a/src/config/locales/ja/translation.json b/src/config/locales/ja/translation.json index e32b262b..429ef0ae 100644 --- a/src/config/locales/ja/translation.json +++ b/src/config/locales/ja/translation.json @@ -409,5 +409,19 @@ "attach_image": "画像かビデオしか添付できません", "poll_invalid": "アンケートに不正な選択肢が含まれています" } + }, + "notification": { + "favourite": { + "title": "お気に入り", + "body": "{{username}} さんにお気に入り登録されました" + }, + "follow": { + "title": "フォロー", + "body": "{{username}} さんにフォローされました" + }, + "reblog": { + "title": "ブースト", + "body": "{{username}} さんにブーストされました" + } } } diff --git a/src/config/locales/ko/translation.missing.json b/src/config/locales/ko/translation.missing.json index da2f1e61..a9c7f316 100644 --- a/src/config/locales/ko/translation.missing.json +++ b/src/config/locales/ko/translation.missing.json @@ -73,5 +73,19 @@ "new_toot": { "poll_invalid": "Invalid poll choices" } + }, + "notification": { + "favourite": { + "title": "Favourite", + "body": "{{username}} favourited your status" + }, + "follow": { + "title": "Follow", + "body": "{{username}} is now following you" + }, + "reblog": { + "title": "Reblog", + "body": "{{username}} boosted your status" + } } } diff --git a/src/config/locales/pl/translation.missing.json b/src/config/locales/pl/translation.missing.json index 905cd954..b481f2ed 100644 --- a/src/config/locales/pl/translation.missing.json +++ b/src/config/locales/pl/translation.missing.json @@ -97,5 +97,19 @@ "new_toot": { "poll_invalid": "Invalid poll choices" } + }, + "notification": { + "favourite": { + "title": "Favourite", + "body": "{{username}} favourited your status" + }, + "follow": { + "title": "Follow", + "body": "{{username}} is now following you" + }, + "reblog": { + "title": "Reblog", + "body": "{{username}} boosted your status" + } } } diff --git a/src/main/index.ts b/src/main/index.ts index 5bc5319c..671f155f 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -9,7 +9,9 @@ import { BrowserWindow, BrowserWindowConstructorOptions, MenuItemConstructorOptions, - Event + Event, + Notification, + NotificationConstructorOptions } from 'electron' import Datastore from 'nedb' import { isEmpty } from 'lodash' @@ -20,7 +22,8 @@ import path from 'path' import ContextMenu from 'electron-context-menu' import { initSplashScreen, Config } from '@trodi/electron-splashscreen' import openAboutWindow from 'about-window' -import { Status, Notification } from 'megalodon' +import { Status, Notification as RemoteNotification, Account as RemoteAccount } from 'megalodon' +import sanitizeHtml from 'sanitize-html' import Authentication from './auth' import Account from './account' @@ -29,12 +32,12 @@ import Preferences from './preferences' import Fonts from './fonts' import Hashtags from './hashtags' import UnreadNotification from './unreadNotification' -import i18n from '../config/i18n' +import i18n from '~/src/config/i18n' import Language from '../constants/language' import { LocalAccount } from '~/src/types/localAccount' import { LocalTag } from '~/src/types/localTag' import { UnreadNotification as UnreadNotificationConfig } from '~/src/types/unreadNotification' -import { AccountNotification } from '~/src/types/accountNotification' +import { Notify } from '~/src/types/notify' import { StreamingError } from '~/src/errors/streamingError' /** @@ -363,7 +366,7 @@ ipcMain.on('update-account', (event: Event, acct: LocalAccount) => { ipcMain.on('remove-account', (event: Event, id: string) => { accountManager .removeAccount(id) - .then((id) => { + .then(id => { stopUserStreaming(id) event.sender.send('response-remove-account', id) }) @@ -444,13 +447,18 @@ ipcMain.on('start-all-user-streamings', (event: Event, accounts: Array { event.sender.send(`update-start-all-user-streamings-${id}`, update) }, - (notification: Notification) => { - const accountNotification: AccountNotification = { - id: id, - notification: notification - } - // To notiy badge - event.sender.send('notification-start-all-user-streamings', accountNotification) + (notification: RemoteNotification) => { + const preferences = new Preferences(preferencesDBPath) + preferences.load().then(conf => { + const options = createNotification(notification, conf.notification.notify) + if (options !== null) { + const notify = new Notification(options) + notify.on('click', _ => { + event.sender.send('open-notification-tab', id) + }) + notify.show() + } + }) // To update notification timeline event.sender.send(`notification-start-all-user-streamings-${id}`, notification) @@ -1138,3 +1146,58 @@ async function reopenWindow() { return null } } + +const createNotification = (notification: RemoteNotification, notifyConfig: Notify): NotificationConstructorOptions | null => { + switch (notification.type) { + case 'favourite': + if (notifyConfig.favourite) { + return { + title: i18n.t('notification.favourite.title'), + body: i18n.t('notification.favourite.body', { username: username(notification.account) }), + silent: false + } as NotificationConstructorOptions + } + break + case 'follow': + if (notifyConfig.follow) { + return { + title: i18n.t('notification.follow.title'), + body: i18n.t('notification.follow.body', { username: username(notification.account) }), + silent: false + } as NotificationConstructorOptions + } + break + case 'mention': + if (notifyConfig.reply) { + return { + title: `${username(notification.status!.account)}`, + body: sanitizeHtml(notification.status!.content, { + allowedTags: [], + allowedAttributes: [] + }), + silent: false + } as NotificationConstructorOptions + } + break + case 'reblog': + if (notifyConfig.reblog) { + return { + title: i18n.t('notification.reblog.title'), + body: i18n.t('notification.reblog.body', { username: username(notification.account) }), + silent: false + } as NotificationConstructorOptions + } + break + default: + break + } + return null +} + +const username = (account: RemoteAccount): string => { + if (account.display_name !== '') { + return account.display_name + } else { + return account.username + } +} diff --git a/src/renderer/components/GlobalHeader.vue b/src/renderer/components/GlobalHeader.vue index c0a614b7..5f1019da 100644 --- a/src/renderer/components/GlobalHeader.vue +++ b/src/renderer/components/GlobalHeader.vue @@ -56,9 +56,6 @@ export default { created() { this.initialize() }, - destroyed() { - this.$store.dispatch('GlobalHeader/unbindUserStreamings') - }, methods: { activeRoute() { return this.$route.path diff --git a/src/renderer/store/GlobalHeader.ts b/src/renderer/store/GlobalHeader.ts index f10216ee..ab9011d8 100644 --- a/src/renderer/store/GlobalHeader.ts +++ b/src/renderer/store/GlobalHeader.ts @@ -1,16 +1,10 @@ -import sanitizeHtml from 'sanitize-html' -import { Account, Notification as NotificationType } from 'megalodon' import { ipcRenderer } from 'electron' import router from '@/router' import { LocalAccount } from '~/src/types/localAccount' import { Module, MutationTree, ActionTree } from 'vuex' import { RootState } from '@/store' -import { Notify } from '~/src/types/notify' -import { AccountNotification } from '~/src/types/accountNotification' import { StreamingError } from '~src/errors/streamingError' -declare var Notification: any - export type GlobalHeaderState = { accounts: Array changing: boolean @@ -55,7 +49,7 @@ const actions: ActionTree = { return accounts }, startStreamings: async ({ dispatch }) => { - dispatch('bindUserStreamingsForNotify') + dispatch('bindNotification') dispatch('startUserStreamings') }, listAccounts: ({ dispatch, commit }): Promise> => { @@ -140,24 +134,13 @@ const actions: ActionTree = { stopUserStreamings: () => { ipcRenderer.send('stop-all-user-streamings') }, - bindUserStreamingsForNotify: ({ rootState }) => { - ipcRenderer.on('notification-start-all-user-streamings', (_, accountNotification: AccountNotification) => { - const { id, notification } = accountNotification - let notify = createNotification(notification, rootState.App.notify as Notify) - if (notify) { - notify.onclick = () => { - router.push(`/${id}/home`) - // We have to wait until change el-menu-item - setTimeout(() => router.push(`/${id}/notifications`), 1000) - } - } else { - console.log('could not create notify') - } + bindNotification: () => { + ipcRenderer.removeAllListeners('open-notification-tab') + ipcRenderer.on('open-notification-tab', (_, id: string) => { + router.push(`/${id}/home`) + // We have to wait until change el-menu-item + setTimeout(() => router.push(`/${id}/notifications`), 500) }) - }, - unbindUserStreamings: () => { - ipcRenderer.removeAllListeners('notification-start-all-user-streamings') - ipcRenderer.removeAllListeners('error-start-all-user-streamings') } } @@ -169,49 +152,3 @@ const GlobalHeader: Module = { } export default GlobalHeader - -function createNotification(notification: NotificationType, notifyConfig: Notify): Notification | null { - switch (notification.type) { - case 'favourite': - if (notifyConfig.favourite) { - return new Notification('Favourite', { - body: `${username(notification.account)} favourited your status` - }) - } - break - case 'follow': - if (notifyConfig.follow) { - return new Notification('Follow', { - body: `${username(notification.account)} is now following you` - }) - } - break - case 'mention': - if (notifyConfig.reply) { - // Clean html tags - return new Notification(`${notification.status!.account.display_name}`, { - body: sanitizeHtml(notification.status!.content, { - allowedTags: [], - allowedAttributes: [] - }) - }) - } - break - case 'reblog': - if (notifyConfig.reblog) { - return new Notification('Reblog', { - body: `${username(notification.account)} boosted your status` - }) - } - break - } - return null -} - -function username(account: Account) { - if (account.display_name !== '') { - return account.display_name - } else { - return account.username - } -}