Merge pull request #974 from h3poteto/iss-958

closes #958 Notify notification in main process
This commit is contained in:
AkiraFukushima 2019-07-22 23:03:05 +09:00 committed by GitHub
commit b51d7e1a15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 180 additions and 85 deletions

View File

@ -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"
}
}
}

View File

@ -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"
}
}
}

View File

@ -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"
}
}
}

View File

@ -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"
}
}
}

View File

@ -409,5 +409,19 @@
"attach_image": "画像かビデオしか添付できません",
"poll_invalid": "アンケートに不正な選択肢が含まれています"
}
},
"notification": {
"favourite": {
"title": "お気に入り",
"body": "{{username}} さんにお気に入り登録されました"
},
"follow": {
"title": "フォロー",
"body": "{{username}} さんにフォローされました"
},
"reblog": {
"title": "ブースト",
"body": "{{username}} さんにブーストされました"
}
}
}

View File

@ -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"
}
}
}

View File

@ -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"
}
}
}

View File

@ -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<LocalAcco
(update: Status) => {
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
}
}

View File

@ -56,9 +56,6 @@ export default {
created() {
this.initialize()
},
destroyed() {
this.$store.dispatch('GlobalHeader/unbindUserStreamings')
},
methods: {
activeRoute() {
return this.$route.path

View File

@ -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<LocalAccount>
changing: boolean
@ -55,7 +49,7 @@ const actions: ActionTree<GlobalHeaderState, RootState> = {
return accounts
},
startStreamings: async ({ dispatch }) => {
dispatch('bindUserStreamingsForNotify')
dispatch('bindNotification')
dispatch('startUserStreamings')
},
listAccounts: ({ dispatch, commit }): Promise<Array<LocalAccount>> => {
@ -140,24 +134,13 @@ const actions: ActionTree<GlobalHeaderState, RootState> = {
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<GlobalHeaderState, RootState> = {
}
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
}
}