Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Add a send URL by email menu item
Browse files Browse the repository at this point in the history
Fix #3121

Auditors: @bsclifton
  • Loading branch information
bbondy committed Apr 27, 2017
1 parent 50bf50c commit f345818
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/browser/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ const createFileSubmenu = () => {
]
*/
},
// Move inside share menu when it's enabled
CommonMenu.emailPageLinkMenuItem(),
CommonMenu.separatorMenuItem,
CommonMenu.printMenuItem()
]
Expand Down
21 changes: 21 additions & 0 deletions app/browser/reducers/shareReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* This SourceCode Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict'

const appConstants = require('../../../js/constants/appConstants')
const {makeImmutable} = require('../../common/state/immutableUtil')
const {emailActiveTab} = require('../share')

const shareReducer = (state, action) => {
action = makeImmutable(action)
switch (action.get('actionType')) {
case appConstants.APP_EMAIL_ACTIVE_TAB_REQUESTED:
state = emailActiveTab(state, action.get('windowId'))
break
}
return state
}

module.exports = shareReducer
18 changes: 18 additions & 0 deletions app/browser/share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

const tabState = require('../common/state/tabState')
const {shell} = require('electron')

const emailActiveTab = (state, windowId) => {
const tabValue = tabState.getActiveTabValue(state, windowId)
shell.openExternal(
`mailto:?subject=${encodeURIComponent(tabValue.get('title') || '')}&body=${encodeURIComponent(tabValue.get('url'))}`
)
return state
}

module.exports = {
emailActiveTab
}
10 changes: 10 additions & 0 deletions app/common/commonMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ module.exports.printMenuItem = () => {
}
}

module.exports.emailPageLinkMenuItem = () => {
return {
label: locale.translation('emailPageLink'),
accelerator: 'CmdOrCtrl+Shift+I',
click: function (item, focusedWindow) {
appActions.emailActiveTabRequested(getCurrentWindowId())
}
}
}

module.exports.findOnPageMenuItem = () => {
return {
label: locale.translation('findOnPage'),
Expand Down
1 change: 1 addition & 0 deletions app/extensions/brave/locales/en-US/menu.properties
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ newSessionTab=New Session Tab
newWindow=New Window
reopenLastClosedTab=Reopen Last Closed Tab
print=Print…
emailPageLink=Email Page Link…
findOnPage=Find on Page…
find=Find…
checkForUpdates=Check for Updates…
Expand Down
1 change: 1 addition & 0 deletions app/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ var rendererIdentifiers = function () {
'newWindow',
'reopenLastClosedTab',
'print',
'emailPageLink',
'findOnPage',
'find',
'checkForUpdates',
Expand Down
10 changes: 10 additions & 0 deletions docs/appActions.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ A request for a URL load for the active tab of the specified window



### emailActiveTabRequested(windowId)

A request for a URL email share occurred

**Parameters**

**windowId**: `number`, the window ID to use for the active tab



### maybeCreateTabRequested(createProperties)

A request for a "maybe" new tab has been made with the specified createProperties
Expand Down
11 changes: 11 additions & 0 deletions js/actions/appActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@ const appActions = {
})
},

/**
* A request for a URL email share occurred
* @param {number} windowId - the window ID to use for the active tab
*/
emailActiveTabRequested: function (windowId) {
AppDispatcher.dispatch({
actionType: appConstants.APP_EMAIL_ACTIVE_TAB_REQUESTED,
windowId
})
},

/**
* A request for a "maybe" new tab has been made with the specified createProperties
* If a tab is already opened it will instead set it as active.
Expand Down
1 change: 1 addition & 0 deletions js/constants/appConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const appConstants = {
APP_MAYBE_CREATE_TAB_REQUESTED: _,
APP_LOAD_URL_REQUESTED: _,
APP_LOAD_URL_IN_ACTIVE_TAB_REQUESTED: _,
APP_EMAIL_ACTIVE_TAB_REQUESTED: _,
APP_NEW_WEB_CONTENTS_ADDED: _,
APP_TAB_DESTROYED: _,
APP_SET_MENUBAR_TEMPLATE: _,
Expand Down
3 changes: 2 additions & 1 deletion js/stores/appStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ const handleAppAction = (action) => {
require('../../app/browser/reducers/passwordManagerReducer'),
require('../../app/browser/reducers/tabMessageBoxReducer'),
require('../../app/browser/reducers/dragDropReducer'),
require('../../app/browser/reducers/extensionsReducer')
require('../../app/browser/reducers/extensionsReducer'),
require('../../app/browser/reducers/shareReducer')
]
initialized = true
appState = action.appState
Expand Down
42 changes: 42 additions & 0 deletions test/unit/app/browser/reducers/shareReducerTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* global describe, it, before, after */
const mockery = require('mockery')
const sinon = require('sinon')
const Immutable = require('immutable')
const assert = require('assert')
const fakeElectron = require('../../../lib/fakeElectron')

const appConstants = require('../../../../../js/constants/appConstants')
require('../../../braveUnit')

describe('shareReducer', function () {
let shareReducer
before(function () {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
})
mockery.registerMock('electron', fakeElectron)
this.shareStub = {
emailActiveTab: sinon.stub()
}
mockery.registerMock('../share', this.shareStub)
shareReducer = require('../../../../../app/browser/reducers/shareReducer')
})

after(function () {
mockery.disable()
})

describe('APP_EMAIL_ACTIVE_TAB_REQUESTED', function () {
before(function () {
this.state = Immutable.Map()
this.windowId = 2
this.newState = shareReducer(this.state, {actionType: appConstants.APP_EMAIL_ACTIVE_TAB_REQUESTED, windowId: this.windowId})
})
it('calls emailActiveTab once with the correct args', function () {
const callCount = this.shareStub.emailActiveTab.withArgs(this.state, this.windowId).callCount
assert.equal(callCount, 1)
})
})
})
67 changes: 67 additions & 0 deletions test/unit/app/browser/shareTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* global describe, it, before, after, afterEach */
const mockery = require('mockery')
const sinon = require('sinon')
const Immutable = require('immutable')
const assert = require('assert')
const fakeElectron = require('../../lib/fakeElectron')

require('../../braveUnit')

describe('share API', function () {
let share
before(function () {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
})
mockery.registerMock('electron', fakeElectron)
share = require('../../../../app/browser/share')
})

after(function () {
mockery.disable()
})

describe('emailActiveTab', function () {
before(function () {
this.state = Immutable.fromJS({
tabs: [{
windowId: 2,
tabId: 2,
url: 'https://www.brave.com/2',
title: 'title 2',
active: true
}, {
windowId: 3,
tabId: 3,
url: 'https://www.brave.com/3',
title: 'title 3'
}, {
windowId: 5,
tabId: 5,
url: 'https://www.brave.com/5',
title: 'title 5',
active: true
}]
})
this.windowId = 2
this.openExternalSpy = sinon.spy(fakeElectron.shell, 'openExternal')
})
afterEach(function () {
this.openExternalSpy.reset()
})
it('calls openExternal with the correct args', function () {
share.emailActiveTab(this.state, 2)
const expectedUrl = 'mailto:?subject=title%202&body=https%3A%2F%2Fwww.brave.com%2F2'
const callCount = this.openExternalSpy.withArgs(expectedUrl).callCount
assert.equal(callCount, 1)
})
it('takes active tab windowId into consideration', function () {
share.emailActiveTab(this.state, 5)
const expectedUrl = 'mailto:?subject=title%205&body=https%3A%2F%2Fwww.brave.com%2F5'
const callCount = this.openExternalSpy.withArgs(expectedUrl).callCount
assert.equal(callCount, 1)
})
})
})
6 changes: 6 additions & 0 deletions test/unit/app/common/commonMenuTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ describe('Common menu module unit tests', function () {
})
})

describe('emailPageLinkMenuItem', function () {
it('has the expected defaults set', function () {
checkExpectedDefaults(commonMenu.emailPageLinkMenuItem)
})
})

describe('findOnPageMenuItem', function () {
it('has the expected defaults set', function () {
checkExpectedDefaults(commonMenu.findOnPageMenuItem)
Expand Down
2 changes: 2 additions & 0 deletions test/unit/lib/fakeElectron.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const fakeElectron = {
showOpenDialog: function () { }
},
shell: {
openExternal: function () {
},
showItemInFolder: function () {
},
openItem: function () {
Expand Down

0 comments on commit f345818

Please sign in to comment.