From 98bc2326eeeb5d915706dee9aadc2ac3e9af1789 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 6 May 2018 11:45:07 +0900 Subject: Refactor background directories --- src/background/shared/tabs.js | 136 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/background/shared/tabs.js (limited to 'src/background/shared/tabs.js') diff --git a/src/background/shared/tabs.js b/src/background/shared/tabs.js new file mode 100644 index 0000000..277afb2 --- /dev/null +++ b/src/background/shared/tabs.js @@ -0,0 +1,136 @@ +let prevSelTab = 1; +let currSelTab = 1; + +browser.tabs.onActivated.addListener((activeInfo) => { + return browser.tabs.query({ currentWindow: true }).then(() => { + prevSelTab = currSelTab; + currSelTab = activeInfo.tabId; + }); +}); + +const closeTab = (id) => { + return browser.tabs.get(id).then((tab) => { + if (!tab.pinned) { + return browser.tabs.remove(id); + } + }); +}; + +const closeTabForce = (id) => { + return browser.tabs.remove(id); +}; + +const reopenTab = () => { + return browser.sessions.getRecentlyClosed({ + maxResults: 1 + }).then((sessions) => { + if (sessions.length === 0) { + return; + } + let session = sessions[0]; + if (session.tab) { + return browser.sessions.restore(session.tab.sessionId); + } + return browser.sessions.restore(session.window.sessionId); + }); +}; + +const selectAt = (index) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + if (tabs.length < 2) { + return; + } + if (index < 0 || tabs.length <= index) { + throw new RangeError(`tab ${index + 1} does not exist`); + } + let id = tabs[index].id; + return browser.tabs.update(id, { active: true }); + }); +}; + +const selectByKeyword = (current, keyword) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let matched = tabs.filter((t) => { + return t.url.includes(keyword) || t.title.includes(keyword); + }); + + if (matched.length === 0) { + throw new RangeError('No matching buffer for ' + keyword); + } + for (let tab of matched) { + if (tab.index > current.index) { + return browser.tabs.update(tab.id, { active: true }); + } + } + return browser.tabs.update(matched[0].id, { active: true }); + }); +}; + +const selectPrevTab = (current, count) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + if (tabs.length < 2) { + return; + } + let select = (current - count + tabs.length) % tabs.length; + let id = tabs[select].id; + return browser.tabs.update(id, { active: true }); + }); +}; + +const selectNextTab = (current, count) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + if (tabs.length < 2) { + return; + } + let select = (current + count) % tabs.length; + let id = tabs[select].id; + return browser.tabs.update(id, { active: true }); + }); +}; + +const selectFirstTab = () => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let id = tabs[0].id; + return browser.tabs.update(id, { active: true }); + }); +}; + +const selectLastTab = () => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let id = tabs[tabs.length - 1].id; + return browser.tabs.update(id, { active: true }); + }); +}; + +const selectPrevSelTab = () => { + return browser.tabs.update(prevSelTab, { active: true }); +}; + +const reload = (current, cache) => { + return browser.tabs.reload( + current.id, + { bypassCache: cache } + ); +}; + +const updateTabPinned = (current, pinned) => { + return browser.tabs.query({ currentWindow: true, active: true }) + .then(() => { + return browser.tabs.update(current.id, { pinned: pinned }); + }); +}; + +const toggleTabPinned = (current) => { + updateTabPinned(current, !current.pinned); +}; + +const duplicate = (id) => { + return browser.tabs.duplicate(id); +}; + +export { + closeTab, closeTabForce, reopenTab, selectAt, selectByKeyword, + selectPrevTab, selectNextTab, selectFirstTab, + selectLastTab, selectPrevSelTab, reload, updateTabPinned, + toggleTabPinned, duplicate +}; -- cgit v1.2.3 From 2c366ac3b1d7114869567845c955238e96056565 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 6 May 2018 16:11:40 +0900 Subject: Previous selected tab as redux --- src/background/actions/index.js | 3 +++ src/background/actions/tab.js | 11 ++++++++++- src/background/components/operation.js | 7 ++++++- src/background/components/tab.js | 17 +++++++++++++++++ src/background/index.js | 3 +++ src/background/reducers/index.js | 3 +++ src/background/reducers/tab.js | 19 +++++++++++++++++++ src/background/shared/tabs.js | 16 +++------------- 8 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/background/components/tab.js create mode 100644 src/background/reducers/tab.js (limited to 'src/background/shared/tabs.js') diff --git a/src/background/actions/index.js b/src/background/actions/index.js index 2bdaaf2..3833389 100644 --- a/src/background/actions/index.js +++ b/src/background/actions/index.js @@ -5,4 +5,7 @@ export default { // Find FIND_SET_KEYWORD: 'find.set.keyword', + + // Tab + TAB_SELECTED: 'tab.selected', }; diff --git a/src/background/actions/tab.js b/src/background/actions/tab.js index 3c642fd..0d439fd 100644 --- a/src/background/actions/tab.js +++ b/src/background/actions/tab.js @@ -1,3 +1,5 @@ +import actions from './index'; + const openNewTab = (url, openerTabId, background = false, adjacent = false) => { if (adjacent) { return browser.tabs.query({ @@ -18,4 +20,11 @@ const openToTab = (url, tab) => { return browser.tabs.update(tab.id, { url: url }); }; -export { openNewTab, openToTab }; +const selected = (tabId) => { + return { + type: actions.TAB_SELECTED, + tabId, + }; +}; + +export { openNewTab, openToTab, selected }; diff --git a/src/background/components/operation.js b/src/background/components/operation.js index b9581c9..9a0b4e1 100644 --- a/src/background/components/operation.js +++ b/src/background/components/operation.js @@ -30,6 +30,8 @@ export default class BackgroundComponent { // eslint-disable-next-line complexity exec(operation, tab) { + let tabState = this.store.getState().tab; + switch (operation.type) { case operations.TAB_CLOSE: return tabs.closeTab(tab.id); @@ -46,7 +48,10 @@ export default class BackgroundComponent { case operations.TAB_LAST: return tabs.selectLastTab(); case operations.TAB_PREV_SEL: - return tabs.selectPrevSelTab(); + if (tabState.previousSelected > 0) { + return tabs.selectTab(tabState.previousSelected); + } + break; case operations.TAB_RELOAD: return tabs.reload(tab, operation.cache); case operations.TAB_PIN: diff --git a/src/background/components/tab.js b/src/background/components/tab.js new file mode 100644 index 0000000..b273546 --- /dev/null +++ b/src/background/components/tab.js @@ -0,0 +1,17 @@ +import * as tabActions from '../actions/tab'; + +export default class TabComponent { + constructor(store) { + this.store = store; + + browser.tabs.onActivated.addListener((info) => { + return browser.tabs.query({ currentWindow: true }).then(() => { + return this.onTabActivated(info); + }); + }); + } + + onTabActivated(info) { + return this.store.dispatch(tabActions.selected(info.tabId)); + } +} diff --git a/src/background/index.js b/src/background/index.js index 4f6b23f..be042ce 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -2,6 +2,7 @@ import * as settingActions from 'background/actions/setting'; import messages from 'shared/messages'; import BackgroundComponent from 'background/components/background'; import OperationComponent from 'background/components/operation'; +import TabComponent from 'background/components/tab'; import reducers from 'background/reducers'; import { createStore } from 'shared/store'; import * as versions from 'shared/versions'; @@ -19,6 +20,8 @@ const store = createStore(reducers, (e, sender) => { const backgroundComponent = new BackgroundComponent(store); // eslint-disable-next-line no-unused-vars const operationComponent = new OperationComponent(store); +// eslint-disable-next-line no-unused-vars +const tabComponent = new TabComponent(store); store.dispatch(settingActions.load()); diff --git a/src/background/reducers/index.js b/src/background/reducers/index.js index 63ff0f8..5729f0a 100644 --- a/src/background/reducers/index.js +++ b/src/background/reducers/index.js @@ -1,15 +1,18 @@ import settingReducer from './setting'; import findReducer from './find'; +import tabReducer from './tab'; // Make setting reducer instead of re-use const defaultState = { setting: settingReducer(undefined, {}), find: findReducer(undefined, {}), + tab: tabReducer(undefined, {}), }; export default function reducer(state = defaultState, action = {}) { return Object.assign({}, state, { setting: settingReducer(state.setting, action), find: findReducer(state.find, action), + tab: tabReducer(state.tab, action), }); } diff --git a/src/background/reducers/tab.js b/src/background/reducers/tab.js new file mode 100644 index 0000000..e0cdf32 --- /dev/null +++ b/src/background/reducers/tab.js @@ -0,0 +1,19 @@ +import actions from 'background/actions'; + +const defaultState = { + previousSelected: -1, + currentSelected: -1, +}; + +export default function reducer(state = defaultState, action = {}) { + switch (action.type) { + case actions.TAB_SELECTED: + return { + previousSelected: state.currentSelected, + currentSelected: action.tabId, + }; + default: + return state; + } +} + diff --git a/src/background/shared/tabs.js b/src/background/shared/tabs.js index 277afb2..f1dcc73 100644 --- a/src/background/shared/tabs.js +++ b/src/background/shared/tabs.js @@ -1,13 +1,3 @@ -let prevSelTab = 1; -let currSelTab = 1; - -browser.tabs.onActivated.addListener((activeInfo) => { - return browser.tabs.query({ currentWindow: true }).then(() => { - prevSelTab = currSelTab; - currSelTab = activeInfo.tabId; - }); -}); - const closeTab = (id) => { return browser.tabs.get(id).then((tab) => { if (!tab.pinned) { @@ -102,8 +92,8 @@ const selectLastTab = () => { }); }; -const selectPrevSelTab = () => { - return browser.tabs.update(prevSelTab, { active: true }); +const selectTab = (id) => { + return browser.tabs.update(id, { active: true }); }; const reload = (current, cache) => { @@ -131,6 +121,6 @@ const duplicate = (id) => { export { closeTab, closeTabForce, reopenTab, selectAt, selectByKeyword, selectPrevTab, selectNextTab, selectFirstTab, - selectLastTab, selectPrevSelTab, reload, updateTabPinned, + selectLastTab, selectTab, reload, updateTabPinned, toggleTabPinned, duplicate }; -- cgit v1.2.3