diff --git a/app/localShortcuts.js b/app/localShortcuts.js
index 2f12a0fa329..f0d73bcc892 100644
--- a/app/localShortcuts.js
+++ b/app/localShortcuts.js
@@ -7,6 +7,7 @@ const BrowserWindow = electron.BrowserWindow
const electronLocalshortcut = require('electron-localshortcut')
const messages = require('../js/constants/messages')
const appActions = require('../js/actions/appActions')
+const windowActions = require('../js/actions/windowActions')
const isDarwin = process.platform === 'darwin'
module.exports.register = (win) => {
@@ -73,6 +74,20 @@ module.exports.register = (win) => {
isPartitioned: true
})
})
+
+ electronLocalshortcut.register(win, 'Ctrl+Shift+PageUp', () => {
+ const win = BrowserWindow.getFocusedWindow()
+ if (win) {
+ windowActions.tabMoveIncrementalRequested(win.id, false)
+ }
+ })
+
+ electronLocalshortcut.register(win, 'Ctrl+Shift+PageDown', () => {
+ const win = BrowserWindow.getFocusedWindow()
+ if (win) {
+ windowActions.tabMoveIncrementalRequested(win.id)
+ }
+ })
}
module.exports.unregister = (win) => {
diff --git a/app/renderer/components/tabs/pinnedTabs.js b/app/renderer/components/tabs/pinnedTabs.js
index 233c6706ab3..37b691cf731 100644
--- a/app/renderer/components/tabs/pinnedTabs.js
+++ b/app/renderer/components/tabs/pinnedTabs.js
@@ -89,6 +89,7 @@ class PinnedTabs extends React.Component {
render () {
this.tabRefs = []
return
diff --git a/app/renderer/components/tabs/tabs.js b/app/renderer/components/tabs/tabs.js
index a2ff81a417c..ad51a98e387 100644
--- a/app/renderer/components/tabs/tabs.js
+++ b/app/renderer/components/tabs/tabs.js
@@ -159,7 +159,9 @@ class Tabs extends React.Component {
render () {
this.tabRefs = []
- return
{
case appConstants.APP_WINDOW_RESIZED:
windowState = windowState.set('windowInfo', action.windowValue)
break
+ case windowConstants.WINDOW_TAB_MOVE_INCREMENTAL_REQUESTED:
+ const sourceFrame = frameStateUtil.getActiveFrame(windowState)
+ const sourceIsPinned = sourceFrame.get('pinnedLocation')
+ const frameGroup = sourceIsPinned ? frameStateUtil.getPinnedFrames(windowState) : frameStateUtil.getNonPinnedFrames(windowState)
+ const sourceFrameGroupIndex = frameGroup.indexOf(sourceFrame)
+ const destinationFrameGroupIndex = sourceFrameGroupIndex + (action.moveNext ? 1 : -1)
+ // conditions we cannot move tab:
+ // - if we can't find it,
+ // - if we ask to move to previous and tab is first,
+ // - or we ask to move to next and tab is last
+ if (destinationFrameGroupIndex < 0 || destinationFrameGroupIndex >= frameGroup.count()) {
+ break
+ }
+ const destinationFrame = frameGroup.get(destinationFrameGroupIndex)
+ const destinationFrameIndex = frameStateUtil.getFrameIndex(windowState, destinationFrame.get('key'))
+ const sourceFrameTabId = sourceFrame.get('tabId')
+ appActions.tabIndexChangeRequested(sourceFrameTabId, destinationFrameIndex)
+ break
default:
break
}
diff --git a/test/lib/brave.js b/test/lib/brave.js
index 25297040c3a..53c9cc749b8 100644
--- a/test/lib/brave.js
+++ b/test/lib/brave.js
@@ -675,6 +675,13 @@ var exports = {
}, sourcePinKey, destinationPinKey, prepend)
})
+ this.app.client.addCommand('moveTabIncrementally', function (moveNext, windowId = 1) {
+ logVerbose(`moveTabIncrementally(${moveNext}, ${windowId}`)
+ return this.execute(function (moveNext, windowId) {
+ return devTools('electron').testData.windowActions.tabMoveIncrementalRequested(windowId, moveNext)
+ }, moveNext, windowId)
+ })
+
this.app.client.addCommand('ipcOn', function (message, fn) {
logVerbose('ipcOn("' + message + '")')
return this.execute(function (message, fn) {
@@ -719,6 +726,15 @@ var exports = {
})
})
+ this.app.client.addCommand('activateTabByFrameKey', function (key) {
+ return this.getAppState().then((val) => {
+ const tab = val.value.tabs.find((tab) => tab.frame.key === key)
+ return this.execute(function (tabId) {
+ devTools('appActions').tabActivateRequested(tabId)
+ }, tab.tabId)
+ })
+ })
+
/**
* Adds a bookmark
*
diff --git a/test/lib/selectors.js b/test/lib/selectors.js
index 6115a77d4d8..dfe69a74d25 100644
--- a/test/lib/selectors.js
+++ b/test/lib/selectors.js
@@ -7,11 +7,13 @@ module.exports = {
activeTab: '[data-test-active-tab]',
activeTabTitle: '[data-test-active-tab] [data-test-id="tabTitle"]',
activeTabFavicon: '[data-test-active-tab] [data-test-favicon]',
- pinnedTabsTabs: '.pinnedTabs [data-test-id="tab"]',
- tabsTabs: '.tabs [data-test-id="tab"]',
+ pinnedTabs: '[data-test-pinnedTabs]',
+ pinnedTabsTabs: '[data-test-pinnedTabs] [data-test-id="tab"]',
+ tabs: '[data-test-tabs]',
+ tabsTabs: '[data-test-tabs] [data-test-id="tab"]',
navigator: '#navigator',
navigatorLoadTime: '#navigator .loadTime',
- newFrameButton: '.tabs .newFrameButton',
+ newFrameButton: '[data-test-tabs] .newFrameButton',
tabPage: '.tabPage',
tabPage1: '[data-tab-page="0"]',
tabPage2: '[data-tab-page="1"]',
diff --git a/test/tab-components/tabTest.js b/test/tab-components/tabTest.js
index b009d696293..2edb572931e 100644
--- a/test/tab-components/tabTest.js
+++ b/test/tab-components/tabTest.js
@@ -4,7 +4,7 @@ const Brave = require('../lib/brave')
const messages = require('../../js/constants/messages')
const settings = require('../../js/constants/settings')
const {tabPreviewTiming} = require('../../app/common/constants/settingsEnums')
-const {urlInput, backButton, forwardButton, activeTab, activeTabTitle, activeTabFavicon, newFrameButton, notificationBar, contextMenu, pinnedTabsTabs, tabsTabs} = require('../lib/selectors')
+const {urlInput, backButton, forwardButton, activeTab, activeTabTitle, activeTabFavicon, newFrameButton, notificationBar, contextMenu, pinnedTabsTabs, tabsTabs, pinnedTabs, tabs} = require('../lib/selectors')
const newTabUrl = 'chrome-extension://mnojpmjdmbbfmejpflffifhffcmidifd/about-newtab.html'
@@ -207,6 +207,83 @@ describe('tab tests', function () {
})
})
+ describe('tab order index change', function () {
+ Brave.beforeAll(this)
+ before(function * () {
+ this.page1 = Brave.server.url('page1.html')
+ this.page2 = Brave.server.url('page2.html')
+ yield setup(this.app.client)
+ yield this.app.client
+ .waitForExist('.tabArea:nth-of-type(1) [data-frame-key="1"]') // original newtab
+ .newTab({ url: this.page1, pinned: true })
+ .waitForExist(pinnedTabs + ' [data-frame-key="2"]')
+ .newTab({ url: this.page2, pinned: true })
+ .waitForExist(pinnedTabs + ' [data-frame-key="3"]')
+ .newTab({ url: this.page1 })
+ .waitForExist(tabs + ' [data-frame-key="4"]')
+ .newTab({ url: this.page2 })
+ .waitForExist(tabs + ' [data-frame-key="5"]')
+ // check initial order
+ .waitForExist(pinnedTabs + ' [data-test-id="tab-area"][data-frame-key="2"] + [data-test-id="tab-area"][data-frame-key="3"]')
+ .waitForExist(tabs + ' [data-test-id="tab-area"][data-frame-key="1"] + [data-test-id="tab-area"][data-frame-key="4"] + [data-test-id="tab-area"][data-frame-key="5"]')
+ })
+
+ it('does not move first unpinned index backwards', function * () {
+ yield this.app.client
+ .activateTabByFrameKey(1) // first created tab
+ .waitForExist('[data-test-active-tab][data-frame-key="1"]')
+ // attempt to move the first tab backwards
+ .moveTabIncrementally(false)
+ // should not have changed anything
+ .waitForExist(tabs + ' [data-test-id="tab-area"][data-frame-key="1"] + [data-test-id="tab-area"][data-frame-key="4"] + [data-test-id="tab-area"][data-frame-key="5"]')
+ .waitForExist(pinnedTabs + ' [data-test-id="tab-area"][data-frame-key="2"] + [data-test-id="tab-area"][data-frame-key="3"]')
+ })
+
+ it('does not move last unpinned index forwards', function * () {
+ yield this.app.client
+ .activateTabByFrameKey(5)
+ .waitForExist('[data-test-active-tab][data-frame-key="4"]')
+ // attempt to move the last tab forwards
+ .moveTabIncrementally(true)
+ // should not have changed anything
+ .waitForExist(tabs + ' [data-test-id="tab-area"][data-frame-key="1"] + [data-test-id="tab-area"][data-frame-key="4"] + [data-test-id="tab-area"][data-frame-key="5"]')
+ .waitForExist(pinnedTabs + ' [data-test-id="tab-area"][data-frame-key="2"] + [data-test-id="tab-area"][data-frame-key="3"]')
+ })
+
+ it('moves from first unpinned position to next', function * () {
+ yield this.app.client
+ .activateTabByFrameKey(1)
+ .waitForExist('[data-test-active-tab][data-frame-key="1"]')
+ // move first tab forwards
+ .moveTabIncrementally(true)
+ // check tabs are changed order and pinned remain unchanged
+ .waitForExist(tabs + ' [data-test-id="tab-area"][data-frame-key="4"] + [data-test-id="tab-area"][data-frame-key="1"] + [data-test-id="tab-area"][data-frame-key="5"]')
+ .waitForExist(pinnedTabs + ' [data-test-id="tab-area"][data-frame-key="2"] + [data-test-id="tab-area"][data-frame-key="3"]')
+ })
+
+ it('moves from last unpinned index backwards', function * () {
+ yield this.app.client
+ .activateTabByFrameKey(5)
+ .waitForExist('[data-test-active-tab][data-frame-key="5"]')
+ // move last tab backwards
+ .moveTabIncrementally(false)
+ // check tabs are changed order and pinned remain unchanged
+ .waitForExist(tabs + ' [data-test-id="tab-area"][data-frame-key="4"] + [data-test-id="tab-area"][data-frame-key="5"] + [data-test-id="tab-area"][data-frame-key="1"]')
+ .waitForExist(pinnedTabs + ' [data-test-id="tab-area"][data-frame-key="2"] + [data-test-id="tab-area"][data-frame-key="3"]')
+ })
+
+ it('moves from first pinned position to next', function * () {
+ yield this.app.client
+ .activateTabByFrameKey(2)
+ .waitForExist('[data-test-active-tab][data-frame-key="2"]')
+ // move first pinned tab forwards
+ .moveTabIncrementally(true)
+ // check pinned tabs are changed order and unpinned remain unchanged
+ .waitForExist(tabs + ' [data-test-id="tab-area"][data-frame-key="4"] + [data-test-id="tab-area"][data-frame-key="5"] + [data-test-id="tab-area"][data-frame-key="1"]')
+ .waitForExist(pinnedTabs + ' [data-test-id="tab-area"][data-frame-key="3"] + [data-test-id="tab-area"][data-frame-key="2"]')
+ })
+ })
+
describe('new private tab signal', function () {
Brave.beforeAll(this)
before(function * () {