commit
8b9125871b
18 changed files with 137 additions and 69 deletions
|
@ -48,7 +48,7 @@ export default class BackgroundComponent {
|
||||||
tabActions.openToTab(message.url, sender.tab), sender);
|
tabActions.openToTab(message.url, sender.tab), sender);
|
||||||
case messages.CONSOLE_BLURRED:
|
case messages.CONSOLE_BLURRED:
|
||||||
return browser.tabs.sendMessage(sender.tab.id, {
|
return browser.tabs.sendMessage(sender.tab.id, {
|
||||||
type: messages.CONSOLE_HIDE,
|
type: messages.CONSOLE_HIDE_COMMAND,
|
||||||
});
|
});
|
||||||
case messages.CONSOLE_ENTERED:
|
case messages.CONSOLE_ENTERED:
|
||||||
return commands.exec(message.text, this.settings).catch((e) => {
|
return commands.exec(message.text, this.settings).catch((e) => {
|
||||||
|
|
|
@ -14,9 +14,16 @@ const showError = (text) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const hide = () => {
|
const showInfo = (text) => {
|
||||||
return {
|
return {
|
||||||
type: actions.CONSOLE_HIDE
|
type: actions.CONSOLE_SHOW_INFO,
|
||||||
|
text: text
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideCommand = () => {
|
||||||
|
return {
|
||||||
|
type: actions.CONSOLE_HIDE_COMMAND,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,5 +47,6 @@ const completionPrev = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
showCommand, showError, hide, setCompletions, completionNext, completionPrev
|
showCommand, showError, showInfo, hideCommand,
|
||||||
|
setCompletions, completionNext, completionPrev
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
export default {
|
export default {
|
||||||
// console commands
|
// console commands
|
||||||
CONSOLE_SHOW_COMMAND: 'console.show.command',
|
CONSOLE_SHOW_COMMAND: 'console.show.command',
|
||||||
CONSOLE_SET_COMPLETIONS: 'console.set.completions',
|
|
||||||
CONSOLE_SHOW_ERROR: 'console.show.error',
|
CONSOLE_SHOW_ERROR: 'console.show.error',
|
||||||
CONSOLE_HIDE: 'console.hide',
|
CONSOLE_SHOW_INFO: 'console.show.info',
|
||||||
|
CONSOLE_HIDE_COMMAND: 'console.hide.command',
|
||||||
|
CONSOLE_SET_COMPLETIONS: 'console.set.completions',
|
||||||
CONSOLE_COMPLETION_NEXT: 'console.completion.next',
|
CONSOLE_COMPLETION_NEXT: 'console.completion.next',
|
||||||
CONSOLE_COMPLETION_PREV: 'console.completion.prev',
|
CONSOLE_COMPLETION_PREV: 'console.completion.prev',
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default class ConsoleComponent {
|
||||||
input.addEventListener('keyup', this.onKeyUp.bind(this));
|
input.addEventListener('keyup', this.onKeyUp.bind(this));
|
||||||
|
|
||||||
this.hideCommand();
|
this.hideCommand();
|
||||||
this.hideError();
|
this.hideMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
onBlur() {
|
onBlur() {
|
||||||
|
@ -72,17 +72,16 @@ export default class ConsoleComponent {
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
let state = this.store.getState();
|
let state = this.store.getState();
|
||||||
if (!this.prevState.commandShown && state.commandShown) {
|
if (this.prevState.mode !== 'command' && state.mode === 'command') {
|
||||||
this.showCommand(state.commandText);
|
this.showCommand(state.commandText);
|
||||||
} else if (!state.commandShown) {
|
} else if (state.mode !== 'command') {
|
||||||
this.hideCommand();
|
this.hideCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.errorShown) {
|
if (state.mode === 'error' || state.mode === 'info') {
|
||||||
this.setErrorText(state.errorText);
|
this.showMessage(state.mode, state.messageText);
|
||||||
this.showError();
|
|
||||||
} else {
|
} else {
|
||||||
this.hideError();
|
this.hideMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.groupSelection >= 0 && state.itemSelection >= 0) {
|
if (state.groupSelection >= 0 && state.itemSelection >= 0) {
|
||||||
|
@ -128,21 +127,21 @@ export default class ConsoleComponent {
|
||||||
input.value = this.completionOrigin;
|
input.value = this.completionOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrorText(text) {
|
showMessage(mode, text) {
|
||||||
let doc = this.wrapper.ownerDocument;
|
let doc = this.wrapper.ownerDocument;
|
||||||
let error = doc.querySelector('#vimvixen-console-error');
|
let error = doc.querySelector('#vimvixen-console-message');
|
||||||
|
error.classList.remove(
|
||||||
|
'vimvixen-console-info',
|
||||||
|
'vimvixen-console-error'
|
||||||
|
);
|
||||||
|
error.classList.add('vimvixen-console-' + mode);
|
||||||
error.textContent = text;
|
error.textContent = text;
|
||||||
}
|
|
||||||
|
|
||||||
showError() {
|
|
||||||
let doc = this.wrapper.ownerDocument;
|
|
||||||
let error = doc.querySelector('#vimvixen-console-error');
|
|
||||||
error.style.display = 'block';
|
error.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
hideError() {
|
hideMessage() {
|
||||||
let doc = this.wrapper.ownerDocument;
|
let doc = this.wrapper.ownerDocument;
|
||||||
let error = doc.querySelector('#vimvixen-console-error');
|
let error = doc.querySelector('#vimvixen-console-message');
|
||||||
error.style.display = 'none';
|
error.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<script src='console.js'></script>
|
<script src='console.js'></script>
|
||||||
</head>
|
</head>
|
||||||
<body class='vimvixen-console'>
|
<body class='vimvixen-console'>
|
||||||
<p id='vimvixen-console-error'
|
<p id='vimvixen-console-message'
|
||||||
class='vimvixen-console-error'></p>
|
class='vimvixen-console-message'></p>
|
||||||
<div id='vimvixen-console-command'>
|
<div id='vimvixen-console-command'>
|
||||||
<ul id='vimvixen-console-completion' class='vimvixen-console-completion'></ul>
|
<ul id='vimvixen-console-completion' class='vimvixen-console-completion'></ul>
|
||||||
<div class='vimvixen-console-command'>
|
<div class='vimvixen-console-command'>
|
||||||
|
|
|
@ -17,18 +17,25 @@ window.addEventListener('load', () => {
|
||||||
consoleComponent = new ConsoleComponent(document.body, store);
|
consoleComponent = new ConsoleComponent(document.body, store);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onMessage = (message) => {
|
||||||
|
switch (message.type) {
|
||||||
|
case messages.CONSOLE_SHOW_COMMAND:
|
||||||
|
return store.dispatch(consoleActions.showCommand(message.command));
|
||||||
|
case messages.CONSOLE_SHOW_ERROR:
|
||||||
|
return store.dispatch(consoleActions.showError(message.text));
|
||||||
|
case messages.CONSOLE_SHOW_INFO:
|
||||||
|
return store.dispatch(consoleActions.showInfo(message.text));
|
||||||
|
case messages.CONSOLE_HIDE_COMMAND:
|
||||||
|
return store.dispatch(consoleActions.hideCommand());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
store.subscribe(() => {
|
store.subscribe(() => {
|
||||||
completionComponent.update();
|
completionComponent.update();
|
||||||
consoleComponent.update();
|
consoleComponent.update();
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener((action) => {
|
browser.runtime.onMessage.addListener(onMessage);
|
||||||
switch (action.type) {
|
window.addEventListener('message', (message) => {
|
||||||
case messages.CONSOLE_SHOW_COMMAND:
|
onMessage(JSON.parse(message.data));
|
||||||
return store.dispatch(consoleActions.showCommand(action.command));
|
}, false);
|
||||||
case messages.CONSOLE_SHOW_ERROR:
|
|
||||||
return store.dispatch(consoleActions.showError(action.text));
|
|
||||||
case messages.CONSOLE_HIDE:
|
|
||||||
return store.dispatch(consoleActions.hide(action.command));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import actions from 'console/actions';
|
import actions from 'console/actions';
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
errorShown: false,
|
mode: '',
|
||||||
errorText: '',
|
messageText: '',
|
||||||
commandShown: false,
|
|
||||||
commandText: '',
|
commandText: '',
|
||||||
completions: [],
|
completions: [],
|
||||||
groupSelection: -1,
|
groupSelection: -1,
|
||||||
|
@ -48,25 +47,24 @@ export default function reducer(state = defaultState, action = {}) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case actions.CONSOLE_SHOW_COMMAND:
|
case actions.CONSOLE_SHOW_COMMAND:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
commandShown: true,
|
mode: 'command',
|
||||||
commandText: action.text,
|
commandText: action.text,
|
||||||
errorShown: false,
|
errorShown: false,
|
||||||
completions: []
|
completions: []
|
||||||
});
|
});
|
||||||
case actions.CONSOLE_SHOW_ERROR:
|
case actions.CONSOLE_SHOW_ERROR:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
errorText: action.text,
|
mode: 'error',
|
||||||
errorShown: true,
|
messageText: action.text,
|
||||||
commandShown: false,
|
|
||||||
});
|
});
|
||||||
case actions.CONSOLE_HIDE:
|
case actions.CONSOLE_SHOW_INFO:
|
||||||
if (state.errorShown) {
|
|
||||||
// keep error message if shown
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
errorShown: false,
|
mode: 'info',
|
||||||
commandShown: false
|
messageText: action.text,
|
||||||
|
});
|
||||||
|
case actions.CONSOLE_HIDE_COMMAND:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
mode: state.mode === 'command' ? '' : state.mode,
|
||||||
});
|
});
|
||||||
case actions.CONSOLE_SET_COMPLETIONS:
|
case actions.CONSOLE_SET_COMPLETIONS:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
|
|
|
@ -64,12 +64,20 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-message {
|
||||||
|
@include consoole-font;
|
||||||
|
}
|
||||||
|
|
||||||
&-error {
|
&-error {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
@include consoole-font;
|
&-info {
|
||||||
|
background-color: white;
|
||||||
|
font-weight: normal;
|
||||||
|
color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-command {
|
&-command {
|
||||||
|
|
|
@ -2,7 +2,9 @@ import operations from 'shared/operations';
|
||||||
import messages from 'shared/messages';
|
import messages from 'shared/messages';
|
||||||
import * as scrolls from 'content/scrolls';
|
import * as scrolls from 'content/scrolls';
|
||||||
import * as navigates from 'content/navigates';
|
import * as navigates from 'content/navigates';
|
||||||
|
import * as urls from 'content/urls';
|
||||||
import * as followActions from 'content/actions/follow';
|
import * as followActions from 'content/actions/follow';
|
||||||
|
import * as consoleFrames from 'content/console-frames';
|
||||||
|
|
||||||
const exec = (operation) => {
|
const exec = (operation) => {
|
||||||
switch (operation.type) {
|
switch (operation.type) {
|
||||||
|
@ -32,6 +34,12 @@ const exec = (operation) => {
|
||||||
return navigates.parent(window);
|
return navigates.parent(window);
|
||||||
case operations.NAVIGATE_ROOT:
|
case operations.NAVIGATE_ROOT:
|
||||||
return navigates.root(window);
|
return navigates.root(window);
|
||||||
|
case operations.URLS_YANK:
|
||||||
|
urls.yank(window);
|
||||||
|
return consoleFrames.postMessage(window.document, {
|
||||||
|
type: messages.CONSOLE_SHOW_INFO,
|
||||||
|
text: 'Current url yanked',
|
||||||
|
});
|
||||||
default:
|
default:
|
||||||
browser.runtime.sendMessage({
|
browser.runtime.sendMessage({
|
||||||
type: messages.BACKGROUND_OPERATION,
|
type: messages.BACKGROUND_OPERATION,
|
||||||
|
|
|
@ -15,4 +15,9 @@ const blur = (doc) => {
|
||||||
iframe.blur();
|
iframe.blur();
|
||||||
};
|
};
|
||||||
|
|
||||||
export { initialize, blur };
|
const postMessage = (doc, message) => {
|
||||||
|
let iframe = doc.getElementById('vimvixen-console-frame');
|
||||||
|
iframe.contentWindow.postMessage(JSON.stringify(message), '*');
|
||||||
|
};
|
||||||
|
|
||||||
|
export { initialize, blur, postMessage };
|
||||||
|
|
|
@ -40,7 +40,7 @@ const reloadSettings = () => {
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener((action) => {
|
browser.runtime.onMessage.addListener((action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case messages.CONSOLE_HIDE:
|
case messages.CONSOLE_HIDE_COMMAND:
|
||||||
window.focus();
|
window.focus();
|
||||||
consoleFrames.blur(window.document);
|
consoleFrames.blur(window.document);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|
15
src/content/urls.js
Normal file
15
src/content/urls.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
const yank = (win) => {
|
||||||
|
let input = win.document.createElement('input');
|
||||||
|
win.document.body.append(input);
|
||||||
|
|
||||||
|
input.style.position = 'fixed';
|
||||||
|
input.style.top = '-100px';
|
||||||
|
input.value = win.location.href;
|
||||||
|
input.select();
|
||||||
|
|
||||||
|
win.document.execCommand('copy');
|
||||||
|
|
||||||
|
input.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
export { yank };
|
|
@ -37,7 +37,8 @@ export default {
|
||||||
"[[": { "type": "navigate.link.prev" },
|
"[[": { "type": "navigate.link.prev" },
|
||||||
"]]": { "type": "navigate.link.next" },
|
"]]": { "type": "navigate.link.next" },
|
||||||
"gu": { "type": "navigate.parent" },
|
"gu": { "type": "navigate.parent" },
|
||||||
"gU": { "type": "navigate.root" }
|
"gU": { "type": "navigate.root" },
|
||||||
|
"y": { "type": "urls.yank" }
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"default": "google",
|
"default": "google",
|
||||||
|
|
|
@ -8,7 +8,8 @@ export default {
|
||||||
CONSOLE_QUERY_COMPLETIONS: 'console.query.completions',
|
CONSOLE_QUERY_COMPLETIONS: 'console.query.completions',
|
||||||
CONSOLE_SHOW_COMMAND: 'console.show.command',
|
CONSOLE_SHOW_COMMAND: 'console.show.command',
|
||||||
CONSOLE_SHOW_ERROR: 'console.show.error',
|
CONSOLE_SHOW_ERROR: 'console.show.error',
|
||||||
CONSOLE_HIDE: 'console.hide',
|
CONSOLE_SHOW_INFO: 'console.show.info',
|
||||||
|
CONSOLE_HIDE_COMMAND: 'console.hide.command',
|
||||||
|
|
||||||
OPEN_URL: 'open.url',
|
OPEN_URL: 'open.url',
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,7 @@ export default {
|
||||||
ZOOM_IN: 'zoom.in',
|
ZOOM_IN: 'zoom.in',
|
||||||
ZOOM_OUT: 'zoom.out',
|
ZOOM_OUT: 'zoom.out',
|
||||||
ZOOM_NEUTRAL: 'zoom.neutral',
|
ZOOM_NEUTRAL: 'zoom.neutral',
|
||||||
|
|
||||||
|
// Url yank
|
||||||
|
URLS_YANK: 'urls.yank',
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,14 @@ describe("console actions", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("showInfo", () => {
|
||||||
|
it('create CONSOLE_SHOW_INFO action', () => {
|
||||||
|
let action = consoleActions.showInfo('an info');
|
||||||
|
expect(action.type).to.equal(actions.CONSOLE_SHOW_INFO);
|
||||||
|
expect(action.text).to.equal('an info');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("showError", () => {
|
describe("showError", () => {
|
||||||
it('create CONSOLE_SHOW_ERROR action', () => {
|
it('create CONSOLE_SHOW_ERROR action', () => {
|
||||||
let action = consoleActions.showError('an error');
|
let action = consoleActions.showError('an error');
|
||||||
|
@ -20,9 +28,9 @@ describe("console actions", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("hide", () => {
|
describe("hide", () => {
|
||||||
it('create CONSOLE_HIDE action', () => {
|
it('create CONSOLE_HIDE_COMMAND action', () => {
|
||||||
let action = consoleActions.hide();
|
let action = consoleActions.hideCommand();
|
||||||
expect(action.type).to.equal(actions.CONSOLE_HIDE);
|
expect(action.type).to.equal(actions.CONSOLE_HIDE_COMMAND);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@ import reducer from 'console/reducers';
|
||||||
describe("console reducer", () => {
|
describe("console reducer", () => {
|
||||||
it('return the initial state', () => {
|
it('return the initial state', () => {
|
||||||
let state = reducer(undefined, {});
|
let state = reducer(undefined, {});
|
||||||
expect(state).to.have.property('errorShown', false);
|
expect(state).to.have.property('mode', '');
|
||||||
expect(state).to.have.property('errorText', '');
|
expect(state).to.have.property('messageText', '');
|
||||||
expect(state).to.have.property('commandShown', false);
|
|
||||||
expect(state).to.have.property('commandText', '');
|
expect(state).to.have.property('commandText', '');
|
||||||
expect(state).to.have.deep.property('completions', []);
|
expect(state).to.have.deep.property('completions', []);
|
||||||
expect(state).to.have.property('groupSelection', -1);
|
expect(state).to.have.property('groupSelection', -1);
|
||||||
|
@ -17,24 +16,31 @@ describe("console reducer", () => {
|
||||||
it('return next state for CONSOLE_SHOW_COMMAND', () => {
|
it('return next state for CONSOLE_SHOW_COMMAND', () => {
|
||||||
let action = { type: actions.CONSOLE_SHOW_COMMAND, text: 'open ' };
|
let action = { type: actions.CONSOLE_SHOW_COMMAND, text: 'open ' };
|
||||||
let state = reducer({}, action);
|
let state = reducer({}, action);
|
||||||
expect(state).to.have.property('commandShown', true);
|
expect(state).to.have.property('mode', 'command');
|
||||||
expect(state).to.have.property('commandText', 'open ');
|
expect(state).to.have.property('commandText', 'open ');
|
||||||
expect(state).to.have.property('errorShown', false);
|
});
|
||||||
|
|
||||||
|
it('return next state for CONSOLE_SHOW_INFO', () => {
|
||||||
|
let action = { type: actions.CONSOLE_SHOW_INFO, text: 'an info' };
|
||||||
|
let state = reducer({}, action);
|
||||||
|
expect(state).to.have.property('mode', 'info');
|
||||||
|
expect(state).to.have.property('messageText', 'an info');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return next state for CONSOLE_SHOW_ERROR', () => {
|
it('return next state for CONSOLE_SHOW_ERROR', () => {
|
||||||
let action = { type: actions.CONSOLE_SHOW_ERROR, text: 'an error' };
|
let action = { type: actions.CONSOLE_SHOW_ERROR, text: 'an error' };
|
||||||
let state = reducer({}, action);
|
let state = reducer({}, action);
|
||||||
expect(state).to.have.property('errorShown', true);
|
expect(state).to.have.property('mode', 'error');
|
||||||
expect(state).to.have.property('errorText', 'an error');
|
expect(state).to.have.property('messageText', 'an error');
|
||||||
expect(state).to.have.property('commandShown', false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return next state for CONSOLE_HIDE', () => {
|
it('return next state for CONSOLE_HIDE_COMMAND', () => {
|
||||||
let action = { type: actions.CONSOLE_HIDE };
|
let action = { type: actions.CONSOLE_HIDE_COMMAND };
|
||||||
let state = reducer({}, action);
|
let state = reducer({ mode: 'command' }, action);
|
||||||
expect(state).to.have.property('errorShown', false);
|
expect(state).to.have.property('mode', '');
|
||||||
expect(state).to.have.property('commandShown', false);
|
|
||||||
|
state = reducer({ mode: 'error' }, action);
|
||||||
|
expect(state).to.have.property('mode', 'error');
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('return next state for CONSOLE_SET_COMPLETIONS', () => {
|
it ('return next state for CONSOLE_SET_COMPLETIONS', () => {
|
||||||
|
|
Reference in a new issue