diff --git a/app/common/state/contextMenuState.js b/app/common/state/contextMenuState.js index 31840aa9830..aa4b5cf356e 100644 --- a/app/common/state/contextMenuState.js +++ b/app/common/state/contextMenuState.js @@ -5,6 +5,7 @@ const Immutable = require('immutable') const assert = require('assert') const { makeImmutable, isMap } = require('./immutableUtil') +const uuid = require('uuid') const validateState = function (state) { state = makeImmutable(state) @@ -12,31 +13,34 @@ const validateState = function (state) { return state } +let contextMenuDetail = Immutable.Map() + const api = { setContextMenu: (windowState, detail) => { detail = makeImmutable(detail) windowState = validateState(windowState) if (!detail) { - if (windowState.getIn(['contextMenuDetail', 'type']) === 'hamburgerMenu') { + if (contextMenuDetail.get('type') === 'hamburgerMenu') { windowState = windowState.set('hamburgerMenuWasOpen', true) } else { windowState = windowState.set('hamburgerMenuWasOpen', false) } + contextMenuDetail = Immutable.Map() windowState = windowState.delete('contextMenuDetail') } else { if (!(detail.get('type') === 'hamburgerMenu' && windowState.get('hamburgerMenuWasOpen'))) { - windowState = windowState.set('contextMenuDetail', detail) + contextMenuDetail = detail + windowState = windowState.set('contextMenuDetail', uuid()) } windowState = windowState.set('hamburgerMenuWasOpen', false) } - return windowState }, getContextMenu: (windowState) => { windowState = validateState(windowState) - return windowState.get('contextMenuDetail', Immutable.Map()) + return contextMenuDetail }, selectedIndex: (windowState) => { diff --git a/app/renderer/components/common/contextMenu/contextMenu.js b/app/renderer/components/common/contextMenu/contextMenu.js index 845c4660838..bc2f7102d32 100644 --- a/app/renderer/components/common/contextMenu/contextMenu.js +++ b/app/renderer/components/common/contextMenu/contextMenu.js @@ -15,6 +15,9 @@ const windowActions = require('../../../../../js/actions/windowActions') // Constants const keyCodes = require('../../../../common/constants/keyCodes') +// State +const contextMenuState = require('../../../../common/state/contextMenuState') + // Utils const cx = require('../../../../../js/lib/classSet') const frameStateUtil = require('../../../../../js/state/frameStateUtil') @@ -215,7 +218,7 @@ class ContextMenu extends React.Component { const currentWindow = state.get('currentWindow') const activeFrame = frameStateUtil.getActiveFrame(currentWindow) || Immutable.Map() const selectedIndex = currentWindow.getIn(['ui', 'contextMenu', 'selectedIndex'], null) - const contextMenuDetail = currentWindow.get('contextMenuDetail', Immutable.Map()) + const contextMenuDetail = contextMenuState.getContextMenu(currentWindow) const props = {} props.lastZoomPercentage = activeFrame.get('lastZoomPercentage') diff --git a/app/renderer/components/frame/frame.js b/app/renderer/components/frame/frame.js index ec167d5ba9d..ee2691c0a41 100644 --- a/app/renderer/components/frame/frame.js +++ b/app/renderer/components/frame/frame.js @@ -24,6 +24,7 @@ const windowStore = require('../../../../js/stores/windowStore') const appStoreRenderer = require('../../../../js/stores/appStoreRenderer') // State +const contextMenuState = require('../../../common/state/contextMenuState') const siteSettings = require('../../../../js/state/siteSettings') const siteSettingsState = require('../../../common/state/siteSettingsState') const tabState = require('../../../common/state/tabState') @@ -856,7 +857,7 @@ class Frame extends React.Component { const allSiteSettings = siteSettingsState.getAllSiteSettings(state, isPrivate) const frameSiteSettings = siteSettings.getSiteSettingsForURL(allSiteSettings, location) || Immutable.Map() - const contextMenu = currentWindow.get('contextMenuDetail') + const contextMenu = contextMenuState.getContextMenu(currentWindow) const tab = tabId && tabId > -1 && tabState.getByTabId(state, tabId) const props = {} diff --git a/docs/state.md b/docs/state.md index 2c0b8ae5e5d..6cd2d03a6fe 100644 --- a/docs/state.md +++ b/docs/state.md @@ -674,7 +674,7 @@ WindowStore }, cleanedOnShutdown: boolean, // whether app data was successfully cleared on shutdown closedFrames: [], // holds the same type of frame objects as frames - contextMenuDetail: { + contextMenuDetail: { // currently using uuid hack to avoid serializing click function in template bottom: number, // the bottom position of the context menu left: number, // the left position of the context menu maxHeight: number, // the maximum height of the context menu diff --git a/js/actions/windowActions.js b/js/actions/windowActions.js index 63b1e673a9f..2fb96d25dc5 100644 --- a/js/actions/windowActions.js +++ b/js/actions/windowActions.js @@ -536,9 +536,16 @@ const windowActions = { * @param {Object} detail - The context menu detail */ setContextMenuDetail: function (detail) { + // TODO(darkdh): This is a hack to prevent dispatch from serializing + // click function in template. `contextMenuDetail` is just a uuid to trigger + // state update for new menu + const Immutable = require('immutable') + const contextMenuState = require('../../app/common/state/contextMenuState') + let state = contextMenuState.setContextMenu(Immutable.Map(), detail) + const contextMenuDetail = state.get('contextMenuDetail') dispatch({ actionType: windowConstants.WINDOW_SET_CONTEXT_MENU_DETAIL, - detail + contextMenuDetail }) }, diff --git a/js/stores/windowStore.js b/js/stores/windowStore.js index cd2d05a54c5..4bfd039b4ff 100644 --- a/js/stores/windowStore.js +++ b/js/stores/windowStore.js @@ -465,21 +465,28 @@ const doAction = (action) => { windowState = windowState.delete('bookmarkFolderDetail') break case windowConstants.WINDOW_AUTOFILL_SELECTION_CLICKED: + windowState = contextMenuState.setContextMenu(windowState) ipc.send('autofill-selection-clicked', action.tabId, action.value, action.frontEndId, action.index) - windowState = windowState.delete('contextMenuDetail') break case windowConstants.WINDOW_AUTOFILL_POPUP_HIDDEN: - if (!action.detail && - windowState.getIn(['contextMenuDetail', 'type']) === 'autofill' && - windowState.getIn(['contextMenuDetail', 'tabId']) === action.tabId) { - windowState = windowState.delete('contextMenuDetail') - if (action.notify) { - ipc.send('autofill-popup-hidden', action.tabId) + { + const contextMenuDetail = contextMenuState.getContextMenu(windowState) + if (!action.detail && + contextMenuDetail.get('type') === 'autofill' && + contextMenuDetail.get('tabId') === action.tabId) { + windowState = contextMenuState.setContextMenu(windowState) + if (action.notify) { + ipc.send('autofill-popup-hidden', action.tabId) + } } + break } - break case windowConstants.WINDOW_SET_CONTEXT_MENU_DETAIL: - windowState = contextMenuState.setContextMenu(windowState, action.detail) + if (action.contextMenuDetail) { + windowState = windowState.set('contextMenuDetail', action.contextMenuDetail) + } else { + windowState = windowState.delete('contextMenuDetail') + } break case windowConstants.WINDOW_SET_POPUP_WINDOW_DETAIL: if (!action.detail) {