Merge pull request #355 from ueokande/search-across-pages

Search across pages
jh-changes
Shin'ya Ueoka 6 years ago committed by GitHub
commit d2a3c6cdd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      src/background/actions/find.js
  2. 3
      src/background/actions/index.js
  3. 8
      src/background/components/background.js
  4. 16
      src/background/reducers/find.js
  5. 3
      src/background/reducers/index.js
  6. 59
      src/content/actions/find.js
  7. 5
      src/content/actions/operation.js
  8. 13
      src/content/components/top-content/find.js
  9. 9
      src/content/console-frames.js
  10. 2
      src/content/reducers/find.js
  11. 2
      src/shared/messages.js
  12. 13
      test/background/actions/find.test.js
  13. 19
      test/background/reducers/find.test.js
  14. 2
      test/content/reducers/find.test.js

@ -0,0 +1,10 @@
import actions from './index';
const setKeyword = (keyword) => {
return {
type: actions.FIND_SET_KEYWORD,
keyword,
};
};
export { setKeyword };

@ -2,4 +2,7 @@ export default {
// Settings // Settings
SETTING_SET_SETTINGS: 'setting.set.settings', SETTING_SET_SETTINGS: 'setting.set.settings',
SETTING_SET_PROPERTY: 'setting.set.property', SETTING_SET_PROPERTY: 'setting.set.property',
// Find
FIND_SET_KEYWORD: 'find.set.keyword',
}; };

@ -2,6 +2,7 @@ import messages from 'shared/messages';
import * as operationActions from 'background/actions/operation'; import * as operationActions from 'background/actions/operation';
import * as commandActions from 'background/actions/command'; import * as commandActions from 'background/actions/command';
import * as settingActions from 'background/actions/setting'; import * as settingActions from 'background/actions/setting';
import * as findActions from 'background/actions/find';
import * as tabActions from 'background/actions/tab'; import * as tabActions from 'background/actions/tab';
import * as commands from 'shared/commands'; import * as commands from 'shared/commands';
@ -23,6 +24,8 @@ export default class BackgroundComponent {
onMessage(message, sender) { onMessage(message, sender) {
let settings = this.store.getState().setting; let settings = this.store.getState().setting;
let find = this.store.getState().find;
switch (message.type) { switch (message.type) {
case messages.BACKGROUND_OPERATION: case messages.BACKGROUND_OPERATION:
return this.store.dispatch( return this.store.dispatch(
@ -48,6 +51,11 @@ export default class BackgroundComponent {
case messages.SETTINGS_RELOAD: case messages.SETTINGS_RELOAD:
this.store.dispatch(settingActions.load()); this.store.dispatch(settingActions.load());
return this.broadcastSettingsChanged(); 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({});
} }
} }

@ -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 './setting'; import settingReducer from './setting';
import findReducer from './find';
// Make setting reducer instead of re-use // Make setting reducer instead of re-use
const defaultState = { const defaultState = {
setting: settingReducer(undefined, {}), setting: settingReducer(undefined, {}),
find: findReducer(undefined, {}),
}; };
export default function reducer(state = defaultState, action = {}) { export default function reducer(state = defaultState, action = {}) {
return Object.assign({}, state, { return Object.assign({}, state, {
setting: settingReducer(state.setting, action), setting: settingReducer(state.setting, action),
find: findReducer(state.find, action),
}); });
} }

@ -5,6 +5,7 @@
// NOTE: window.find is not standard API // NOTE: window.find is not standard API
// https://developer.mozilla.org/en-US/docs/Web/API/Window/find // https://developer.mozilla.org/en-US/docs/Web/API/Window/find
import messages from 'shared/messages';
import actions from 'content/actions'; import actions from 'content/actions';
import * as consoleFrames from '../console-frames'; import * as consoleFrames from '../console-frames';
@ -14,6 +15,13 @@ const postPatternNotFound = (pattern) => {
'Pattern not found: ' + pattern); 'Pattern not found: ' + pattern);
}; };
const postPatternFound = (pattern) => {
return consoleFrames.postInfo(
window.document,
'Pattern found: ' + pattern,
);
};
const find = (string, backwards) => { const find = (string, backwards) => {
let caseSensitive = false; let caseSensitive = false;
let wrapScan = true; let wrapScan = true;
@ -24,32 +32,49 @@ const find = (string, backwards) => {
return window.find(string, caseSensitive, backwards, wrapScan); return window.find(string, caseSensitive, backwards, wrapScan);
}; };
const findNext = (keyword, reset, backwards) => { const findNext = (currentKeyword, reset, backwards) => {
if (reset) { if (reset) {
window.getSelection().removeAllRanges(); window.getSelection().removeAllRanges();
} }
let found = find(keyword, backwards); let promise = Promise.resolve(currentKeyword);
if (!found) { if (currentKeyword) {
window.getSelection().removeAllRanges(); browser.runtime.sendMessage({
found = find(keyword, backwards); type: messages.FIND_SET_KEYWORD,
keyword: currentKeyword,
});
} else {
promise = browser.runtime.sendMessage({
type: messages.FIND_GET_KEYWORD,
});
} }
if (!found) {
postPatternNotFound(keyword); return promise.then((keyword) => {
} let found = find(keyword, backwards);
return { if (!found) {
type: actions.FIND_SET_KEYWORD, window.getSelection().removeAllRanges();
keyword, found = find(keyword, backwards);
found, }
}; if (found) {
postPatternFound(keyword);
} else {
postPatternNotFound(keyword);
}
return {
type: actions.FIND_SET_KEYWORD,
keyword,
found,
};
});
}; };
const next = (keyword, reset) => { const next = (currentKeyword, reset) => {
return findNext(keyword, reset, false); return findNext(currentKeyword, reset, false);
}; };
const prev = (keyword, reset) => { const prev = (currentKeyword, reset) => {
return findNext(keyword, reset, true); return findNext(currentKeyword, reset, true);
}; };
export { next, prev }; export { next, prev };

@ -62,10 +62,7 @@ const exec = (operation, repeat, settings) => {
return focuses.focusInput(); return focuses.focusInput();
case operations.URLS_YANK: case operations.URLS_YANK:
urls.yank(window); urls.yank(window);
return consoleFrames.postMessage(window.document, { return consoleFrames.postInfo(window.document, 'Current url yanked');
type: messages.CONSOLE_SHOW_INFO,
text: 'Current url yanked',
});
case operations.URLS_PASTE: case operations.URLS_PASTE:
return urls.paste(window, operation.newTab ? operation.newTab : false); return urls.paste(window, operation.newTab ? operation.newTab : false);
default: default:

@ -1,6 +1,5 @@
import * as findActions from 'content/actions/find'; import * as findActions from 'content/actions/find';
import messages from 'shared/messages'; import messages from 'shared/messages';
import * as consoleFrames from '../../console-frames';
export default class FindComponent { export default class FindComponent {
constructor(win, store) { constructor(win, store) {
@ -32,23 +31,11 @@ export default class FindComponent {
next() { next() {
let state = this.store.getState().find; let state = this.store.getState().find;
if (!state.found) {
return consoleFrames.postError(
window.document,
'Pattern not found: ' + state.keyword);
}
return this.store.dispatch(findActions.next(state.keyword, false)); return this.store.dispatch(findActions.next(state.keyword, false));
} }
prev() { prev() {
let state = this.store.getState().find; let state = this.store.getState().find;
if (!state.found) {
return consoleFrames.postError(
window.document,
'Pattern not found: ' + state.keyword);
}
return this.store.dispatch(findActions.prev(state.keyword, false)); return this.store.dispatch(findActions.prev(state.keyword, false));
} }
} }

@ -28,4 +28,11 @@ const postError = (doc, message) => {
}); });
}; };
export { initialize, blur, postMessage, postError }; const postInfo = (doc, message) => {
return postMessage(doc, {
type: messages.CONSOLE_SHOW_INFO,
text: message,
});
};
export { initialize, blur, postError, postInfo };

@ -1,7 +1,7 @@
import actions from 'content/actions'; import actions from 'content/actions';
const defaultState = { const defaultState = {
keyword: '', keyword: null,
found: false, found: false,
}; };

@ -45,6 +45,8 @@ export default {
FIND_NEXT: 'find.next', FIND_NEXT: 'find.next',
FIND_PREV: 'find.prev', FIND_PREV: 'find.prev',
FIND_GET_KEYWORD: 'find.get.keyword',
FIND_SET_KEYWORD: 'find.set.keyword',
OPEN_URL: 'open.url', OPEN_URL: 'open.url',

@ -0,0 +1,13 @@
import { expect } from "chai";
import actions from 'background/actions';
import * as findActions from 'background/actions/find';
describe("find actions", () => {
describe("setKeyword", () => {
it('create FIND_SET_KEYWORD action', () => {
let action = findActions.setKeyword('banana');
expect(action.type).to.equal(actions.FIND_SET_KEYWORD);
expect(action.keyword).to.equal('banana');
});
});
});

@ -0,0 +1,19 @@
import { expect } from "chai";
import actions from 'background/actions';
import findReducer from 'background/reducers/find';
describe("find reducer", () => {
it('return the initial state', () => {
let state = findReducer(undefined, {});
expect(state).to.have.deep.property('keyword', null);
});
it('return next state for FIND_SET_KEYWORD', () => {
let action = {
type: actions.FIND_SET_KEYWORD,
keyword: 'cherry',
};
let state = findReducer(undefined, action);
expect(state).to.have.deep.property('keyword', 'cherry')
});
});

@ -5,7 +5,7 @@ import findReducer from 'content/reducers/find';
describe("find reducer", () => { describe("find reducer", () => {
it('return the initial state', () => { it('return the initial state', () => {
let state = findReducer(undefined, {}); let state = findReducer(undefined, {});
expect(state).to.have.property('keyword', ''); expect(state).to.have.property('keyword', null);
expect(state).to.have.property('found', false); expect(state).to.have.property('found', false);
}); });