Merge remote-tracking branch 'origin/master' into background-adjacent-tabs
This commit is contained in:
commit
4d7c24f38a
120 changed files with 14625 additions and 1641 deletions
79
src/background/actions/command.js
Normal file
79
src/background/actions/command.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
import actions from '../actions';
|
||||
import * as tabs from 'background/tabs';
|
||||
import * as parsers from 'shared/commands/parsers';
|
||||
import * as properties from 'shared/settings/properties';
|
||||
|
||||
const openCommand = (url) => {
|
||||
return browser.tabs.query({
|
||||
active: true, currentWindow: true
|
||||
}).then((gotTabs) => {
|
||||
if (gotTabs.length > 0) {
|
||||
return browser.tabs.update(gotTabs[0].id, { url: url });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const tabopenCommand = (url) => {
|
||||
return browser.tabs.create({ url: url });
|
||||
};
|
||||
|
||||
const winopenCommand = (url) => {
|
||||
return browser.windows.create({ url });
|
||||
};
|
||||
|
||||
const bufferCommand = (keywords) => {
|
||||
if (keywords.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
let keywordsStr = keywords.join(' ');
|
||||
return browser.tabs.query({
|
||||
active: true, currentWindow: true
|
||||
}).then((gotTabs) => {
|
||||
if (gotTabs.length > 0) {
|
||||
if (isNaN(keywordsStr)) {
|
||||
return tabs.selectByKeyword(gotTabs[0], keywordsStr);
|
||||
}
|
||||
let index = parseInt(keywordsStr, 10) - 1;
|
||||
return tabs.selectAt(index);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const setCommand = (args) => {
|
||||
if (!args[0]) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let [name, value] = parsers.parseSetOption(args[0], properties.types);
|
||||
return {
|
||||
type: actions.SETTING_SET_PROPERTY,
|
||||
name,
|
||||
value
|
||||
};
|
||||
};
|
||||
|
||||
const exec = (line, settings) => {
|
||||
let [name, args] = parsers.parseCommandLine(line);
|
||||
|
||||
switch (name) {
|
||||
case 'o':
|
||||
case 'open':
|
||||
return openCommand(parsers.normalizeUrl(args, settings.search));
|
||||
case 't':
|
||||
case 'tabopen':
|
||||
return tabopenCommand(parsers.normalizeUrl(args, settings.search));
|
||||
case 'w':
|
||||
case 'winopen':
|
||||
return winopenCommand(parsers.normalizeUrl(args, settings.search));
|
||||
case 'b':
|
||||
case 'buffer':
|
||||
return bufferCommand(args);
|
||||
case 'set':
|
||||
return setCommand(args);
|
||||
case '':
|
||||
return Promise.resolve();
|
||||
}
|
||||
throw new Error(name + ' command is not defined');
|
||||
};
|
||||
|
||||
export { exec };
|
10
src/background/actions/find.js
Normal file
10
src/background/actions/find.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import actions from './index';
|
||||
|
||||
const setKeyword = (keyword) => {
|
||||
return {
|
||||
type: actions.FIND_SET_KEYWORD,
|
||||
keyword,
|
||||
};
|
||||
};
|
||||
|
||||
export { setKeyword };
|
8
src/background/actions/index.js
Normal file
8
src/background/actions/index.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
// Settings
|
||||
SETTING_SET_SETTINGS: 'setting.set.settings',
|
||||
SETTING_SET_PROPERTY: 'setting.set.property',
|
||||
|
||||
// Find
|
||||
FIND_SET_KEYWORD: 'find.set.keyword',
|
||||
};
|
|
@ -17,6 +17,8 @@ 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:
|
||||
|
@ -27,6 +29,8 @@ const exec = (operation, tab) => {
|
|||
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:
|
||||
|
@ -69,6 +73,10 @@ const exec = (operation, tab) => {
|
|||
return browser.tabs.sendMessage(tab.id, {
|
||||
type: messages.CONSOLE_SHOW_FIND
|
||||
});
|
||||
case operations.CANCEL:
|
||||
return browser.tabs.sendMessage(tab.id, {
|
||||
type: messages.CONSOLE_HIDE,
|
||||
});
|
||||
default:
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
21
src/background/actions/setting.js
Normal file
21
src/background/actions/setting.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import actions from '../actions';
|
||||
import * as settingsStorage from 'shared/settings/storage';
|
||||
|
||||
const load = () => {
|
||||
return settingsStorage.loadValue().then((value) => {
|
||||
return {
|
||||
type: actions.SETTING_SET_SETTINGS,
|
||||
value,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const setProperty = (name, value) => {
|
||||
return {
|
||||
type: actions.SETTING_SET_PROPERTY,
|
||||
name,
|
||||
value,
|
||||
};
|
||||
};
|
||||
|
||||
export { load, setProperty };
|
|
@ -1,5 +1,21 @@
|
|||
const openNewTab = (url, openerTabId, background = false, adjacent = false) => {
|
||||
if (adjacent) {
|
||||
return browser.tabs.query({
|
||||
active: true, currentWindow: true
|
||||
}).then((tabs) => {
|
||||
return browser.tabs.create({
|
||||
url,
|
||||
openerTabId,
|
||||
active: !background,
|
||||
index: tabs[0].index + 1
|
||||
});
|
||||
});
|
||||
}
|
||||
return browser.tabs.create({ url, active: !background });
|
||||
};
|
||||
|
||||
const openToTab = (url, tab) => {
|
||||
return browser.tabs.update(tab.id, { url: url });
|
||||
};
|
||||
|
||||
export { openToTab };
|
||||
export { openNewTab, openToTab };
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import messages from 'shared/messages';
|
||||
import * as operationActions from 'background/actions/operation';
|
||||
import * as settingsActions from 'settings/actions/setting';
|
||||
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';
|
||||
|
||||
|
@ -22,6 +24,8 @@ export default class BackgroundComponent {
|
|||
|
||||
onMessage(message, sender) {
|
||||
let settings = this.store.getState().setting;
|
||||
let find = this.store.getState().find;
|
||||
|
||||
switch (message.type) {
|
||||
case messages.BACKGROUND_OPERATION:
|
||||
return this.store.dispatch(
|
||||
|
@ -29,26 +33,31 @@ export default class BackgroundComponent {
|
|||
sender);
|
||||
case messages.OPEN_URL:
|
||||
if (message.newTab) {
|
||||
return this.store.dispatch(
|
||||
commands.tabopenCommand(message.url, message.background,
|
||||
settings.value.openAdjacentTabs), sender);
|
||||
let action = tabActions.openNewTab(
|
||||
message.url, sender.tab.id, message.background,
|
||||
settings.value.properties.adjacenttab);
|
||||
return this.store.dispatch(action, sender);
|
||||
}
|
||||
return this.store.dispatch(
|
||||
tabActions.openToTab(message.url, sender.tab), sender);
|
||||
case messages.CONSOLE_ENTER_COMMAND:
|
||||
return commands.exec(message.text, settings.value).catch((e) => {
|
||||
return browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: messages.CONSOLE_SHOW_ERROR,
|
||||
text: e.message,
|
||||
});
|
||||
});
|
||||
this.store.dispatch(
|
||||
commandActions.exec(message.text, settings.value),
|
||||
sender
|
||||
);
|
||||
return this.broadcastSettingsChanged();
|
||||
case messages.SETTINGS_QUERY:
|
||||
return Promise.resolve(this.store.getState().setting.value);
|
||||
case messages.CONSOLE_QUERY_COMPLETIONS:
|
||||
return commands.complete(message.text, settings.value);
|
||||
case messages.SETTINGS_RELOAD:
|
||||
this.store.dispatch(settingsActions.load());
|
||||
this.store.dispatch(settingActions.load());
|
||||
return this.broadcastSettingsChanged();
|
||||
case messages.FIND_GET_KEYWORD:
|
||||
return Promise.resolve(find.keyword);
|
||||
case messages.FIND_SET_KEYWORD:
|
||||
this.store.dispatch(findActions.setKeyword(message.keyword));
|
||||
return Promise.resolve({});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ const getCompletions = (keyword) => {
|
|||
.sort((x, y) => x[0].visitCount < y[0].visitCount)
|
||||
.slice(0, 10)
|
||||
.map(item => item[0])
|
||||
.sort((x, y) => x.url > y.url)
|
||||
)[0];
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as settingsActions from 'settings/actions/setting';
|
||||
import * as settingActions from 'background/actions/setting';
|
||||
import messages from 'shared/messages';
|
||||
import BackgroundComponent from 'background/components/background';
|
||||
import reducers from 'background/reducers';
|
||||
|
@ -16,4 +16,4 @@ const store = createStore(reducers, (e, sender) => {
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
const backgroundComponent = new BackgroundComponent(store);
|
||||
|
||||
store.dispatch(settingsActions.load());
|
||||
store.dispatch(settingActions.load());
|
||||
|
|
16
src/background/reducers/find.js
Normal file
16
src/background/reducers/find.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import actions from 'content/actions';
|
||||
|
||||
const defaultState = {
|
||||
keyword: null,
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action = {}) {
|
||||
switch (action.type) {
|
||||
case actions.FIND_SET_KEYWORD:
|
||||
return Object.assign({}, state, {
|
||||
keyword: action.keyword,
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,15 @@
|
|||
import settingReducer from 'settings/reducers/setting';
|
||||
import settingReducer from './setting';
|
||||
import findReducer from './find';
|
||||
|
||||
// Make setting reducer instead of re-use
|
||||
const defaultState = {
|
||||
setting: settingReducer(undefined, {}),
|
||||
find: findReducer(undefined, {}),
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action = {}) {
|
||||
return Object.assign({}, state, {
|
||||
setting: settingReducer(state.setting, action),
|
||||
find: findReducer(state.find, action),
|
||||
});
|
||||
}
|
||||
|
|
24
src/background/reducers/setting.js
Normal file
24
src/background/reducers/setting.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import actions from 'background/actions';
|
||||
|
||||
const defaultState = {
|
||||
value: {},
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action = {}) {
|
||||
switch (action.type) {
|
||||
case actions.SETTING_SET_SETTINGS:
|
||||
return {
|
||||
value: action.value,
|
||||
};
|
||||
case actions.SETTING_SET_PROPERTY:
|
||||
return {
|
||||
value: Object.assign({}, state.value, {
|
||||
properties: Object.assign({}, state.value.properties,
|
||||
{ [action.name]: action.value })
|
||||
})
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,22 @@
|
|||
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);
|
||||
};
|
||||
|
||||
|
@ -51,7 +69,7 @@ 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.includes(keyword);
|
||||
return t.url.includes(keyword) || t.title && t.title.includes(keyword);
|
||||
});
|
||||
return matched;
|
||||
});
|
||||
|
@ -93,6 +111,10 @@ const selectLastTab = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const selectPrevSelTab = () => {
|
||||
return browser.tabs.update(prevSelTab, { active: true });
|
||||
};
|
||||
|
||||
const reload = (current, cache) => {
|
||||
return browser.tabs.reload(
|
||||
current.id,
|
||||
|
@ -116,7 +138,8 @@ const duplicate = (id) => {
|
|||
};
|
||||
|
||||
export {
|
||||
closeTab, reopenTab, selectAt, selectByKeyword, getCompletions,
|
||||
selectPrevTab, selectNextTab, selectFirstTab, selectLastTab, reload,
|
||||
updateTabPinned, toggleTabPinned, duplicate
|
||||
closeTab, closeTabForce, reopenTab, selectAt, selectByKeyword,
|
||||
getCompletions, selectPrevTab, selectNextTab, selectFirstTab,
|
||||
selectLastTab, selectPrevSelTab, reload, updateTabPinned,
|
||||
toggleTabPinned, duplicate
|
||||
};
|
||||
|
|
Reference in a new issue