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

Perform drag and drop from the browser end #8436

Merged
merged 4 commits into from
Apr 23, 2017
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
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