Skip to content

fix: ensure menu items update properly #2605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/common/ipc-main-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const ipcMainEvents = Object.freeze({
IPFSD: 'ipfsd',
IPFS_CONFIG_CHANGED: 'ipfsConfigChanged',
LANG_UPDATED: 'languageUpdated',
LANG_UPDATED_SUCCEEDED: 'languageUpdatedSucceeded',
MENUBAR_CLOSE: 'menubar-will-close',
MENUBAR_OPEN: 'menubar-will-open',
UPDATING: 'updating',
Expand Down
2 changes: 1 addition & 1 deletion src/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const pDefer = require('p-defer')
const logger = require('./common/logger')

/**
* @typedef { 'tray' | 'tray-menu-state' | 'tray.update-menu' | 'countlyDeviceId' | 'manualCheckForUpdates' | 'startIpfs' | 'stopIpfs' | 'restartIpfs' | 'getIpfsd' | 'launchWebUI' | 'webui' | 'splashScreen' | 'i18n.initDone' } ContextProperties
* @typedef { 'tray' | 'tray.update-menu' | 'countlyDeviceId' | 'manualCheckForUpdates' | 'startIpfs' | 'stopIpfs' | 'restartIpfs' | 'getIpfsd' | 'launchWebUI' | 'webui' | 'splashScreen' | 'i18n.initDone' } ContextProperties
*/

/**
Expand Down
21 changes: 18 additions & 3 deletions src/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,32 @@ module.exports = async function () {
backend: {
loadPath: join(__dirname, '../assets/locales/{{lng}}.json')
}
},
(err, t) => {
if (err) {
logger.error('[i18n] init failed', err)
return
}
logger.info('[i18n] init done')
ctx.setProp('i18n.initDone', true)
})
logger.info('[i18n] init done')
ctx.setProp('i18n.initDone', true)

ipcMain.on(ipcMainEvents.LANG_UPDATED, async (_, lang) => {
logger.fileLogger.info('[i18n] language updated to %s requested', lang)
if (lang === store.get('language')) {
logger.fileLogger.info('[i18n] language update skipped due to no change')
return
}

store.safeSet('language', lang)

await i18n.changeLanguage(lang)
await i18n.changeLanguage(lang, async (err, t) => {
if (err) {
logger.error('[i18n] language update failed', err)
return
}
logger.fileLogger.info('[i18n] language update succeeded')
ipcMain.emit(ipcMainEvents.LANG_UPDATED_SUCCEEDED)
})
})
}
40 changes: 13 additions & 27 deletions src/tray.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const runGarbageCollector = require('./run-gc')
const ipcMainEvents = require('./common/ipc-main-events')
const { setCustomBinary, clearCustomBinary, hasCustomBinary } = require('./custom-ipfs-binary')
const { STATUS } = require('./daemon')
const { IS_MAC, IS_WIN, VERSION, KUBO_VERSION } = require('./common/consts')
const { IS_MAC, VERSION, KUBO_VERSION } = require('./common/consts')

const CONFIG_KEYS = require('./common/config-keys')

Expand All @@ -33,7 +33,7 @@ function buildCheckbox (key, label) {
// or other OSes and must be registered globally. They still collide with global
// accelerator. Please see ../utils/setup-global-shortcut.js for more info.
/**
*
* Note: This method needs to be called any time the menu item labels need updated. i.e. when the language changes.
* @returns {Promise<Omit<Electron.Menu, 'getMenuItemById'> & {getMenuItemById: (id: string) => Electron.MenuItem}>}
*/
async function buildMenu () {
Expand Down Expand Up @@ -265,32 +265,20 @@ function icon (status) {
// https://www.electronjs.org/docs/faq#my-apps-tray-disappeared-after-a-few-minutes
let tray = null

const setupMenu = async () => {
const ctx = getCtx()
const updateMenu = ctx.getFn('tray.update-menu')
const menu = await buildMenu()

tray.setContextMenu(menu)
tray.setToolTip('IPFS Desktop')

menu.on('menu-will-show', () => { ipcMain.emit(ipcMainEvents.MENUBAR_OPEN) })
menu.on('menu-will-close', () => { ipcMain.emit(ipcMainEvents.MENUBAR_CLOSE) })

updateMenu()
}

module.exports = async function () {
const ctx = getCtx()
logger.info('[tray] starting')
tray = new Tray(icon(off))
tray.setToolTip('IPFS Desktop')

const launchWebUI = ctx.getFn('launchWebUI')

// this state needs to be mutable so menu can update visible/hidden and enabled/disabled menu items
const state = {
status: null,
gcRunning: false,
isUpdating: false
}
ctx.setProp('tray-menu-state', state)

// macOS tray drop files
tray.on('drop-files', async (_, files) => {
Expand All @@ -315,10 +303,12 @@ module.exports = async function () {
tray.on('double-click', async () => launchWebUI('/'))

ctx.setProp('tray.update-menu', async () => {
const ctx = getCtx()
const { status, gcRunning, isUpdating } = await ctx.getProp('tray-menu-state')
logger.fileLogger.debug('[tray.update-menu] updating tray menu')
const { status, gcRunning, isUpdating } = state
const errored = status === STATUS.STARTING_FAILED || status === STATUS.STOPPING_FAILED
const menu = await buildMenu()
const menu = await buildMenu() // new menu instance every time
menu.on('menu-will-show', () => { ipcMain.emit(ipcMainEvents.MENUBAR_OPEN) })
menu.on('menu-will-close', () => { ipcMain.emit(ipcMainEvents.MENUBAR_CLOSE) })

menu.getMenuItemById('ipfsIsStarting').visible = status === STATUS.STARTING_STARTED && !gcRunning && !isUpdating
menu.getMenuItemById('ipfsIsRunning').visible = status === STATUS.STARTING_FINISHED && !gcRunning && !isUpdating
Expand Down Expand Up @@ -370,11 +360,7 @@ module.exports = async function () {
}
}

if (!IS_MAC && !IS_WIN) {
// On Linux, in order for changes made to individual MenuItems to take effect,
// you have to call setContextMenu again - https://electronjs.org/docs/api/tray
tray.setContextMenu(menu)
}
tray.setContextMenu(menu) // this is needed on macOS too, otherwise the menu won't update
})
const updateMenu = ctx.getFn('tray.update-menu')

Expand Down Expand Up @@ -405,13 +391,13 @@ module.exports = async function () {
})

ipcMain.on(ipcMainEvents.CONFIG_UPDATED, () => { updateMenu() })
ipcMain.on(ipcMainEvents.LANG_UPDATED, () => { updateMenu() })
ipcMain.on(ipcMainEvents.LANG_UPDATED_SUCCEEDED, () => { updateMenu() })

nativeTheme.on('updated', () => {
updateMenu()
})

await setupMenu()
await updateMenu()

createToggler(CONFIG_KEYS.MONOCHROME_TRAY_ICON, async ({ newValue }) => {
return store.safeSet(CONFIG_KEYS.MONOCHROME_TRAY_ICON, newValue, () => true)
Expand Down