diff options
Diffstat (limited to 'src/background')
-rw-r--r-- | src/background/actions/command.js | 2 | ||||
-rw-r--r-- | src/background/actions/index.js | 3 | ||||
-rw-r--r-- | src/background/actions/operation.js | 92 | ||||
-rw-r--r-- | src/background/actions/tab.js | 11 | ||||
-rw-r--r-- | src/background/components/background.js | 9 | ||||
-rw-r--r-- | src/background/components/indicator.js | 45 | ||||
-rw-r--r-- | src/background/components/operation.js | 118 | ||||
-rw-r--r-- | src/background/components/tab.js | 17 | ||||
-rw-r--r-- | src/background/index.js | 10 | ||||
-rw-r--r-- | src/background/reducers/index.js | 3 | ||||
-rw-r--r-- | src/background/reducers/tab.js | 19 | ||||
-rw-r--r-- | src/background/shared/completions/histories.js (renamed from src/background/histories.js) | 0 | ||||
-rw-r--r-- | src/background/shared/completions/index.js | 84 | ||||
-rw-r--r-- | src/background/shared/completions/tabs.js | 10 | ||||
-rw-r--r-- | src/background/shared/indicators.js | 13 | ||||
-rw-r--r-- | src/background/shared/tabs.js (renamed from src/background/tabs.js) | 27 | ||||
-rw-r--r-- | src/background/shared/zooms.js (renamed from src/background/zooms.js) | 0 |
17 files changed, 338 insertions, 125 deletions
diff --git a/src/background/actions/command.js b/src/background/actions/command.js index 4c52bca..2f7305a 100644 --- a/src/background/actions/command.js +++ b/src/background/actions/command.js @@ -1,5 +1,5 @@ import actions from '../actions'; -import * as tabs from 'background/tabs'; +import * as tabs from '../shared/tabs'; import * as parsers from 'shared/commands/parsers'; import * as properties from 'shared/settings/properties'; 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/operation.js b/src/background/actions/operation.js deleted file mode 100644 index 10c366f..0000000 --- a/src/background/actions/operation.js +++ /dev/null @@ -1,92 +0,0 @@ -import operations from 'shared/operations'; -import messages from 'shared/messages'; -import * as tabs from 'background/tabs'; -import * as zooms from 'background/zooms'; - -const sendConsoleShowCommand = (tab, command) => { - return browser.tabs.sendMessage(tab.id, { - type: messages.CONSOLE_SHOW_COMMAND, - command, - }); -}; - -// This switch statement is only gonna get longer as more -// features are added, so disable complexity check -/* eslint-disable complexity */ -const exec = (operation, tab) => { - switch (operation.type) { - case operations.TAB_CLOSE: - return tabs.closeTab(tab.id); - case operations.TAB_CLOSE_FORCE: - return tabs.closeTabForce(tab.id); - case operations.TAB_REOPEN: - return tabs.reopenTab(); - case operations.TAB_PREV: - return tabs.selectPrevTab(tab.index, operation.count); - case operations.TAB_NEXT: - return tabs.selectNextTab(tab.index, operation.count); - case operations.TAB_FIRST: - return tabs.selectFirstTab(); - case operations.TAB_LAST: - return tabs.selectLastTab(); - case operations.TAB_PREV_SEL: - return tabs.selectPrevSelTab(); - case operations.TAB_RELOAD: - return tabs.reload(tab, operation.cache); - case operations.TAB_PIN: - return tabs.updateTabPinned(tab, true); - case operations.TAB_UNPIN: - return tabs.updateTabPinned(tab, false); - case operations.TAB_TOGGLE_PINNED: - return tabs.toggleTabPinned(tab); - case operations.TAB_DUPLICATE: - return tabs.duplicate(tab.id); - case operations.ZOOM_IN: - return zooms.zoomIn(); - case operations.ZOOM_OUT: - return zooms.zoomOut(); - case operations.ZOOM_NEUTRAL: - return zooms.neutral(); - case operations.COMMAND_SHOW: - return sendConsoleShowCommand(tab, ''); - case operations.COMMAND_SHOW_OPEN: - if (operation.alter) { - // alter url - return sendConsoleShowCommand(tab, 'open ' + tab.url); - } - return sendConsoleShowCommand(tab, 'open '); - case operations.COMMAND_SHOW_TABOPEN: - if (operation.alter) { - // alter url - return sendConsoleShowCommand(tab, 'tabopen ' + tab.url); - } - return sendConsoleShowCommand(tab, 'tabopen '); - case operations.COMMAND_SHOW_WINOPEN: - if (operation.alter) { - // alter url - return sendConsoleShowCommand(tab, 'winopen ' + tab.url); - } - return sendConsoleShowCommand(tab, 'winopen '); - case operations.COMMAND_SHOW_BUFFER: - return sendConsoleShowCommand(tab, 'buffer '); - case operations.FIND_START: - return browser.tabs.sendMessage(tab.id, { - type: messages.CONSOLE_SHOW_FIND - }); - case operations.CANCEL: - return browser.tabs.sendMessage(tab.id, { - type: messages.CONSOLE_HIDE, - }); - case operations.PAGE_SOURCE: - return browser.tabs.create({ - url: 'view-source:' + tab.url, - index: tab.index + 1, - openerTabId: tab.id, - }); - default: - return Promise.resolve(); - } -}; -/* eslint-enable complexity */ - -export { exec }; 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/background.js b/src/background/components/background.js index fae3fbb..e13424b 100644 --- a/src/background/components/background.js +++ b/src/background/components/background.js @@ -1,10 +1,9 @@ import messages from 'shared/messages'; -import * as operationActions from 'background/actions/operation'; import * as commandActions from 'background/actions/command'; import * as settingActions from 'background/actions/setting'; import * as findActions from 'background/actions/find'; import * as tabActions from 'background/actions/tab'; -import * as commands from 'shared/commands'; +import * as completions from '../shared/completions'; export default class BackgroundComponent { constructor(store) { @@ -27,10 +26,6 @@ export default class BackgroundComponent { let find = this.store.getState().find; switch (message.type) { - case messages.BACKGROUND_OPERATION: - return this.store.dispatch( - operationActions.exec(message.operation, sender.tab), - sender); case messages.OPEN_URL: if (message.newTab) { let action = tabActions.openNewTab( @@ -49,7 +44,7 @@ export default class BackgroundComponent { case messages.SETTINGS_QUERY: return Promise.resolve(this.store.getState().setting.value); case messages.CONSOLE_QUERY_COMPLETIONS: - return commands.complete(message.text, settings.value); + return completions.complete(message.text, settings.value); case messages.SETTINGS_RELOAD: this.store.dispatch(settingActions.load()); return this.broadcastSettingsChanged(); diff --git a/src/background/components/indicator.js b/src/background/components/indicator.js new file mode 100644 index 0000000..cceb119 --- /dev/null +++ b/src/background/components/indicator.js @@ -0,0 +1,45 @@ +import * as indicators from '../shared/indicators'; +import messages from 'shared/messages'; + +export default class IndicatorComponent { + constructor(store) { + this.store = store; + + messages.onMessage(this.onMessage.bind(this)); + + browser.browserAction.onClicked.addListener(this.onClicked); + browser.tabs.onActivated.addListener((info) => { + return browser.tabs.query({ currentWindow: true }).then(() => { + return this.onTabActivated(info); + }); + }); + } + + onTabActivated(info) { + return browser.tabs.sendMessage(info.tabId, { + type: messages.ADDON_ENABLED_QUERY, + }).then((resp) => { + return this.updateIndicator(resp.enabled); + }); + } + + onClicked(tab) { + browser.tabs.sendMessage(tab.id, { + type: messages.ADDON_TOGGLE_ENABLED, + }); + } + + onMessage(message) { + switch (message.type) { + case messages.ADDON_ENABLED_RESPONSE: + return this.updateIndicator(message.enabled); + } + } + + updateIndicator(enabled) { + if (enabled) { + return indicators.enable(); + } + return indicators.disable(); + } +} diff --git a/src/background/components/operation.js b/src/background/components/operation.js new file mode 100644 index 0000000..9a0b4e1 --- /dev/null +++ b/src/background/components/operation.js @@ -0,0 +1,118 @@ +import messages from 'shared/messages'; +import operations from 'shared/operations'; +import * as tabs from '../shared//tabs'; +import * as zooms from '../shared/zooms'; + +export default class BackgroundComponent { + constructor(store) { + this.store = store; + + browser.runtime.onMessage.addListener((message, sender) => { + try { + return this.onMessage(message, sender); + } catch (e) { + return browser.tabs.sendMessage(sender.tab.id, { + type: messages.CONSOLE_SHOW_ERROR, + text: e.message, + }); + } + }); + } + + onMessage(message, sender) { + switch (message.type) { + case messages.BACKGROUND_OPERATION: + return this.store.dispatch( + this.exec(message.operation, sender.tab), + sender); + } + } + + // 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); + case operations.TAB_CLOSE_FORCE: + return tabs.closeTabForce(tab.id); + case operations.TAB_REOPEN: + return tabs.reopenTab(); + case operations.TAB_PREV: + return tabs.selectPrevTab(tab.index, operation.count); + case operations.TAB_NEXT: + return tabs.selectNextTab(tab.index, operation.count); + case operations.TAB_FIRST: + return tabs.selectFirstTab(); + case operations.TAB_LAST: + return tabs.selectLastTab(); + case operations.TAB_PREV_SEL: + if (tabState.previousSelected > 0) { + return tabs.selectTab(tabState.previousSelected); + } + break; + case operations.TAB_RELOAD: + return tabs.reload(tab, operation.cache); + case operations.TAB_PIN: + return tabs.updateTabPinned(tab, true); + case operations.TAB_UNPIN: + return tabs.updateTabPinned(tab, false); + case operations.TAB_TOGGLE_PINNED: + return tabs.toggleTabPinned(tab); + case operations.TAB_DUPLICATE: + return tabs.duplicate(tab.id); + case operations.ZOOM_IN: + return zooms.zoomIn(); + case operations.ZOOM_OUT: + return zooms.zoomOut(); + case operations.ZOOM_NEUTRAL: + return zooms.neutral(); + case operations.COMMAND_SHOW: + return this.sendConsoleShowCommand(tab, ''); + case operations.COMMAND_SHOW_OPEN: + if (operation.alter) { + // alter url + return this.sendConsoleShowCommand(tab, 'open ' + tab.url); + } + return this.sendConsoleShowCommand(tab, 'open '); + case operations.COMMAND_SHOW_TABOPEN: + if (operation.alter) { + // alter url + return this.sendConsoleShowCommand(tab, 'tabopen ' + tab.url); + } + return this.sendConsoleShowCommand(tab, 'tabopen '); + case operations.COMMAND_SHOW_WINOPEN: + if (operation.alter) { + // alter url + return this.sendConsoleShowCommand(tab, 'winopen ' + tab.url); + } + return this.sendConsoleShowCommand(tab, 'winopen '); + case operations.COMMAND_SHOW_BUFFER: + return this.sendConsoleShowCommand(tab, 'buffer '); + case operations.FIND_START: + return browser.tabs.sendMessage(tab.id, { + type: messages.CONSOLE_SHOW_FIND + }); + case operations.CANCEL: + return browser.tabs.sendMessage(tab.id, { + type: messages.CONSOLE_HIDE, + }); + case operations.PAGE_SOURCE: + return browser.tabs.create({ + url: 'view-source:' + tab.url, + index: tab.index + 1, + openerTabId: tab.id, + }); + default: + return Promise.resolve(); + } + } + + sendConsoleShowCommand(tab, command) { + return browser.tabs.sendMessage(tab.id, { + type: messages.CONSOLE_SHOW_COMMAND, + command, + }); + } +} 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 ff27796..3f1013c 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -1,6 +1,9 @@ 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 IndicatorComponent from 'background/components/indicator'; import reducers from 'background/reducers'; import { createStore } from 'shared/store'; import * as versions from 'shared/versions'; @@ -14,8 +17,13 @@ const store = createStore(reducers, (e, sender) => { }); } }); -// eslint-disable-next-line no-unused-vars + +/* eslint-disable no-unused-vars */ const backgroundComponent = new BackgroundComponent(store); +const operationComponent = new OperationComponent(store); +const tabComponent = new TabComponent(store); +const indicatorComponent = new IndicatorComponent(store); +/* eslint-enable no-unused-vars */ 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/histories.js b/src/background/shared/completions/histories.js index a7d3d47..a7d3d47 100644 --- a/src/background/histories.js +++ b/src/background/shared/completions/histories.js diff --git a/src/background/shared/completions/index.js b/src/background/shared/completions/index.js new file mode 100644 index 0000000..73b7b27 --- /dev/null +++ b/src/background/shared/completions/index.js @@ -0,0 +1,84 @@ +import * as tabs from './tabs'; +import * as histories from './histories'; + +const getOpenCompletions = (command, keywords, searchConfig) => { + return histories.getCompletions(keywords).then((pages) => { + let historyItems = pages.map((page) => { + return { + caption: page.title, + content: command + ' ' + page.url, + url: page.url + }; + }); + let engineNames = Object.keys(searchConfig.engines); + let engineItems = engineNames.filter(name => name.startsWith(keywords)) + .map(name => ({ + caption: name, + content: command + ' ' + name + })); + + let completions = []; + if (engineItems.length > 0) { + completions.push({ + name: 'Search Engines', + items: engineItems + }); + } + if (historyItems.length > 0) { + completions.push({ + name: 'History', + items: historyItems + }); + } + return completions; + }); +}; + +const getCompletions = (line, settings) => { + let typedWords = line.trim().split(/ +/); + let typing = ''; + if (!line.endsWith(' ')) { + typing = typedWords.pop(); + } + + if (typedWords.length === 0) { + return Promise.resolve([]); + } + let name = typedWords.shift(); + let keywords = typedWords.concat(typing).join(' '); + + switch (name) { + case 'o': + case 'open': + case 't': + case 'tabopen': + case 'w': + case 'winopen': + return getOpenCompletions(name, keywords, settings.search); + case 'b': + case 'buffer': + return tabs.getCompletions(keywords).then((gotTabs) => { + let items = gotTabs.map((tab) => { + return { + caption: tab.title, + content: name + ' ' + tab.title, + url: tab.url, + icon: tab.favIconUrl + }; + }); + return [ + { + name: 'Buffers', + items: items + } + ]; + }); + } + return Promise.resolve([]); +}; + +const complete = (line, settings) => { + return getCompletions(line, settings); +}; + +export { complete }; diff --git a/src/background/shared/completions/tabs.js b/src/background/shared/completions/tabs.js new file mode 100644 index 0000000..5edddca --- /dev/null +++ b/src/background/shared/completions/tabs.js @@ -0,0 +1,10 @@ +const getCompletions = (keyword) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let matched = tabs.filter((t) => { + return t.url.includes(keyword) || t.title && t.title.includes(keyword); + }); + return matched; + }); +}; + +export { getCompletions }; diff --git a/src/background/shared/indicators.js b/src/background/shared/indicators.js new file mode 100644 index 0000000..74002c4 --- /dev/null +++ b/src/background/shared/indicators.js @@ -0,0 +1,13 @@ +const enable = () => { + return browser.browserAction.setIcon({ + path: 'resources/enabled_32x32.png', + }); +}; + +const disable = () => { + return browser.browserAction.setIcon({ + path: 'resources/disabled_32x32.png', + }); +}; + +export { enable, disable }; diff --git a/src/background/tabs.js b/src/background/shared/tabs.js index e939870..f1dcc73 100644 --- a/src/background/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) { @@ -66,15 +56,6 @@ const selectByKeyword = (current, keyword) => { }); }; -const getCompletions = (keyword) => { - return browser.tabs.query({ currentWindow: true }).then((tabs) => { - let matched = tabs.filter((t) => { - return t.url.includes(keyword) || t.title && t.title.includes(keyword); - }); - return matched; - }); -}; - const selectPrevTab = (current, count) => { return browser.tabs.query({ currentWindow: true }).then((tabs) => { if (tabs.length < 2) { @@ -111,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) => { @@ -139,7 +120,7 @@ const duplicate = (id) => { export { closeTab, closeTabForce, reopenTab, selectAt, selectByKeyword, - getCompletions, selectPrevTab, selectNextTab, selectFirstTab, - selectLastTab, selectPrevSelTab, reload, updateTabPinned, + selectPrevTab, selectNextTab, selectFirstTab, + selectLastTab, selectTab, reload, updateTabPinned, toggleTabPinned, duplicate }; diff --git a/src/background/zooms.js b/src/background/shared/zooms.js index e3e2aa6..e3e2aa6 100644 --- a/src/background/zooms.js +++ b/src/background/shared/zooms.js |