Whalebird-desktop-client-ma.../src/renderer/store/GlobalHeader.ts

180 lines
7.9 KiB
TypeScript

import router from '@/router'
import { LocalAccount } from '~/src/types/localAccount'
import { Module, MutationTree, ActionTree } from 'vuex'
import { RootState } from '@/store'
import { MyWindow } from '~/src/types/global'
import { LocalServer } from '~src/types/localServer'
const win = (window as any) as MyWindow
export type GlobalHeaderState = {
accounts: Array<[LocalAccount, LocalServer]>
changing: boolean
hide: boolean
}
const state = (): GlobalHeaderState => ({
accounts: [],
changing: false,
hide: false
})
export const MUTATION_TYPES = {
UPDATE_ACCOUNTS: 'updateAccounts',
UPDATE_CHANGING: 'updateChanging',
CHANGE_HIDE: 'changeHide'
}
const mutations: MutationTree<GlobalHeaderState> = {
[MUTATION_TYPES.UPDATE_ACCOUNTS]: (state: GlobalHeaderState, accounts: Array<[LocalAccount, LocalServer]>) => {
state.accounts = accounts
},
[MUTATION_TYPES.UPDATE_CHANGING]: (state: GlobalHeaderState, value: boolean) => {
state.changing = value
},
[MUTATION_TYPES.CHANGE_HIDE]: (state: GlobalHeaderState, value: boolean) => {
state.hide = value
}
}
export const ACTION_TYPES = {
INIT_LOAD: 'initLoad',
START_STREAMINGS: 'startStreamings',
LIST_ACCOUNTS: 'listAccounts',
WATCH_SHORTCUT_EVENTS: 'watchShortcutEvents',
REMOVE_SHORTCUT_EVENTS: 'removeShortcutEvents',
LOAD_HIDE: 'loadHide',
SWITCH_HIDE: 'switchHide',
LOAD_TIMELINES: 'loadTimelines',
BIND_STREAMINGS: 'bindStreamings',
BIND_NOTIFICATION: 'bindNotification'
}
const actions: ActionTree<GlobalHeaderState, RootState> = {
[ACTION_TYPES.INIT_LOAD]: async ({ dispatch }): Promise<Array<LocalAccount>> => {
// Ignore error
try {
await dispatch(ACTION_TYPES.REMOVE_SHORTCUT_EVENTS)
await dispatch(ACTION_TYPES.LOAD_HIDE)
dispatch(ACTION_TYPES.WATCH_SHORTCUT_EVENTS)
} catch (err) {
console.error(err)
}
const accounts = await dispatch(ACTION_TYPES.LIST_ACCOUNTS)
await dispatch(ACTION_TYPES.LOAD_TIMELINES, accounts)
await dispatch(ACTION_TYPES.BIND_STREAMINGS, accounts)
// Block to root path when user use browser-back, like mouse button.
// Because any contents are not rendered when browser back to / from home.
router.beforeEach((to, from, next) => {
if (!(to.fullPath === '/' && from.name)) {
return next()
}
})
return accounts
},
[ACTION_TYPES.LIST_ACCOUNTS]: async ({ commit }): Promise<Array<[LocalAccount, LocalServer]>> => {
const accounts: Array<[LocalAccount, LocalServer]> = await win.ipcRenderer.invoke('list-accounts')
commit(MUTATION_TYPES.UPDATE_ACCOUNTS, accounts)
return accounts
},
[ACTION_TYPES.WATCH_SHORTCUT_EVENTS]: ({ state, commit, rootState, rootGetters }) => {
win.ipcRenderer.on('change-account', (_, account: LocalAccount) => {
if (state.changing) {
return null
}
if ((rootState.route.params.id as string) === account[0].id) {
return null
}
// When the modal window is active, don't change account
if (rootGetters['TimelineSpace/Modals/modalOpened']) {
return null
}
// changing finish after loading
commit(MUTATION_TYPES.UPDATE_CHANGING, true)
router.push(`/${account[0].id}/home`)
return true
})
},
[ACTION_TYPES.REMOVE_SHORTCUT_EVENTS]: async () => {
win.ipcRenderer.removeAllListeners('change-account')
return true
},
[ACTION_TYPES.LOAD_HIDE]: async ({ commit }): Promise<boolean> => {
const hide: boolean = await win.ipcRenderer.invoke('get-global-header')
commit(MUTATION_TYPES.CHANGE_HIDE, hide)
return hide
},
[ACTION_TYPES.SWITCH_HIDE]: async ({ dispatch }, hide: boolean): Promise<boolean> => {
await win.ipcRenderer.invoke('change-global-header', hide)
dispatch(ACTION_TYPES.LOAD_HIDE)
return true
},
[ACTION_TYPES.BIND_NOTIFICATION]: () => {
win.ipcRenderer.removeAllListeners('open-notification-tab')
win.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)
})
},
[ACTION_TYPES.LOAD_TIMELINES]: async ({ dispatch }, req: Array<[LocalAccount, LocalServer]>) => {
req.forEach(async ([account, server]) => {
await dispatch('TimelineSpace/Contents/Home/fetchTimeline', { account, server }, { root: true })
await dispatch('TimelineSpace/Contents/Notifications/fetchNotifications', { account, server }, { root: true })
await dispatch('TimelineSpace/Contents/Local/fetchLocalTimeline', { account, server }, { root: true })
await dispatch('TimelineSpace/Contents/Public/fetchPublicTimeline', { account, server }, { root: true })
await dispatch('TimelineSpace/Contents/DirectMessages/fetchTimeline', { account, server }, { root: true })
})
},
[ACTION_TYPES.BIND_STREAMINGS]: async ({ commit }, req: Array<[LocalAccount, LocalServer]>) => {
req.forEach(async ([account, _server]) => {
win.ipcRenderer.removeAllListeners(`update-user-streamings-${account.id}`)
win.ipcRenderer.on(`update-user-streamings-${account.id}`, (_, update: Entity.Status) => {
commit('TimelineSpace/Contents/Home/appendTimeline', { status: update, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`notification-user-streamings-${account.id}`)
win.ipcRenderer.on(`notification-user-streamings-${account.id}`, (_, notification: Entity.Notification) => {
commit('TimelineSpace/Contents/Notifications/appendNotifications', { notification, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`delete-user-streamings-${account.id}`)
win.ipcRenderer.on(`delete-user-streamings-${account.id}`, (_, id: string) => {
commit('TimelineSpace/Contents/Home/deleteToot', { statusId: id, accountId: account.id }, { root: true })
commit('TimelineSpace/Contents/Notifications/deleteToot', { statusId: id, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`update-local-streamings-${account.id}`)
win.ipcRenderer.on(`update-local-streamings-${account.id}`, (_, update: Entity.Status) => {
commit('TimelineSpace/Contents/Local/appendTimeline', { status: update, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`delete-local-streamings-${account.id}`)
win.ipcRenderer.on(`delete-local-streamings-${account.id}`, (_, id: string) => {
commit('TimelineSpace/Contents/Local/deleteToot', { statusId: id, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`update-public-streamings-${account.id}`)
win.ipcRenderer.on(`update-public-streamings-${account.id}`, (_, update: Entity.Status) => {
commit('TimelineSpace/Contents/Public/appendTimeline', { status: update, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`delete-public-streamings-${account.id}`)
win.ipcRenderer.on(`delete-public-streamings-${account.id}`, (_, id: string) => {
commit('TimelineSpace/Contents/Public/deleteToot', { statusId: id, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`update-direct-streamings-${account.id}`)
win.ipcRenderer.on(`update-direct-streamings-${account.id}`, (_, update: Entity.Status) => {
commit('TimelineSpace/Contents/DirectMessages/appendTimeline', { status: update, accountId: account.id }, { root: true })
})
win.ipcRenderer.removeAllListeners(`delete-direct-streamings-${account.id}`)
win.ipcRenderer.on(`delete-direct-streamings-${account.id}`, (_, id: string) => {
commit('TimelineSpace/Contents/DirectMessages/deleteToot', { statusId: id, accountId: account.id }, { root: true })
})
})
}
}
const GlobalHeader: Module<GlobalHeaderState, RootState> = {
namespaced: true,
state: state,
mutations: mutations,
actions: actions
}
export default GlobalHeader