Remove unused components
This commit is contained in:
parent
e0c4182f14
commit
4be04628e1
27 changed files with 1 additions and 1083 deletions
|
@ -1,32 +0,0 @@
|
||||||
import * as actions from './index';
|
|
||||||
|
|
||||||
const enable = (
|
|
||||||
newTab: boolean, background: boolean,
|
|
||||||
): actions.FollowAction => {
|
|
||||||
return {
|
|
||||||
type: actions.FOLLOW_CONTROLLER_ENABLE,
|
|
||||||
newTab,
|
|
||||||
background,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const disable = (): actions.FollowAction => {
|
|
||||||
return {
|
|
||||||
type: actions.FOLLOW_CONTROLLER_DISABLE,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const keyPress = (key: string): actions.FollowAction => {
|
|
||||||
return {
|
|
||||||
type: actions.FOLLOW_CONTROLLER_KEY_PRESS,
|
|
||||||
key: key
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const backspace = (): actions.FollowAction => {
|
|
||||||
return {
|
|
||||||
type: actions.FOLLOW_CONTROLLER_BACKSPACE,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export { enable, disable, keyPress, backspace };
|
|
|
@ -1,81 +0,0 @@
|
||||||
import Redux from 'redux';
|
|
||||||
import Key from '../domains/Key';
|
|
||||||
|
|
||||||
// User input
|
|
||||||
export const INPUT_KEY_PRESS = 'input.key.press';
|
|
||||||
export const INPUT_CLEAR_KEYS = 'input.clear.keys';
|
|
||||||
|
|
||||||
// Completion
|
|
||||||
export const COMPLETION_SET_ITEMS = 'completion.set.items';
|
|
||||||
export const COMPLETION_SELECT_NEXT = 'completions.select.next';
|
|
||||||
export const COMPLETION_SELECT_PREV = 'completions.select.prev';
|
|
||||||
|
|
||||||
// Follow
|
|
||||||
export const FOLLOW_CONTROLLER_ENABLE = 'follow.controller.enable';
|
|
||||||
export const FOLLOW_CONTROLLER_DISABLE = 'follow.controller.disable';
|
|
||||||
export const FOLLOW_CONTROLLER_KEY_PRESS = 'follow.controller.key.press';
|
|
||||||
export const FOLLOW_CONTROLLER_BACKSPACE = 'follow.controller.backspace';
|
|
||||||
|
|
||||||
// Mark
|
|
||||||
export const MARK_START_SET = 'mark.start.set';
|
|
||||||
export const MARK_START_JUMP = 'mark.start.jump';
|
|
||||||
export const MARK_CANCEL = 'mark.cancel';
|
|
||||||
|
|
||||||
export const NOOP = 'noop';
|
|
||||||
|
|
||||||
export interface InputKeyPressAction extends Redux.Action {
|
|
||||||
type: typeof INPUT_KEY_PRESS;
|
|
||||||
key: Key;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InputClearKeysAction extends Redux.Action {
|
|
||||||
type: typeof INPUT_CLEAR_KEYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FollowControllerEnableAction extends Redux.Action {
|
|
||||||
type: typeof FOLLOW_CONTROLLER_ENABLE;
|
|
||||||
newTab: boolean;
|
|
||||||
background: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FollowControllerDisableAction extends Redux.Action {
|
|
||||||
type: typeof FOLLOW_CONTROLLER_DISABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FollowControllerKeyPressAction extends Redux.Action {
|
|
||||||
type: typeof FOLLOW_CONTROLLER_KEY_PRESS;
|
|
||||||
key: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FollowControllerBackspaceAction extends Redux.Action {
|
|
||||||
type: typeof FOLLOW_CONTROLLER_BACKSPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MarkStartSetAction extends Redux.Action {
|
|
||||||
type: typeof MARK_START_SET;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MarkStartJumpAction extends Redux.Action {
|
|
||||||
type: typeof MARK_START_JUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MarkCancelAction extends Redux.Action {
|
|
||||||
type: typeof MARK_CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NoopAction extends Redux.Action {
|
|
||||||
type: typeof NOOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type InputAction = InputKeyPressAction | InputClearKeysAction;
|
|
||||||
export type FollowAction =
|
|
||||||
FollowControllerEnableAction | FollowControllerDisableAction |
|
|
||||||
FollowControllerKeyPressAction | FollowControllerBackspaceAction;
|
|
||||||
export type MarkAction =
|
|
||||||
MarkStartSetAction | MarkStartJumpAction | MarkCancelAction | NoopAction;
|
|
||||||
|
|
||||||
export type Action =
|
|
||||||
InputAction |
|
|
||||||
FollowAction |
|
|
||||||
MarkAction |
|
|
||||||
NoopAction;
|
|
|
@ -1,17 +0,0 @@
|
||||||
import * as actions from './index';
|
|
||||||
import Key from '../domains/Key';
|
|
||||||
|
|
||||||
const keyPress = (key: Key): actions.InputAction => {
|
|
||||||
return {
|
|
||||||
type: actions.INPUT_KEY_PRESS,
|
|
||||||
key,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearKeys = (): actions.InputAction => {
|
|
||||||
return {
|
|
||||||
type: actions.INPUT_CLEAR_KEYS
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export { keyPress, clearKeys };
|
|
|
@ -1,17 +0,0 @@
|
||||||
import * as actions from './index';
|
|
||||||
|
|
||||||
const startSet = (): actions.MarkAction => {
|
|
||||||
return { type: actions.MARK_START_SET };
|
|
||||||
};
|
|
||||||
|
|
||||||
const startJump = (): actions.MarkAction => {
|
|
||||||
return { type: actions.MARK_START_JUMP };
|
|
||||||
};
|
|
||||||
|
|
||||||
const cancel = (): actions.MarkAction => {
|
|
||||||
return { type: actions.MARK_CANCEL };
|
|
||||||
};
|
|
||||||
|
|
||||||
export {
|
|
||||||
startSet, startJump, cancel,
|
|
||||||
};
|
|
|
@ -1,112 +0,0 @@
|
||||||
import * as operations from '../../shared/operations';
|
|
||||||
import * as actions from './index';
|
|
||||||
import * as messages from '../../shared/messages';
|
|
||||||
import * as navigates from '../navigates';
|
|
||||||
import * as focuses from '../focuses';
|
|
||||||
import * as markActions from './mark';
|
|
||||||
|
|
||||||
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
|
|
||||||
import ClipboardUseCase from '../usecases/ClipboardUseCase';
|
|
||||||
import { SettingRepositoryImpl } from '../repositories/SettingRepository';
|
|
||||||
import { ScrollPresenterImpl } from '../presenters/ScrollPresenter';
|
|
||||||
import { FollowMasterClientImpl } from '../client/FollowMasterClient';
|
|
||||||
|
|
||||||
let addonEnabledUseCase = new AddonEnabledUseCase();
|
|
||||||
let clipbaordUseCase = new ClipboardUseCase();
|
|
||||||
let settingRepository = new SettingRepositoryImpl();
|
|
||||||
let scrollPresenter = new ScrollPresenterImpl();
|
|
||||||
let followMasterClient = new FollowMasterClientImpl(window.top);
|
|
||||||
|
|
||||||
// eslint-disable-next-line complexity, max-lines-per-function
|
|
||||||
const exec = async(
|
|
||||||
operation: operations.Operation,
|
|
||||||
): Promise<actions.Action> => {
|
|
||||||
let settings = settingRepository.get();
|
|
||||||
let smoothscroll = settings.properties.smoothscroll;
|
|
||||||
switch (operation.type) {
|
|
||||||
case operations.ADDON_ENABLE:
|
|
||||||
await addonEnabledUseCase.enable();
|
|
||||||
return { type: actions.NOOP };
|
|
||||||
case operations.ADDON_DISABLE:
|
|
||||||
await addonEnabledUseCase.disable();
|
|
||||||
return { type: actions.NOOP };
|
|
||||||
case operations.ADDON_TOGGLE_ENABLED:
|
|
||||||
await addonEnabledUseCase.toggle();
|
|
||||||
return { type: actions.NOOP };
|
|
||||||
case operations.FIND_NEXT:
|
|
||||||
window.top.postMessage(JSON.stringify({
|
|
||||||
type: messages.FIND_NEXT,
|
|
||||||
}), '*');
|
|
||||||
break;
|
|
||||||
case operations.FIND_PREV:
|
|
||||||
window.top.postMessage(JSON.stringify({
|
|
||||||
type: messages.FIND_PREV,
|
|
||||||
}), '*');
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_VERTICALLY:
|
|
||||||
scrollPresenter.scrollVertically(operation.count, smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_HORIZONALLY:
|
|
||||||
scrollPresenter.scrollHorizonally(operation.count, smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_PAGES:
|
|
||||||
scrollPresenter.scrollPages(operation.count, smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_TOP:
|
|
||||||
scrollPresenter.scrollToTop(smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_BOTTOM:
|
|
||||||
scrollPresenter.scrollToBottom(smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_HOME:
|
|
||||||
scrollPresenter.scrollToHome(smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.SCROLL_END:
|
|
||||||
scrollPresenter.scrollToEnd(smoothscroll);
|
|
||||||
break;
|
|
||||||
case operations.FOLLOW_START:
|
|
||||||
followMasterClient.startFollow(operation.newTab, operation.background);
|
|
||||||
break;
|
|
||||||
case operations.MARK_SET_PREFIX:
|
|
||||||
return markActions.startSet();
|
|
||||||
case operations.MARK_JUMP_PREFIX:
|
|
||||||
return markActions.startJump();
|
|
||||||
case operations.NAVIGATE_HISTORY_PREV:
|
|
||||||
navigates.historyPrev(window);
|
|
||||||
break;
|
|
||||||
case operations.NAVIGATE_HISTORY_NEXT:
|
|
||||||
navigates.historyNext(window);
|
|
||||||
break;
|
|
||||||
case operations.NAVIGATE_LINK_PREV:
|
|
||||||
navigates.linkPrev(window);
|
|
||||||
break;
|
|
||||||
case operations.NAVIGATE_LINK_NEXT:
|
|
||||||
navigates.linkNext(window);
|
|
||||||
break;
|
|
||||||
case operations.NAVIGATE_PARENT:
|
|
||||||
navigates.parent(window);
|
|
||||||
break;
|
|
||||||
case operations.NAVIGATE_ROOT:
|
|
||||||
navigates.root(window);
|
|
||||||
break;
|
|
||||||
case operations.FOCUS_INPUT:
|
|
||||||
focuses.focusInput();
|
|
||||||
break;
|
|
||||||
case operations.URLS_YANK:
|
|
||||||
await clipbaordUseCase.yankCurrentURL();
|
|
||||||
break;
|
|
||||||
case operations.URLS_PASTE:
|
|
||||||
await clipbaordUseCase.openOrSearch(
|
|
||||||
operation.newTab ? operation.newTab : false,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
browser.runtime.sendMessage({
|
|
||||||
type: messages.BACKGROUND_OPERATION,
|
|
||||||
operation,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return { type: actions.NOOP };
|
|
||||||
};
|
|
||||||
|
|
||||||
export { exec };
|
|
|
@ -1,104 +0,0 @@
|
||||||
import MessageListener from '../../MessageListener';
|
|
||||||
import { LinkHint, InputHint } from '../../presenters/Hint';
|
|
||||||
import * as messages from '../../../shared/messages';
|
|
||||||
import Key from '../../domains/Key';
|
|
||||||
import TabsClient, { TabsClientImpl } from '../../client/TabsClient';
|
|
||||||
import FollowMasterClient, { FollowMasterClientImpl }
|
|
||||||
from '../../client/FollowMasterClient';
|
|
||||||
import FollowPresenter, { FollowPresenterImpl }
|
|
||||||
from '../../presenters/FollowPresenter';
|
|
||||||
|
|
||||||
let tabsClient: TabsClient = new TabsClientImpl();
|
|
||||||
let followMasterClient: FollowMasterClient =
|
|
||||||
new FollowMasterClientImpl(window.top);
|
|
||||||
let followPresenter: FollowPresenter =
|
|
||||||
new FollowPresenterImpl();
|
|
||||||
|
|
||||||
interface Size {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Point {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Follow {
|
|
||||||
private enabled: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.enabled = false;
|
|
||||||
|
|
||||||
new MessageListener().onWebMessage(this.onMessage.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
key(key: Key): boolean {
|
|
||||||
if (!this.enabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
followMasterClient.sendKey(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
countHints(viewSize: Size, framePosition: Point) {
|
|
||||||
let count = followPresenter.getTargetCount(viewSize, framePosition);
|
|
||||||
followMasterClient.responseHintCount(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
createHints(viewSize: Size, framePosition: Point, tags: string[]) {
|
|
||||||
this.enabled = true;
|
|
||||||
followPresenter.createHints(viewSize, framePosition, tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
showHints(prefix: string) {
|
|
||||||
followPresenter.filterHints(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHints() {
|
|
||||||
followPresenter.clearHints();
|
|
||||||
this.enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async activateHints(
|
|
||||||
tag: string, newTab: boolean, background: boolean,
|
|
||||||
): Promise<void> {
|
|
||||||
let hint = followPresenter.getHint(tag);
|
|
||||||
if (!hint) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hint instanceof LinkHint) {
|
|
||||||
let url = hint.getLink();
|
|
||||||
// ignore taget='_blank'
|
|
||||||
if (!newTab && hint.getLinkTarget() !== '_blank') {
|
|
||||||
hint.click();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line no-script-url
|
|
||||||
if (!url || url === '#' || url.toLowerCase().startsWith('javascript:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await tabsClient.openUrl(url, newTab, background);
|
|
||||||
} else if (hint instanceof InputHint) {
|
|
||||||
hint.activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessage(message: messages.Message, _sender: Window) {
|
|
||||||
switch (message.type) {
|
|
||||||
case messages.FOLLOW_REQUEST_COUNT_TARGETS:
|
|
||||||
return this.countHints(message.viewSize, message.framePosition);
|
|
||||||
case messages.FOLLOW_CREATE_HINTS:
|
|
||||||
return this.createHints(
|
|
||||||
message.viewSize, message.framePosition, message.tags);
|
|
||||||
case messages.FOLLOW_SHOW_HINTS:
|
|
||||||
return this.showHints(message.prefix);
|
|
||||||
case messages.FOLLOW_ACTIVATE:
|
|
||||||
return this.activateHints(
|
|
||||||
message.tag, message.newTab, message.background);
|
|
||||||
case messages.FOLLOW_REMOVE_HINTS:
|
|
||||||
return this.removeHints();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
import InputDriver from './../../InputDriver';
|
|
||||||
import FollowComponent from './follow';
|
|
||||||
import MarkComponent from './mark';
|
|
||||||
// import KeymapperComponent from './keymapper';
|
|
||||||
import * as messages from '../../../shared/messages';
|
|
||||||
import MessageListener from '../../MessageListener';
|
|
||||||
import * as blacklists from '../../../shared/blacklists';
|
|
||||||
import Key from '../../domains/Key';
|
|
||||||
|
|
||||||
import AddonEnabledUseCase from '../../usecases/AddonEnabledUseCase';
|
|
||||||
import SettingUseCase from '../../usecases/SettingUseCase';
|
|
||||||
|
|
||||||
let addonEnabledUseCase = new AddonEnabledUseCase();
|
|
||||||
let settingUseCase = new SettingUseCase();
|
|
||||||
|
|
||||||
export default class Common {
|
|
||||||
constructor(win: Window, store: any) {
|
|
||||||
const input = new InputDriver(win.document.body);
|
|
||||||
const follow = new FollowComponent();
|
|
||||||
const mark = new MarkComponent(store);
|
|
||||||
// const keymapper = new KeymapperComponent(store);
|
|
||||||
|
|
||||||
input.onKey((key: Key) => follow.key(key));
|
|
||||||
input.onKey((key: Key) => mark.key(key));
|
|
||||||
// input.onKey((key: Key) => keymapper.key(key));
|
|
||||||
|
|
||||||
this.reloadSettings();
|
|
||||||
|
|
||||||
new MessageListener().onBackgroundMessage(this.onMessage.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessage(message: messages.Message) {
|
|
||||||
switch (message.type) {
|
|
||||||
case messages.SETTINGS_CHANGED:
|
|
||||||
return this.reloadSettings();
|
|
||||||
case messages.ADDON_TOGGLE_ENABLED:
|
|
||||||
return addonEnabledUseCase.toggle();
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
async reloadSettings() {
|
|
||||||
try {
|
|
||||||
let current = await settingUseCase.reload();
|
|
||||||
let disabled = blacklists.includes(
|
|
||||||
current.blacklist, window.location.href,
|
|
||||||
);
|
|
||||||
if (disabled) {
|
|
||||||
addonEnabledUseCase.disable();
|
|
||||||
} else {
|
|
||||||
addonEnabledUseCase.enable();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// Sometime sendMessage fails when background script is not ready.
|
|
||||||
console.warn(e);
|
|
||||||
setTimeout(() => this.reloadSettings(), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
import * as markActions from '../../actions/mark';
|
|
||||||
import * as consoleFrames from '../..//console-frames';
|
|
||||||
import Key from '../../domains/Key';
|
|
||||||
|
|
||||||
import MarkUseCase from '../../usecases/MarkUseCase';
|
|
||||||
|
|
||||||
let markUseCase = new MarkUseCase();
|
|
||||||
|
|
||||||
const cancelKey = (key: Key): boolean => {
|
|
||||||
return key.key === 'Esc' || key.key === '[' && Boolean(key.ctrlKey);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class MarkComponent {
|
|
||||||
private store: any;
|
|
||||||
|
|
||||||
constructor(store: any) {
|
|
||||||
this.store = store;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line max-statements
|
|
||||||
key(key: Key) {
|
|
||||||
let { mark: markState } = this.store.getState();
|
|
||||||
|
|
||||||
if (!markState.setMode && !markState.jumpMode) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancelKey(key)) {
|
|
||||||
this.store.dispatch(markActions.cancel());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.ctrlKey || key.metaKey || key.altKey) {
|
|
||||||
consoleFrames.postError('Unknown mark');
|
|
||||||
} else if (markState.setMode) {
|
|
||||||
markUseCase.set(key.key);
|
|
||||||
} else if (markState.jumpMode) {
|
|
||||||
markUseCase.jump(key.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.store.dispatch(markActions.cancel());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import CommonComponent from './common';
|
|
||||||
|
|
||||||
export default CommonComponent;
|
|
|
@ -1,181 +0,0 @@
|
||||||
import * as followControllerActions from '../../actions/follow-controller';
|
|
||||||
import * as messages from '../../../shared/messages';
|
|
||||||
import MessageListener from '../../MessageListener';
|
|
||||||
import HintKeyProducer from '../../hint-key-producer';
|
|
||||||
|
|
||||||
import { SettingRepositoryImpl } from '../../repositories/SettingRepository';
|
|
||||||
import FollowSlaveClient, { FollowSlaveClientImpl }
|
|
||||||
from '../../client/FollowSlaveClient';
|
|
||||||
|
|
||||||
let settingRepository = new SettingRepositoryImpl();
|
|
||||||
|
|
||||||
export default class FollowController {
|
|
||||||
private win: Window;
|
|
||||||
|
|
||||||
private store: any;
|
|
||||||
|
|
||||||
private state: {
|
|
||||||
enabled?: boolean;
|
|
||||||
newTab?: boolean;
|
|
||||||
background?: boolean;
|
|
||||||
keys?: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
private keys: string[];
|
|
||||||
|
|
||||||
private producer: HintKeyProducer | null;
|
|
||||||
|
|
||||||
constructor(win: Window, store: any) {
|
|
||||||
this.win = win;
|
|
||||||
this.store = store;
|
|
||||||
this.state = {};
|
|
||||||
this.keys = [];
|
|
||||||
this.producer = null;
|
|
||||||
|
|
||||||
new MessageListener().onWebMessage(this.onMessage.bind(this));
|
|
||||||
|
|
||||||
store.subscribe(() => {
|
|
||||||
this.update();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessage(message: messages.Message, sender: Window) {
|
|
||||||
switch (message.type) {
|
|
||||||
case messages.FOLLOW_START:
|
|
||||||
return this.store.dispatch(
|
|
||||||
followControllerActions.enable(message.newTab, message.background));
|
|
||||||
case messages.FOLLOW_RESPONSE_COUNT_TARGETS:
|
|
||||||
return this.create(message.count, sender);
|
|
||||||
case messages.FOLLOW_KEY_PRESS:
|
|
||||||
return this.keyPress(message.key, message.ctrlKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update(): void {
|
|
||||||
let prevState = this.state;
|
|
||||||
this.state = this.store.getState().followController;
|
|
||||||
|
|
||||||
if (!prevState.enabled && this.state.enabled) {
|
|
||||||
this.count();
|
|
||||||
} else if (prevState.enabled && !this.state.enabled) {
|
|
||||||
this.remove();
|
|
||||||
} else if (prevState.keys !== this.state.keys) {
|
|
||||||
this.updateHints();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateHints(): void {
|
|
||||||
let shown = this.keys.filter((key) => {
|
|
||||||
return key.startsWith(this.state.keys as string);
|
|
||||||
});
|
|
||||||
if (shown.length === 1) {
|
|
||||||
this.activate();
|
|
||||||
this.store.dispatch(followControllerActions.disable());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.broadcastMessage((c: FollowSlaveClient) => {
|
|
||||||
c.filterHints(this.state.keys!!);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
activate(): void {
|
|
||||||
this.broadcastMessage((c: FollowSlaveClient) => {
|
|
||||||
c.activateIfExists(
|
|
||||||
this.state.keys!!,
|
|
||||||
this.state.newTab!!,
|
|
||||||
this.state.background!!);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
keyPress(key: string, ctrlKey: boolean): boolean {
|
|
||||||
if (key === '[' && ctrlKey) {
|
|
||||||
this.store.dispatch(followControllerActions.disable());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
switch (key) {
|
|
||||||
case 'Enter':
|
|
||||||
this.activate();
|
|
||||||
this.store.dispatch(followControllerActions.disable());
|
|
||||||
break;
|
|
||||||
case 'Esc':
|
|
||||||
this.store.dispatch(followControllerActions.disable());
|
|
||||||
break;
|
|
||||||
case 'Backspace':
|
|
||||||
case 'Delete':
|
|
||||||
this.store.dispatch(followControllerActions.backspace());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (this.hintchars().includes(key)) {
|
|
||||||
this.store.dispatch(followControllerActions.keyPress(key));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
count() {
|
|
||||||
this.producer = new HintKeyProducer(this.hintchars());
|
|
||||||
let doc = this.win.document;
|
|
||||||
let viewWidth = this.win.innerWidth || doc.documentElement.clientWidth;
|
|
||||||
let viewHeight = this.win.innerHeight || doc.documentElement.clientHeight;
|
|
||||||
let frameElements = this.win.document.querySelectorAll('iframe');
|
|
||||||
|
|
||||||
new FollowSlaveClientImpl(this.win).requestHintCount(
|
|
||||||
{ width: viewWidth, height: viewHeight },
|
|
||||||
{ x: 0, y: 0 });
|
|
||||||
|
|
||||||
for (let ele of Array.from(frameElements)) {
|
|
||||||
let { left: frameX, top: frameY } = ele.getBoundingClientRect();
|
|
||||||
new FollowSlaveClientImpl(ele.contentWindow!!).requestHintCount(
|
|
||||||
{ width: viewWidth, height: viewHeight },
|
|
||||||
{ x: frameX, y: frameY },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
create(count: number, sender: Window) {
|
|
||||||
let produced = [];
|
|
||||||
for (let i = 0; i < count; ++i) {
|
|
||||||
produced.push((this.producer as HintKeyProducer).produce());
|
|
||||||
}
|
|
||||||
this.keys = this.keys.concat(produced);
|
|
||||||
|
|
||||||
let doc = this.win.document;
|
|
||||||
let viewWidth = this.win.innerWidth || doc.documentElement.clientWidth;
|
|
||||||
let viewHeight = this.win.innerHeight || doc.documentElement.clientHeight;
|
|
||||||
let pos = { x: 0, y: 0 };
|
|
||||||
if (sender !== window) {
|
|
||||||
let frameElements = this.win.document.querySelectorAll('iframe');
|
|
||||||
let ele = Array.from(frameElements).find(e => e.contentWindow === sender);
|
|
||||||
if (!ele) {
|
|
||||||
// elements of the sender is gone
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let { left: frameX, top: frameY } = ele.getBoundingClientRect();
|
|
||||||
pos = { x: frameX, y: frameY };
|
|
||||||
}
|
|
||||||
new FollowSlaveClientImpl(sender).createHints(
|
|
||||||
{ width: viewWidth, height: viewHeight },
|
|
||||||
pos,
|
|
||||||
produced,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove() {
|
|
||||||
this.keys = [];
|
|
||||||
this.broadcastMessage((c: FollowSlaveClient) => {
|
|
||||||
c.clearHints();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private hintchars() {
|
|
||||||
return settingRepository.get().properties.hintchars;
|
|
||||||
}
|
|
||||||
|
|
||||||
private broadcastMessage(f: (clinet: FollowSlaveClient) => void) {
|
|
||||||
let windows = [window.self].concat(Array.from(window.frames as any));
|
|
||||||
windows
|
|
||||||
.map(w => new FollowSlaveClientImpl(w))
|
|
||||||
.forEach(c => f(c));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
import CommonComponent from '../common';
|
|
||||||
import FollowController from './follow-controller';
|
|
||||||
import * as consoleFrames from '../../console-frames';
|
|
||||||
import * as messages from '../../../shared/messages';
|
|
||||||
import MessageListener from '../../MessageListener';
|
|
||||||
import AddonEnabledUseCase from '../../usecases/AddonEnabledUseCase';
|
|
||||||
import { ScrollPresenterImpl } from '../../presenters/ScrollPresenter';
|
|
||||||
|
|
||||||
let addonEnabledUseCase = new AddonEnabledUseCase();
|
|
||||||
let scrollPresenter = new ScrollPresenterImpl();
|
|
||||||
|
|
||||||
export default class TopContent {
|
|
||||||
private win: Window;
|
|
||||||
|
|
||||||
constructor(win: Window, store: any) {
|
|
||||||
this.win = win;
|
|
||||||
|
|
||||||
new CommonComponent(win, store); // eslint-disable-line no-new
|
|
||||||
new FollowController(win, store); // eslint-disable-line no-new
|
|
||||||
|
|
||||||
// TODO make component
|
|
||||||
consoleFrames.initialize(this.win.document);
|
|
||||||
|
|
||||||
new MessageListener().onWebMessage(this.onWebMessage.bind(this));
|
|
||||||
new MessageListener().onBackgroundMessage(
|
|
||||||
this.onBackgroundMessage.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
onWebMessage(message: messages.Message) {
|
|
||||||
switch (message.type) {
|
|
||||||
case messages.CONSOLE_UNFOCUS:
|
|
||||||
this.win.focus();
|
|
||||||
consoleFrames.blur(window.document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onBackgroundMessage(message: messages.Message) {
|
|
||||||
let addonEnabled = addonEnabledUseCase.getEnabled();
|
|
||||||
|
|
||||||
switch (message.type) {
|
|
||||||
case messages.ADDON_ENABLED_QUERY:
|
|
||||||
return Promise.resolve(addonEnabled);
|
|
||||||
case messages.TAB_SCROLL_TO:
|
|
||||||
return scrollPresenter.scrollTo(message.x, message.y, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
import * as messages from '../shared/messages';
|
|
||||||
|
|
||||||
const initialize = (doc: Document): HTMLIFrameElement => {
|
const initialize = (doc: Document): HTMLIFrameElement => {
|
||||||
let iframe = doc.createElement('iframe');
|
let iframe = doc.createElement('iframe');
|
||||||
iframe.src = browser.runtime.getURL('build/console.html');
|
iframe.src = browser.runtime.getURL('build/console.html');
|
||||||
|
@ -15,24 +13,4 @@ const blur = (doc: Document) => {
|
||||||
ele.blur();
|
ele.blur();
|
||||||
};
|
};
|
||||||
|
|
||||||
const postError = (text: string): Promise<any> => {
|
export { initialize, blur };
|
||||||
return browser.runtime.sendMessage({
|
|
||||||
type: messages.CONSOLE_FRAME_MESSAGE,
|
|
||||||
message: {
|
|
||||||
type: messages.CONSOLE_SHOW_ERROR,
|
|
||||||
text,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const postInfo = (text: string): Promise<any> => {
|
|
||||||
return browser.runtime.sendMessage({
|
|
||||||
type: messages.CONSOLE_FRAME_MESSAGE,
|
|
||||||
message: {
|
|
||||||
type: messages.CONSOLE_SHOW_INFO,
|
|
||||||
text,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export { initialize, blur, postError, postInfo };
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import * as doms from '../shared/utils/dom';
|
|
||||||
|
|
||||||
const focusInput = (): void => {
|
|
||||||
let inputTypes = ['email', 'number', 'search', 'tel', 'text', 'url'];
|
|
||||||
let inputSelector = inputTypes.map(type => `input[type=${type}]`).join(',');
|
|
||||||
let targets = window.document.querySelectorAll(inputSelector + ',textarea');
|
|
||||||
let target = Array.from(targets).find(doms.isVisible);
|
|
||||||
if (target instanceof HTMLInputElement) {
|
|
||||||
target.focus();
|
|
||||||
} else if (target instanceof HTMLTextAreaElement) {
|
|
||||||
target.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export { focusInput };
|
|
|
@ -1,8 +1,5 @@
|
||||||
// import TopContentComponent from './components/top-content';
|
|
||||||
// import FrameContentComponent from './components/frame-content';
|
|
||||||
import * as consoleFrames from './console-frames';
|
import * as consoleFrames from './console-frames';
|
||||||
import consoleFrameStyle from './site-style';
|
import consoleFrameStyle from './site-style';
|
||||||
// import { newStore } from './store';
|
|
||||||
import MessageListener from './MessageListener';
|
import MessageListener from './MessageListener';
|
||||||
import FindController from './controllers/FindController';
|
import FindController from './controllers/FindController';
|
||||||
import MarkController from './controllers/MarkController';
|
import MarkController from './controllers/MarkController';
|
||||||
|
@ -18,12 +15,8 @@ import * as blacklists from '../shared/blacklists';
|
||||||
import MarkKeyController from './controllers/MarkKeyController';
|
import MarkKeyController from './controllers/MarkKeyController';
|
||||||
import AddonEnabledController from './controllers/AddonEnabledController';
|
import AddonEnabledController from './controllers/AddonEnabledController';
|
||||||
|
|
||||||
// const store = newStore();
|
|
||||||
|
|
||||||
let listener = new MessageListener();
|
let listener = new MessageListener();
|
||||||
if (window.self === window.top) {
|
if (window.self === window.top) {
|
||||||
// new TopContentComponent(window, store); // eslint-disable-line no-new
|
|
||||||
|
|
||||||
let findController = new FindController();
|
let findController = new FindController();
|
||||||
|
|
||||||
let followMasterController = new FollowMasterController();
|
let followMasterController = new FollowMasterController();
|
||||||
|
@ -63,8 +56,6 @@ if (window.self === window.top) {
|
||||||
});
|
});
|
||||||
|
|
||||||
consoleFrames.initialize(window.document);
|
consoleFrames.initialize(window.document);
|
||||||
} else {
|
|
||||||
// new FrameContentComponent(window, store); // eslint-disable-line no-new
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let followSlaveController = new FollowSlaveController();
|
let followSlaveController = new FollowSlaveController();
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
import * as actions from '../actions';
|
|
||||||
|
|
||||||
export interface State {
|
|
||||||
enabled: boolean;
|
|
||||||
newTab: boolean;
|
|
||||||
background: boolean;
|
|
||||||
keys: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultState: State = {
|
|
||||||
enabled: false,
|
|
||||||
newTab: false,
|
|
||||||
background: false,
|
|
||||||
keys: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function reducer(
|
|
||||||
state: State = defaultState,
|
|
||||||
action: actions.FollowAction,
|
|
||||||
): State {
|
|
||||||
switch (action.type) {
|
|
||||||
case actions.FOLLOW_CONTROLLER_ENABLE:
|
|
||||||
return { ...state,
|
|
||||||
enabled: true,
|
|
||||||
newTab: action.newTab,
|
|
||||||
background: action.background,
|
|
||||||
keys: '', };
|
|
||||||
case actions.FOLLOW_CONTROLLER_DISABLE:
|
|
||||||
return { ...state,
|
|
||||||
enabled: false, };
|
|
||||||
case actions.FOLLOW_CONTROLLER_KEY_PRESS:
|
|
||||||
return { ...state,
|
|
||||||
keys: state.keys + action.key, };
|
|
||||||
case actions.FOLLOW_CONTROLLER_BACKSPACE:
|
|
||||||
return { ...state,
|
|
||||||
keys: state.keys.slice(0, -1), };
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { combineReducers } from 'redux';
|
|
||||||
import input, { State as InputState } from './input';
|
|
||||||
import followController, { State as FollowControllerState }
|
|
||||||
from './follow-controller';
|
|
||||||
import mark, { State as MarkState } from './mark';
|
|
||||||
|
|
||||||
export interface State {
|
|
||||||
input: InputState;
|
|
||||||
followController: FollowControllerState;
|
|
||||||
mark: MarkState;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default combineReducers({
|
|
||||||
input, followController, mark,
|
|
||||||
});
|
|
|
@ -1,26 +0,0 @@
|
||||||
import * as actions from '../actions';
|
|
||||||
import Key from '../domains/Key';
|
|
||||||
|
|
||||||
export interface State {
|
|
||||||
keys: Key[],
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultState: State = {
|
|
||||||
keys: []
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function reducer(
|
|
||||||
state: State = defaultState,
|
|
||||||
action: actions.InputAction,
|
|
||||||
): State {
|
|
||||||
switch (action.type) {
|
|
||||||
case actions.INPUT_KEY_PRESS:
|
|
||||||
return { ...state,
|
|
||||||
keys: state.keys.concat([action.key]), };
|
|
||||||
case actions.INPUT_CLEAR_KEYS:
|
|
||||||
return { ...state,
|
|
||||||
keys: [], };
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
import * as actions from '../actions';
|
|
||||||
|
|
||||||
export interface State {
|
|
||||||
setMode: boolean;
|
|
||||||
jumpMode: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultState: State = {
|
|
||||||
setMode: false,
|
|
||||||
jumpMode: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function reducer(
|
|
||||||
state: State = defaultState,
|
|
||||||
action: actions.MarkAction,
|
|
||||||
): State {
|
|
||||||
switch (action.type) {
|
|
||||||
case actions.MARK_START_SET:
|
|
||||||
return { ...state, setMode: true };
|
|
||||||
case actions.MARK_START_JUMP:
|
|
||||||
return { ...state, jumpMode: true };
|
|
||||||
case actions.MARK_CANCEL:
|
|
||||||
return { ...state, setMode: false, jumpMode: false };
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
import promise from 'redux-promise';
|
|
||||||
import reducers from '../reducers';
|
|
||||||
import { createStore, applyMiddleware } from 'redux';
|
|
||||||
|
|
||||||
export const newStore = () => createStore(
|
|
||||||
reducers,
|
|
||||||
applyMiddleware(promise),
|
|
||||||
);
|
|
|
@ -1,34 +0,0 @@
|
||||||
import * as actions from 'content/actions';
|
|
||||||
import * as followControllerActions from 'content/actions/follow-controller';
|
|
||||||
|
|
||||||
describe('follow-controller actions', () => {
|
|
||||||
describe('enable', () => {
|
|
||||||
it('creates FOLLOW_CONTROLLER_ENABLE action', () => {
|
|
||||||
let action = followControllerActions.enable(true);
|
|
||||||
expect(action.type).to.equal(actions.FOLLOW_CONTROLLER_ENABLE);
|
|
||||||
expect(action.newTab).to.equal(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('disable', () => {
|
|
||||||
it('creates FOLLOW_CONTROLLER_DISABLE action', () => {
|
|
||||||
let action = followControllerActions.disable(true);
|
|
||||||
expect(action.type).to.equal(actions.FOLLOW_CONTROLLER_DISABLE);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('keyPress', () => {
|
|
||||||
it('creates FOLLOW_CONTROLLER_KEY_PRESS action', () => {
|
|
||||||
let action = followControllerActions.keyPress(100);
|
|
||||||
expect(action.type).to.equal(actions.FOLLOW_CONTROLLER_KEY_PRESS);
|
|
||||||
expect(action.key).to.equal(100);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('backspace', () => {
|
|
||||||
it('creates FOLLOW_CONTROLLER_BACKSPACE action', () => {
|
|
||||||
let action = followControllerActions.backspace(100);
|
|
||||||
expect(action.type).to.equal(actions.FOLLOW_CONTROLLER_BACKSPACE);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,19 +0,0 @@
|
||||||
import * as actions from 'content/actions';
|
|
||||||
import * as inputActions from 'content/actions/input';
|
|
||||||
|
|
||||||
describe("input actions", () => {
|
|
||||||
describe("keyPress", () => {
|
|
||||||
it('create INPUT_KEY_PRESS action', () => {
|
|
||||||
let action = inputActions.keyPress('a');
|
|
||||||
expect(action.type).to.equal(actions.INPUT_KEY_PRESS);
|
|
||||||
expect(action.key).to.equal('a');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("clearKeys", () => {
|
|
||||||
it('create INPUT_CLEAR_KEYSaction', () => {
|
|
||||||
let action = inputActions.clearKeys();
|
|
||||||
expect(action.type).to.equal(actions.INPUT_CLEAR_KEYS);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,25 +0,0 @@
|
||||||
import * as actions from 'content/actions';
|
|
||||||
import * as markActions from 'content/actions/mark';
|
|
||||||
|
|
||||||
describe('mark actions', () => {
|
|
||||||
describe('startSet', () => {
|
|
||||||
it('create MARK_START_SET action', () => {
|
|
||||||
let action = markActions.startSet();
|
|
||||||
expect(action.type).to.equal(actions.MARK_START_SET);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('startJump', () => {
|
|
||||||
it('create MARK_START_JUMP action', () => {
|
|
||||||
let action = markActions.startJump();
|
|
||||||
expect(action.type).to.equal(actions.MARK_START_JUMP);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('cancel', () => {
|
|
||||||
it('create MARK_CANCEL action', () => {
|
|
||||||
let action = markActions.cancel();
|
|
||||||
expect(action.type).to.equal(actions.MARK_CANCEL);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,17 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<a id='visible_a' href='#' >link</a>
|
|
||||||
<a href='#' style='display:none'>invisible 1</a>
|
|
||||||
<a href='#' style='visibility:hidden'>invisible 2</a>
|
|
||||||
<i>not link<i>
|
|
||||||
<div id='editable_div_1' contenteditable>link</div>
|
|
||||||
<div id='editable_div_2' contenteditable='true'>link</div>
|
|
||||||
<div id='x' contenteditable='false'>link</div>
|
|
||||||
<details>
|
|
||||||
<summary id='summary_1'>summary link</summary>
|
|
||||||
Some details
|
|
||||||
<a href='#'>not visible</a>
|
|
||||||
</details>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,25 +0,0 @@
|
||||||
import FollowComponent from 'content/components/common/follow';
|
|
||||||
|
|
||||||
describe('FollowComponent', () => {
|
|
||||||
describe('#getTargetElements', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
document.body.innerHTML = __html__['test/content/components/common/follow.html'];
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns visible links', () => {
|
|
||||||
let targets = FollowComponent.getTargetElements(
|
|
||||||
window,
|
|
||||||
{ width: window.innerWidth, height: window.innerHeight },
|
|
||||||
{ x: 0, y: 0 });
|
|
||||||
expect(targets).to.have.lengthOf(4);
|
|
||||||
|
|
||||||
let ids = Array.prototype.map.call(targets, (e) => e.id);
|
|
||||||
expect(ids).to.include.members([
|
|
||||||
'visible_a',
|
|
||||||
'editable_div_1',
|
|
||||||
'editable_div_2',
|
|
||||||
'summary_1',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,47 +0,0 @@
|
||||||
import * as actions from 'content/actions';
|
|
||||||
import followControllerReducer from 'content/reducers/follow-controller';
|
|
||||||
|
|
||||||
describe('follow-controller reducer', () => {
|
|
||||||
it ('returns the initial state', () => {
|
|
||||||
let state = followControllerReducer(undefined, {});
|
|
||||||
expect(state).to.have.property('enabled', false);
|
|
||||||
expect(state).to.have.property('newTab');
|
|
||||||
expect(state).to.have.deep.property('keys', '');
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('returns next state for FOLLOW_CONTROLLER_ENABLE', () => {
|
|
||||||
let action = { type: actions.FOLLOW_CONTROLLER_ENABLE, newTab: true };
|
|
||||||
let state = followControllerReducer({ enabled: false, newTab: false }, action);
|
|
||||||
expect(state).to.have.property('enabled', true);
|
|
||||||
expect(state).to.have.property('newTab', true);
|
|
||||||
expect(state).to.have.property('keys', '');
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('returns next state for FOLLOW_CONTROLLER_DISABLE', () => {
|
|
||||||
let action = { type: actions.FOLLOW_CONTROLLER_DISABLE };
|
|
||||||
let state = followControllerReducer({ enabled: true }, action);
|
|
||||||
expect(state).to.have.property('enabled', false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('returns next state for FOLLOW_CONTROLLER_KEY_PRESS', () => {
|
|
||||||
let action = { type: actions.FOLLOW_CONTROLLER_KEY_PRESS, key: 'a'};
|
|
||||||
let state = followControllerReducer({ keys: '' }, action);
|
|
||||||
expect(state).to.have.deep.property('keys', 'a');
|
|
||||||
|
|
||||||
action = { type: actions.FOLLOW_CONTROLLER_KEY_PRESS, key: 'b'};
|
|
||||||
state = followControllerReducer(state, action);
|
|
||||||
expect(state).to.have.deep.property('keys', 'ab');
|
|
||||||
});
|
|
||||||
|
|
||||||
it ('returns next state for FOLLOW_CONTROLLER_BACKSPACE', () => {
|
|
||||||
let action = { type: actions.FOLLOW_CONTROLLER_BACKSPACE };
|
|
||||||
let state = followControllerReducer({ keys: 'ab' }, action);
|
|
||||||
expect(state).to.have.deep.property('keys', 'a');
|
|
||||||
|
|
||||||
state = followControllerReducer(state, action);
|
|
||||||
expect(state).to.have.deep.property('keys', '');
|
|
||||||
|
|
||||||
state = followControllerReducer(state, action);
|
|
||||||
expect(state).to.have.deep.property('keys', '');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,25 +0,0 @@
|
||||||
import * as actions from 'content/actions';
|
|
||||||
import inputReducer from 'content/reducers/input';
|
|
||||||
|
|
||||||
describe("input reducer", () => {
|
|
||||||
it('return the initial state', () => {
|
|
||||||
let state = inputReducer(undefined, {});
|
|
||||||
expect(state).to.have.deep.property('keys', []);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('return next state for INPUT_KEY_PRESS', () => {
|
|
||||||
let action = { type: actions.INPUT_KEY_PRESS, key: 'a' };
|
|
||||||
let state = inputReducer(undefined, action);
|
|
||||||
expect(state).to.have.deep.property('keys', ['a']);
|
|
||||||
|
|
||||||
action = { type: actions.INPUT_KEY_PRESS, key: 'b' };
|
|
||||||
state = inputReducer(state, action);
|
|
||||||
expect(state).to.have.deep.property('keys', ['a', 'b']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('return next state for INPUT_CLEAR_KEYS', () => {
|
|
||||||
let action = { type: actions.INPUT_CLEAR_KEYS };
|
|
||||||
let state = inputReducer({ keys: [1, 2, 3] }, action);
|
|
||||||
expect(state).to.have.deep.property('keys', []);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
import * as actions from 'content/actions';
|
|
||||||
import reducer from 'content/reducers/mark';
|
|
||||||
|
|
||||||
describe("mark reducer", () => {
|
|
||||||
it('return the initial state', () => {
|
|
||||||
let state = reducer(undefined, {});
|
|
||||||
expect(state.setMode).to.be.false;
|
|
||||||
expect(state.jumpMode).to.be.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('starts set mode', () => {
|
|
||||||
let action = { type: actions.MARK_START_SET };
|
|
||||||
let state = reducer(undefined, action);
|
|
||||||
expect(state.setMode).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('starts jump mode', () => {
|
|
||||||
let action = { type: actions.MARK_START_JUMP };
|
|
||||||
let state = reducer(undefined, action);
|
|
||||||
expect(state.jumpMode).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cancels set and jump mode', () => {
|
|
||||||
let action = { type: actions.MARK_CANCEL };
|
|
||||||
let state = reducer({ setMode: true }, action);
|
|
||||||
expect(state.setMode).to.be.false;
|
|
||||||
|
|
||||||
state = reducer({ jumpMode: true }, action);
|
|
||||||
expect(state.jumpMode).to.be.false;
|
|
||||||
});
|
|
||||||
});
|
|
Reference in a new issue