Scroll on global mark and handle gone tab

jh-changes
Shin'ya Ueoka 6 years ago
parent 003742ec51
commit e248477ecb
  1. 7
      src/background/domains/global-mark.js
  2. 8
      src/background/infrastructures/content-message-client.js
  3. 4
      src/background/repositories/mark.js
  4. 16
      src/background/usecases/mark.js
  5. 8
      src/content/components/common/mark.js
  6. 3
      src/content/components/top-content/index.js
  7. 2
      src/shared/messages.js
  8. 7
      test/background/domains/global-mark.test.js
  9. 7
      test/background/repositories/mark.test.js

@ -1,6 +1,7 @@
export default class GlobalMark { export default class GlobalMark {
constructor(tabId, x, y) { constructor(tabId, url, x, y) {
this.tabId0 = tabId; this.tabId0 = tabId;
this.url0 = url;
this.x0 = x; this.x0 = x;
this.y0 = y; this.y0 = y;
} }
@ -9,6 +10,10 @@ export default class GlobalMark {
return this.tabId0; return this.tabId0;
} }
get url() {
return this.url0;
}
get x() { get x() {
return this.x0; return this.x0;
} }

@ -22,4 +22,12 @@ export default class ContentMessageClient {
type: messages.ADDON_TOGGLE_ENABLED, type: messages.ADDON_TOGGLE_ENABLED,
}); });
} }
scrollTo(tabId, x, y) {
return browser.tabs.sendMessage(tabId, {
type: messages.TAB_SCROLL_TO,
x,
y,
});
}
} }

@ -14,13 +14,13 @@ export default class MarkRepository {
if (!data) { if (!data) {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
let mark = new GlobalMark(data.tabId, data.x, data.y); let mark = new GlobalMark(data.tabId, data.url, data.x, data.y);
return Promise.resolve(mark); return Promise.resolve(mark);
} }
setMark(key, mark) { setMark(key, mark) {
let marks = this.getOrEmptyMarks(); let marks = this.getOrEmptyMarks();
marks[key] = { tabId: mark.tabId, x: mark.x, y: mark.y }; marks[key] = { tabId: mark.tabId, url: mark.url, x: mark.x, y: mark.y };
this.cache.set(MARK_KEY, marks); this.cache.set(MARK_KEY, marks);
return Promise.resolve(); return Promise.resolve();

@ -2,17 +2,19 @@ import GlobalMark from '../domains/global-mark';
import TabPresenter from '../presenters/tab'; import TabPresenter from '../presenters/tab';
import MarkRepository from '../repositories/mark'; import MarkRepository from '../repositories/mark';
import ConsolePresenter from '../presenters/console'; import ConsolePresenter from '../presenters/console';
import ContentMessageClient from '../infrastructures/content-message-client';
export default class MarkInteractor { export default class MarkInteractor {
constructor() { constructor() {
this.tabPresenter = new TabPresenter(); this.tabPresenter = new TabPresenter();
this.markRepository = new MarkRepository(); this.markRepository = new MarkRepository();
this.consolePresenter = new ConsolePresenter(); this.consolePresenter = new ConsolePresenter();
this.contentMessageClient = new ContentMessageClient();
} }
async setGlobal(key, x, y) { async setGlobal(key, x, y) {
let tab = await this.tabPresenter.getCurrent(); let tab = await this.tabPresenter.getCurrent();
let mark = new GlobalMark(tab.id, x, y); let mark = new GlobalMark(tab.id, tab.url, x, y);
return this.markRepository.setMark(key, mark); return this.markRepository.setMark(key, mark);
} }
@ -23,7 +25,15 @@ export default class MarkInteractor {
if (!mark) { if (!mark) {
return this.consolePresenter.showError(current.id, 'Mark is not set'); return this.consolePresenter.showError(current.id, 'Mark is not set');
} }
// TODO scroll pages and handle if tab is gone
return this.tabPresenter.select(mark.tabId); return this.contentMessageClient.scrollTo(
mark.tabId, mark.x, mark.y
).then(() => {
return this.tabPresenter.select(mark.tabId);
}).catch(async() => {
let tab = await this.tabPresenter.create(mark.url);
let mark2 = new GlobalMark(tab.id, mark.url, mark.x, mark.y);
return this.markRepository.setMark(key, mark2);
});
} }
} }

@ -7,6 +7,10 @@ const cancelKey = (key) => {
return key.key === 'Esc' || key.key === '[' && key.ctrlKey; return key.key === 'Esc' || key.key === '[' && key.ctrlKey;
}; };
const globalKey = (key) => {
return (/^[A-Z0-9]$/).test(key);
};
export default class MarkComponent { export default class MarkComponent {
constructor(body, store) { constructor(body, store) {
this.body = body; this.body = body;
@ -30,9 +34,9 @@ export default class MarkComponent {
if (key.ctrlKey || key.metaKey || key.altKey) { if (key.ctrlKey || key.metaKey || key.altKey) {
consoleFrames.postError(window.document, 'Unknown mark'); consoleFrames.postError(window.document, 'Unknown mark');
} else if (key.shiftKey && markStage.setMode) { } else if (globalKey(key.key) && markStage.setMode) {
this.doSetGlobal(key); this.doSetGlobal(key);
} else if (key.shiftKey && markStage.jumpMode) { } else if (globalKey(key.key) && markStage.jumpMode) {
this.doJumpGlobal(key); this.doJumpGlobal(key);
} else if (markStage.setMode) { } else if (markStage.setMode) {
this.doSet(key); this.doSet(key);

@ -3,6 +3,7 @@ import FollowController from './follow-controller';
import FindComponent from './find'; import FindComponent from './find';
import * as consoleFrames from '../../console-frames'; import * as consoleFrames from '../../console-frames';
import messages from 'shared/messages'; import messages from 'shared/messages';
import * as scrolls from 'content/scrolls';
export default class TopContent { export default class TopContent {
@ -33,6 +34,8 @@ export default class TopContent {
type: messages.ADDON_ENABLED_RESPONSE, type: messages.ADDON_ENABLED_RESPONSE,
enabled: addonState.enabled, enabled: addonState.enabled,
}); });
case messages.TAB_SCROLL_TO:
return scrolls.scrollTo(message.x, message.y, false);
} }
} }
} }

@ -46,6 +46,8 @@ export default {
MARK_SET_GLOBAL: 'mark.set.global', MARK_SET_GLOBAL: 'mark.set.global',
MARK_JUMP_GLOBAL: 'mark.jump.global', MARK_JUMP_GLOBAL: 'mark.jump.global',
TAB_SCROLL_TO: 'tab.scroll.to',
FIND_NEXT: 'find.next', FIND_NEXT: 'find.next',
FIND_PREV: 'find.prev', FIND_PREV: 'find.prev',
FIND_GET_KEYWORD: 'find.get.keyword', FIND_GET_KEYWORD: 'find.get.keyword',

@ -1,9 +1,10 @@
import GlobalMark from 'background/domains/global-mark'; import GlobalMark from 'background/domains/global-mark';
describe("background/domains/global-mark", () => { describe('background/domains/global-mark', () => {
describe("constructor and getter", () => { describe('constructor and getter', () => {
let mark = new GlobalMark(1, 10, 30); let mark = new GlobalMark(1, 'http://example.com', 10, 30);
expect(mark.tabId).to.equal(1); expect(mark.tabId).to.equal(1);
expect(mark.url).to.equal('http://example.com');
expect(mark.x).to.equal(10); expect(mark.x).to.equal(10);
expect(mark.y).to.equal(30); expect(mark.y).to.equal(30);
}); });

@ -1,7 +1,7 @@
import MarkRepository from 'background/repositories/mark'; import MarkRepository from 'background/repositories/mark';
import GlobalMark from 'background/domains/global-mark'; import GlobalMark from 'background/domains/global-mark';
describe("background/repositories/version", () => { describe('background/repositories/mark', () => {
let repository; let repository;
beforeEach(() => { beforeEach(() => {
@ -9,13 +9,16 @@ describe("background/repositories/version", () => {
}); });
it('get and set', async() => { it('get and set', async() => {
let mark = new GlobalMark(1, 10, 30); let mark = new GlobalMark(1, 'http://example.com', 10, 30);
repository.setMark('A', mark); repository.setMark('A', mark);
let got = await repository.getMark('A'); let got = await repository.getMark('A');
expect(got).to.be.a('object'); expect(got).to.be.a('object');
expect(got.tabId).to.equal(1); expect(got.tabId).to.equal(1);
expect(got.url).to.equal('http://example.com');
expect(got.x).to.equal(10);
expect(got.y).to.equal(30);
got = await repository.getMark('B'); got = await repository.getMark('B');
expect(got).to.be.undefined; expect(got).to.be.undefined;