diff --git a/app/browser/reducers/tabsReducer.js b/app/browser/reducers/tabsReducer.js index 82a926820a6..d4116bb9a07 100644 --- a/app/browser/reducers/tabsReducer.js +++ b/app/browser/reducers/tabsReducer.js @@ -54,6 +54,11 @@ const tabsReducer = (state, action) => { case windowConstants.WINDOW_SET_AUDIO_MUTED: state = tabs.setAudioMuted(state, action) break + case windowConstants.WINDOW_SET_ALL_AUDIO_MUTED: + action.get('frameList').forEach((frameProp) => { + state = tabs.setAudioMuted(state, frameProp) + }) + break case windowConstants.WINDOW_SET_ACTIVE_FRAME: state = tabs.setActive(state, action) break diff --git a/app/browser/tabs.js b/app/browser/tabs.js index c147d890901..7241e9b43a1 100644 --- a/app/browser/tabs.js +++ b/app/browser/tabs.js @@ -457,9 +457,8 @@ const api = { setAudioMuted: (state, action) => { action = makeImmutable(action) - const frameProps = action.get('frameProps') const muted = action.get('muted') - const tabId = frameProps.get('tabId') + const tabId = action.get('tabId') const tab = api.getWebContents(tabId) if (tab && !tab.isDestroyed()) { tab.setAudioMuted(muted) diff --git a/app/renderer/components/tabs/tab.js b/app/renderer/components/tabs/tab.js index d7efccb4ae9..1903a0f6859 100644 --- a/app/renderer/components/tabs/tab.js +++ b/app/renderer/components/tabs/tab.js @@ -183,7 +183,8 @@ class Tab extends ImmutableComponent { onMuteFrame (muted, event) { event.stopPropagation() - windowActions.setAudioMuted(this.frame, muted) + const frame = this.frame + windowActions.setAudioMuted(frame.get('key'), frame.get('tabId'), muted) } get loading () { diff --git a/docs/windowActions.md b/docs/windowActions.md index 14ce45282af..eed0df4209e 100644 --- a/docs/windowActions.md +++ b/docs/windowActions.md @@ -505,38 +505,27 @@ If set, also indicates that the popup window is shown. -### setAudioMuted(frameProps, muted) +### setAudioMuted(frameKey, tabId, muted) Dispatches a message to indicate that the frame should be muted **Parameters** -**frameProps**: `Object`, Properties of the frame in question - -**muted**: `boolean`, true if the frame is muted - - +**frameKey**: `number`, Key of the frame in question -### muteAllAudio(framePropsList, muted) +**tabId**: `number`, Id of the tab in question -Dispatches a mute/unmute call to all frames in a provided list (used by TabList). - -**Parameters** - -**framePropsList**: `Object`, List of frame properties to consider - -**muted**: `boolean`, true if the frames should be muted +**muted**: `boolean`, true if the frame is muted -### muteAllAudioExcept(frameToSkip) +### muteAllAudio(frameList) -Dispatches a mute call to all frames except the one provided. -The provided frame will have its audio unmuted. +Dispatches a mute/unmute call to all frames in a provided list. **Parameters** -**frameToSkip**: `Object`, Properties of the frame to keep audio +**frameList**: `Object`, List of frames to consider (frameKey and tabId) diff --git a/js/actions/windowActions.js b/js/actions/windowActions.js index a40109e4ac9..0f21d744d8b 100644 --- a/js/actions/windowActions.js +++ b/js/actions/windowActions.js @@ -6,7 +6,6 @@ const AppDispatcher = require('../dispatcher/appDispatcher') const windowConstants = require('../constants/windowConstants') -const windowStore = require('../stores/windowStore') function dispatch (action) { AppDispatcher.dispatch(action) @@ -604,48 +603,28 @@ const windowActions = { /** * Dispatches a message to indicate that the frame should be muted * - * @param {Object} frameProps - Properties of the frame in question + * @param {number} frameKey - Key of the frame in question + * @param {number} tabId - Id of the tab in question * @param {boolean} muted - true if the frame is muted */ - setAudioMuted: function (frameProps, muted) { + setAudioMuted: function (frameKey, tabId, muted) { dispatch({ actionType: windowConstants.WINDOW_SET_AUDIO_MUTED, - frameProps, + frameKey, + tabId, muted }) }, /** - * Dispatches a mute/unmute call to all frames in a provided list (used by TabList). + * Dispatches a mute/unmute call to all frames in a provided list. * - * @param {Object} framePropsList - List of frame properties to consider - * @param {boolean} muted - true if the frames should be muted + * @param {Object} frameList - List of frames to consider (frameKey and tabId) */ - muteAllAudio: function (framePropsList, mute) { - framePropsList.forEach((frameProps) => { - if (mute && frameProps.get('audioPlaybackActive') && !frameProps.get('audioMuted')) { - this.setAudioMuted(frameProps, true) - } else if (!mute && frameProps.get('audioMuted')) { - this.setAudioMuted(frameProps, false) - } - }) - }, - - /** - * Dispatches a mute call to all frames except the one provided. - * The provided frame will have its audio unmuted. - * - * @param {Object} frameToSkip - Properties of the frame to keep audio - */ - muteAllAudioExcept: function (frameToSkip) { - let framePropsList = windowStore.getState().get('frames') - - framePropsList.forEach((frameProps) => { - if (frameProps.get('key') !== frameToSkip.get('key') && frameProps.get('audioPlaybackActive') && !frameProps.get('audioMuted')) { - this.setAudioMuted(frameProps, true) - } else { - this.setAudioMuted(frameProps, false) - } + muteAllAudio: function (frameList) { + dispatch({ + actionType: windowConstants.WINDOW_SET_ALL_AUDIO_MUTED, + frameList }) }, diff --git a/js/constants/windowConstants.js b/js/constants/windowConstants.js index 188c0e7e62b..9094daa01fa 100644 --- a/js/constants/windowConstants.js +++ b/js/constants/windowConstants.js @@ -100,7 +100,8 @@ const windowConstants = { WINDOW_SHOULD_MAXIMIZE: _, WINDOW_SHOULD_UNMAXIMIZE: _, WINDOW_SHOULD_EXIT_FULL_SCREEN: _, - WINDOW_SHOULD_OPEN_DEV_TOOLS: _ + WINDOW_SHOULD_OPEN_DEV_TOOLS: _, + WINDOW_SET_ALL_AUDIO_MUTED: _ } module.exports = mapValuesByKeys(windowConstants) diff --git a/js/contextMenus.js b/js/contextMenus.js index e1f8bf1c0bc..6d24a52c064 100644 --- a/js/contextMenus.js +++ b/js/contextMenus.js @@ -87,13 +87,13 @@ const getDownloadsBarHeight = () => { function tabPageTemplateInit (framePropsList) { return [{ label: locale.translation('unmuteTabs'), - click: (item) => { - windowActions.muteAllAudio(framePropsList, false) + click: () => { + windowActions.muteAllAudio(generateMuteFrameList(framePropsList, false)) } }, { label: locale.translation('muteTabs'), - click: (item) => { - windowActions.muteAllAudio(framePropsList, true) + click: () => { + windowActions.muteAllAudio(generateMuteFrameList(framePropsList, true)) } }, { label: locale.translation('closeTabPage'), @@ -103,6 +103,16 @@ function tabPageTemplateInit (framePropsList) { }] } +function generateMuteFrameList (framePropsList, muted) { + return framePropsList.map((frameProp) => { + return { + frameKey: frameProp.get('key'), + tabId: frameProp.get('tabId'), + muted: muted && frameProp.get('audioPlaybackActive') && !frameProp.get('audioMuted') + } + }) +} + function urlBarTemplateInit (searchDetail, activeFrame, e) { const items = getEditableItems(window.getSelection().toString()) const clipboardText = clipboard.readText() @@ -516,8 +526,11 @@ function flashTemplateInit (frameProps) { function tabTemplateInit (frameProps) { const frameKey = frameProps.get('key') + const tabId = frameProps.get('tabId') const template = [CommonMenu.newTabMenuItem(frameProps.get('tabId'))] const location = frameProps.get('location') + const store = windowStore.getState() + if (location !== 'about:newtab') { template.push( CommonMenu.separatorMenuItem, @@ -531,7 +544,7 @@ function tabTemplateInit (frameProps) { }, { label: locale.translation('clone'), click: (item) => { - appActions.tabCloned(frameProps.get('tabId')) + appActions.tabCloned(tabId) } }) } @@ -543,7 +556,7 @@ function tabTemplateInit (frameProps) { click: (item) => { const browserOpts = { positionByMouseCursor: true } const frameOpts = frameOptsFromFrame(frameProps).toJS() - appActions.tabMoved(frameProps.get('tabId'), frameOpts, browserOpts, -1) + appActions.tabMoved(tabId, frameOpts, browserOpts, -1) } }) } @@ -555,7 +568,7 @@ function tabTemplateInit (frameProps) { label: locale.translation(isPinned ? 'unpinTab' : 'pinTab'), click: (item) => { // Handle converting the current tab window into a pinned site - appActions.tabPinned(frameProps.get('tabId'), !isPinned) + appActions.tabPinned(tabId, !isPinned) } }) } @@ -569,11 +582,21 @@ function tabTemplateInit (frameProps) { // } // }) + const frames = windowStore.getState().get('frames') + const frameToSkip = frameProps.get('key') + const frameList = frames.map((frame) => { + return { + frameKey: frame.get('key'), + tabId: frame.get('tabId'), + muted: frame.get('key') !== frameToSkip && frame.get('audioPlaybackActive') + } + }) + template.push(CommonMenu.separatorMenuItem, { label: locale.translation('muteOtherTabs'), - click: (item) => { - windowActions.muteAllAudioExcept(frameProps) + click: () => { + windowActions.muteAllAudio(frameList) } }) @@ -583,7 +606,7 @@ function tabTemplateInit (frameProps) { template.push({ label: locale.translation(isMuted ? 'unmuteTab' : 'muteTab'), click: (item) => { - windowActions.setAudioMuted(frameProps, !isMuted) + windowActions.setAudioMuted(frameKey, tabId, !isMuted) } }) } @@ -627,7 +650,7 @@ function tabTemplateInit (frameProps) { template.push(Object.assign({}, CommonMenu.reopenLastClosedTabItem(), - { enabled: windowStore.getState().get('closedFrames').size > 0 } + { enabled: store.get('closedFrames').size > 0 } )) return menuUtil.sanitizeTemplateItems(template) diff --git a/js/stores/windowStore.js b/js/stores/windowStore.js index d379ca8f71d..d70bb850e53 100644 --- a/js/stores/windowStore.js +++ b/js/stores/windowStore.js @@ -494,8 +494,18 @@ const doAction = (action) => { } break case windowConstants.WINDOW_SET_AUDIO_MUTED: - windowState = windowState.setIn(['frames', frameStateUtil.getFramePropsIndex(frameStateUtil.getFrames(windowState), action.frameProps), 'audioMuted'], action.muted) - windowState = windowState.setIn(['tabs', frameStateUtil.getFramePropsIndex(frameStateUtil.getFrames(windowState), action.frameProps), 'audioMuted'], action.muted) + { + const index = frameStateUtil.getFrameIndex(windowState, action.frameKey) + windowState = windowState.setIn(['frames', index, 'audioMuted'], action.muted) + windowState = windowState.setIn(['tabs', index, 'audioMuted'], action.muted) + } + break + case windowConstants.WINDOW_SET_ALL_AUDIO_MUTED: + action.frameList.forEach((frameProp) => { + let index = frameStateUtil.getFrameIndex(windowState, frameProp.frameKey) + windowState = windowState.setIn(['frames', index, 'audioMuted'], frameProp.muted) + windowState = windowState.setIn(['tabs', index, 'audioMuted'], frameProp.muted) + }) break case windowConstants.WINDOW_SET_AUDIO_PLAYBACK_ACTIVE: windowState = windowState.setIn(['frames', frameStateUtil.getFramePropsIndex(frameStateUtil.getFrames(windowState), action.frameProps), 'audioPlaybackActive'], action.audioPlaybackActive)