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

Commit

Permalink
Merge pull request #8436 from brave/dnd-plusplus
Browse files Browse the repository at this point in the history
Perform drag and drop from the browser end
  • Loading branch information
bbondy authored Apr 23, 2017
2 parents 8e63cc0 + 07053d9 commit 4123103
Show file tree
Hide file tree
Showing 16 changed files with 430 additions and 97 deletions.
11 changes: 6 additions & 5 deletions app/browser/reducers/dragDropReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@

'use strict'

const {APP_DRAG_STARTED, APP_DRAG_STOPPED, APP_DATA_DROPPED, APP_DRAGGED_OVER} = require('../../../js/constants/appConstants')
const appActions = require('../../../js/constants/appConstants')
const Immutable = require('immutable')

const dragDropReducer = (state, action) => {
switch (action.actionType) {
case APP_DRAG_STARTED:
case appActions.APP_DRAG_STARTED:
state = state.set('dragData', Immutable.fromJS({
windowId: action.windowId,
type: action.dragType,
data: action.dragData
}))
break
case APP_DRAG_STOPPED:
case appActions.APP_DRAG_CANCELLED:
case appActions.APP_DRAG_ENDED:
state = state.delete('dragData')
break
case APP_DATA_DROPPED:
case appActions.APP_DATA_DROPPED:
state = state.setIn(['dragData', 'dropWindowId'], action.dropWindowId)
break
case APP_DRAGGED_OVER:
case appActions.APP_DRAGGED_OVER:
state = state.mergeIn(['dragData', 'dragOverData'], action.draggedOverData)
break
}
Expand Down
27 changes: 24 additions & 3 deletions app/browser/reducers/tabsReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@

const appConstants = require('../../../js/constants/appConstants')
const tabs = require('../tabs')
const {getWebContents} = require('../webContentsCache')
const tabState = require('../../common/state/tabState')
const windowConstants = require('../../../js/constants/windowConstants')
const {makeImmutable} = require('../../common/state/immutableUtil')
const {getFlashResourceId} = require('../../../js/flash')
const Immutable = require('immutable')
const dragTypes = require('../../../js/constants/dragTypes')
const {frameOptsFromFrame} = require('../../../js/state/frameStateUtil')

const tabsReducer = (state, action) => {
action = makeImmutable(action)
Expand All @@ -20,9 +24,14 @@ const tabsReducer = (state, action) => {
case appConstants.APP_TAB_CREATED:
state = tabState.maybeCreateTab(state, action)
break
case appConstants.APP_TAB_MOVED:
state = tabs.moveTo(state, action)
case appConstants.APP_TAB_MOVED: {
const tabId = action.get('tabId')
const frameOpts = action.get('frameOpts')
const browserOpts = action.get('browserOpts') || new Immutable.Map()
const windowId = action.get('windowId') || -1
state = tabs.moveTo(state, tabId, frameOpts, browserOpts, windowId)
break
}
case appConstants.APP_CREATE_TAB_REQUESTED:
state = tabs.createTab(state, action)
break
Expand All @@ -38,7 +47,7 @@ const tabsReducer = (state, action) => {
case appConstants.APP_ALLOW_FLASH_ONCE:
case appConstants.APP_ALLOW_FLASH_ALWAYS:
{
const webContents = tabs.getWebContents(action.get('tabId'))
const webContents = getWebContents(action.get('tabId'))
if (webContents && !webContents.isDestroyed() && webContents.getURL() === action.get('url')) {
webContents.authorizePlugin(getFlashResourceId())
}
Expand Down Expand Up @@ -68,6 +77,18 @@ const tabsReducer = (state, action) => {
case appConstants.APP_FRAME_CHANGED:
state = tabState.updateFrame(state, action)
break
case appConstants.APP_DRAG_ENDED: {
const dragData = state.get('dragData')
if (dragData && dragData.get('type') === dragTypes.TAB) {
const frame = dragData.get('data')
const frameOpts = frameOptsFromFrame(frame).toJS()
const browserOpts = { positionByMouseCursor: true }
frameOpts.indexByFrameKey = dragData.getIn(['dragOverData', 'draggingOverKey'])
frameOpts.prependIndexByFrameKey = dragData.getIn(['dragOverData', 'draggingOverLeftHalf'])
state = tabs.moveTo(state, frame.get('tabId'), frameOpts, browserOpts, dragData.get('dropWindowId'))
}
break
}
}
return state
}
Expand Down
66 changes: 35 additions & 31 deletions app/browser/tabs.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/* 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 appActions = require('../../js/actions/appActions')
const config = require('../../js/constants/config')
const Immutable = require('immutable')
Expand All @@ -10,18 +14,11 @@ const {isSessionPartition} = require('../../js/state/frameStateUtil')
const {getOrigin} = require('../../js/state/siteUtil')
const {getSetting} = require('../../js/settings')
const settings = require('../../js/constants/settings')
const {cleanupWebContents, currentWebContents, getWebContents, updateWebContents} = require('./webContentsCache')

let currentWebContents = {}
let currentPartitionNumber = 0
const incrementPartitionNumber = () => ++currentPartitionNumber

const cleanupWebContents = (tabId) => {
if (currentWebContents[tabId]) {
delete currentWebContents[tabId]
appActions.tabClosed({ tabId })
}
}

const normalizeUrl = function (url) {
if (isSourceAboutUrl(url)) {
url = getTargetAboutUrl(url)
Expand All @@ -36,7 +33,7 @@ const normalizeUrl = function (url) {
}

const getTabValue = function (tabId) {
let tab = api.getWebContents(tabId)
let tab = getWebContents(tabId)
if (tab) {
let tabValue = makeImmutable(tab.tabValue())
tabValue = tabValue.set('canGoBack', tab.canGoBack())
Expand Down Expand Up @@ -189,7 +186,7 @@ const api = {
console.log('responsive')
})

currentWebContents[tabId] = tab
updateWebContents(tabId, tab)
let tabValue = getTabValue(tabId)
if (tabValue) {
appActions.tabCreated(tabValue)
Expand Down Expand Up @@ -230,14 +227,10 @@ const api = {
}
},

getWebContents: (tabId) => {
return currentWebContents[tabId]
},

toggleDevTools: (state, action) => {
action = makeImmutable(action)
const tabId = action.get('tabId')
const tab = api.getWebContents(tabId)
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
if (tab.isDevToolsOpened()) {
tab.closeDevTools()
Expand All @@ -252,7 +245,7 @@ const api = {
action = makeImmutable(action)
let frameProps = action.get('frameProps')
let tabId = frameProps.get('tabId')
let tab = api.getWebContents(tabId)
let tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
tab.setActive(true)
let tabValue = getTabValue(tabId)
Expand All @@ -264,7 +257,7 @@ const api = {
loadURL: (state, action) => {
action = makeImmutable(action)
const tabId = action.get('tabId')
const tab = api.getWebContents(tabId)
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
let url = normalizeUrl(action.get('url'))
// We only allow loading URLs explicitly when the origin is
Expand All @@ -287,7 +280,7 @@ const api = {
action = makeImmutable(action)
const windowId = action.get('windowId')
const tabValue = tabState.getActiveTabValue(state, windowId)
const tab = tabValue && api.getWebContents(tabValue.get('tabId'))
const tab = tabValue && getWebContents(tabValue.get('tabId'))
if (tab && !tab.isDestroyed()) {
const url = normalizeUrl(action.get('url'))
tab.loadURL(url)
Expand All @@ -300,7 +293,7 @@ const api = {
const frameProps = action.get('frameProps')
const muted = action.get('muted')
const tabId = frameProps.get('tabId')
const tab = api.getWebContents(tabId)
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
tab.setAudioMuted(muted)
const tabValue = getTabValue(tabId)
Expand All @@ -317,7 +310,7 @@ const api = {
if (tabValue && tabValue.get('index') !== undefined) {
options = options.set('index', tabValue.get('index') + 1)
}
const tab = api.getWebContents(tabId)
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
tab.clone(options.toJS(), (newTab) => {
})
Expand All @@ -329,7 +322,7 @@ const api = {
action = makeImmutable(action)
const tabId = action.get('tabId')
const pinned = action.get('pinned')
const tab = api.getWebContents(tabId)
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
const url = tab.getURL()
// For now we only support 1 tab pin per URL
Expand Down Expand Up @@ -357,7 +350,7 @@ const api = {
},

closeTab: (tabId, forceClose) => {
const tab = api.getWebContents(tabId)
const tab = getWebContents(tabId)
try {
if (tab && !tab.isDestroyed()) {
if (forceClose) {
Expand Down Expand Up @@ -414,14 +407,10 @@ const api = {
return state
},

moveTo: (state, action) => {
action = makeImmutable(action)
const tabId = action.get('tabId')
const frameOpts = action.get('frameOpts')
const browserOpts = action.get('browserOpts') || new Immutable.Map()
// positionByMouseCursor: true
const windowId = action.get('windowId') || -1
const tab = api.getWebContents(tabId)
moveTo: (state, tabId, frameOpts, browserOpts, windowId) => {
frameOpts = makeImmutable(frameOpts)
browserOpts = makeImmutable(browserOpts)
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
const tabValue = getTabValue(tabId)
const guestInstanceId = tabValue && tabValue.get('guestInstanceId')
Expand All @@ -433,6 +422,21 @@ const api = {
if (windowId != null && currentWindowId === windowId) {
return state
}

if (windowId == null || windowId === -1) {
// If there's only one tab and we're dragging outside the window, then disallow
// a new window to be created.
const windowTabCount = tabState.getTabsByWindowId(state, currentWindowId).size
if (windowTabCount === 1) {
return state
}
}

if (tabValue.get('pinned')) {
// If the current tab is pinned, then don't allow to drag out
return state
}

tab.detach(() => {
if (windowId == null || windowId === -1) {
appActions.newWindow(makeImmutable(frameOpts), browserOpts)
Expand All @@ -452,7 +456,7 @@ const api = {
const windowId = createProperties.get('windowId')
const tabData = tabState.getMatchingTab(state, createProperties, windowId, url)
if (tabData) {
const tab = api.getWebContents(tabData.get('id'))
const tab = getWebContents(tabData.get('id'))
if (tab && !tab.isDestroyed()) {
tab.setActive(true)
}
Expand Down
29 changes: 29 additions & 0 deletions app/browser/webContentsCache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* 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 appActions = require('../../js/actions/appActions')

const currentWebContents = {}

const cleanupWebContents = (tabId) => {
if (currentWebContents[tabId]) {
delete currentWebContents[tabId]
appActions.tabClosed({ tabId })
}
}

const getWebContents = (tabId) => {
return currentWebContents[tabId]
}

const updateWebContents = (tabId, tab) => {
currentWebContents[tabId] = tab
}

module.exports = {
cleanupWebContents,
getWebContents,
updateWebContents,
currentWebContents
}
4 changes: 2 additions & 2 deletions app/renderer/components/bookmarksToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,10 +536,10 @@ const styles = StyleSheet.create({
}
},
bookmarkToolbarButton__draggingOverLeft: {
marginLeft: bookmarkToolbarButtonDraggingMargin
paddingLeft: bookmarkToolbarButtonDraggingMargin
},
bookmarkToolbarButton__draggingOverRight: {
marginRight: bookmarkToolbarButtonDraggingMargin
paddingRight: bookmarkToolbarButtonDraggingMargin
},
bookmarkToolbarButton__isDragging: {
opacity: '0.2'
Expand Down
7 changes: 7 additions & 0 deletions docs/appActions.md
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,13 @@ Notifies the app that a drop operation occurred



### dragCancelled()

Notifies the app that a drop operation was cancelled
because ESC was pressed.




* * *

Expand Down
12 changes: 11 additions & 1 deletion js/actions/appActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,7 @@ const appActions = {
*/
dragEnded: function () {
AppDispatcher.dispatch({
actionType: appConstants.APP_DRAG_STOPPED
actionType: appConstants.APP_DRAG_ENDED
})
},

Expand All @@ -1198,6 +1198,16 @@ const appActions = {
actionType: appConstants.APP_DRAGGED_OVER,
draggedOverData
})
},

/**
* Notifies the app that a drop operation was cancelled
* because ESC was pressed.
*/
dragCancelled: function () {
AppDispatcher.dispatch({
actionType: appConstants.APP_DRAG_CANCELLED
})
}
}

Expand Down
Loading

0 comments on commit 4123103

Please sign in to comment.