aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2018-10-12 10:14:33 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2018-10-12 10:14:33 +0900
commit003742ec51aa7aea9214442bc0b611e2eb5eaf6e (patch)
tree20345e48bd226c1e83a1145721f7ba585a1452aa
parent6e6e306275a8ee5632a22b1e30c807bd5ae9cc7e (diff)
Support global marks which select a tab
-rw-r--r--src/background/controllers/mark.js15
-rw-r--r--src/background/domains/global-mark.js19
-rw-r--r--src/background/infrastructures/content-message-listener.js14
-rw-r--r--src/background/repositories/mark.js33
-rw-r--r--src/background/usecases/mark.js29
-rw-r--r--src/content/actions/mark.js20
-rw-r--r--src/content/components/common/mark.js15
-rw-r--r--src/shared/messages.js3
-rw-r--r--test/background/domains/global-mark.test.js10
-rw-r--r--test/background/infrastructures/memory-storage.test.js2
-rw-r--r--test/background/repositories/mark.test.js23
11 files changed, 179 insertions, 4 deletions
diff --git a/src/background/controllers/mark.js b/src/background/controllers/mark.js
new file mode 100644
index 0000000..8d0cefd
--- /dev/null
+++ b/src/background/controllers/mark.js
@@ -0,0 +1,15 @@
+import MarkInteractor from '../usecases/mark';
+
+export default class MarkController {
+ constructor() {
+ this.markInteractor = new MarkInteractor();
+ }
+
+ setGlobal(key, x, y) {
+ this.markInteractor.setGlobal(key, x, y);
+ }
+
+ jumpGlobal(key) {
+ this.markInteractor.jumpGlobal(key);
+ }
+}
diff --git a/src/background/domains/global-mark.js b/src/background/domains/global-mark.js
new file mode 100644
index 0000000..77afdba
--- /dev/null
+++ b/src/background/domains/global-mark.js
@@ -0,0 +1,19 @@
+export default class GlobalMark {
+ constructor(tabId, x, y) {
+ this.tabId0 = tabId;
+ this.x0 = x;
+ this.y0 = y;
+ }
+
+ get tabId() {
+ return this.tabId0;
+ }
+
+ get x() {
+ return this.x0;
+ }
+
+ get y() {
+ return this.y0;
+ }
+}
diff --git a/src/background/infrastructures/content-message-listener.js b/src/background/infrastructures/content-message-listener.js
index 4fcc6a6..beb52fe 100644
--- a/src/background/infrastructures/content-message-listener.js
+++ b/src/background/infrastructures/content-message-listener.js
@@ -5,6 +5,7 @@ import FindController from '../controllers/find';
import AddonEnabledController from '../controllers/addon-enabled';
import LinkController from '../controllers/link';
import OperationController from '../controllers/operation';
+import MarkController from '../controllers/mark';
export default class ContentMessageListener {
constructor() {
@@ -14,6 +15,7 @@ export default class ContentMessageListener {
this.addonEnabledController = new AddonEnabledController();
this.linkController = new LinkController();
this.backgroundOperationController = new OperationController();
+ this.markController = new MarkController();
}
run() {
@@ -59,6 +61,10 @@ export default class ContentMessageListener {
message.newTab, message.url, sender.tab.id, message.background);
case messages.BACKGROUND_OPERATION:
return this.onBackgroundOperation(message.operation);
+ case messages.MARK_SET_GLOBAL:
+ return this.onMarkSetGlobal(message.key, message.x, message.y);
+ case messages.MARK_JUMP_GLOBAL:
+ return this.onMarkJumpGlobal(message.key);
}
}
@@ -102,4 +108,12 @@ export default class ContentMessageListener {
onBackgroundOperation(operation) {
return this.backgroundOperationController.exec(operation);
}
+
+ onMarkSetGlobal(key, x, y) {
+ return this.markController.setGlobal(key, x, y);
+ }
+
+ onMarkJumpGlobal(key) {
+ return this.markController.jumpGlobal(key);
+ }
}
diff --git a/src/background/repositories/mark.js b/src/background/repositories/mark.js
new file mode 100644
index 0000000..a1f6a16
--- /dev/null
+++ b/src/background/repositories/mark.js
@@ -0,0 +1,33 @@
+import MemoryStorage from '../infrastructures/memory-storage';
+import GlobalMark from 'background/domains/global-mark';
+
+const MARK_KEY = 'mark';
+
+export default class MarkRepository {
+ constructor() {
+ this.cache = new MemoryStorage();
+ }
+
+ getMark(key) {
+ let marks = this.getOrEmptyMarks();
+ let data = marks[key];
+ if (!data) {
+ return Promise.resolve(undefined);
+ }
+ let mark = new GlobalMark(data.tabId, data.x, data.y);
+ return Promise.resolve(mark);
+ }
+
+ setMark(key, mark) {
+ let marks = this.getOrEmptyMarks();
+ marks[key] = { tabId: mark.tabId, x: mark.x, y: mark.y };
+ this.cache.set(MARK_KEY, marks);
+
+ return Promise.resolve();
+ }
+
+ getOrEmptyMarks() {
+ return this.cache.get(MARK_KEY) || {};
+ }
+}
+
diff --git a/src/background/usecases/mark.js b/src/background/usecases/mark.js
new file mode 100644
index 0000000..2cb3b45
--- /dev/null
+++ b/src/background/usecases/mark.js
@@ -0,0 +1,29 @@
+import GlobalMark from '../domains/global-mark';
+import TabPresenter from '../presenters/tab';
+import MarkRepository from '../repositories/mark';
+import ConsolePresenter from '../presenters/console';
+
+export default class MarkInteractor {
+ constructor() {
+ this.tabPresenter = new TabPresenter();
+ this.markRepository = new MarkRepository();
+ this.consolePresenter = new ConsolePresenter();
+ }
+
+ async setGlobal(key, x, y) {
+ let tab = await this.tabPresenter.getCurrent();
+ let mark = new GlobalMark(tab.id, x, y);
+ return this.markRepository.setMark(key, mark);
+ }
+
+ async jumpGlobal(key) {
+ let current = await this.tabPresenter.getCurrent();
+
+ let mark = await this.markRepository.getMark(key);
+ if (!mark) {
+ 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);
+ }
+}
diff --git a/src/content/actions/mark.js b/src/content/actions/mark.js
index 1f5174e..712a811 100644
--- a/src/content/actions/mark.js
+++ b/src/content/actions/mark.js
@@ -1,4 +1,5 @@
import actions from 'content/actions';
+import messages from 'shared/messages';
const startSet = () => {
return { type: actions.MARK_START_SET };
@@ -21,6 +22,25 @@ const setLocal = (key, x, y) => {
};
};
+const setGlobal = (key, x, y) => {
+ browser.runtime.sendMessage({
+ type: messages.MARK_SET_GLOBAL,
+ key,
+ x,
+ y,
+ });
+ return { type: '' };
+};
+
+const jumpGlobal = (key) => {
+ browser.runtime.sendMessage({
+ type: messages.MARK_JUMP_GLOBAL,
+ key,
+ });
+ return { type: '' };
+};
+
export {
startSet, startJump, cancel, setLocal,
+ setGlobal, jumpGlobal,
};
diff --git a/src/content/components/common/mark.js b/src/content/components/common/mark.js
index 06b2657..ce35afa 100644
--- a/src/content/components/common/mark.js
+++ b/src/content/components/common/mark.js
@@ -30,8 +30,10 @@ export default class MarkComponent {
if (key.ctrlKey || key.metaKey || key.altKey) {
consoleFrames.postError(window.document, 'Unknown mark');
- } else if (key.shiftKey) {
- consoleFrames.postError(window.document, 'Globa marks not supported');
+ } else if (key.shiftKey && markStage.setMode) {
+ this.doSetGlobal(key);
+ } else if (key.shiftKey && markStage.jumpMode) {
+ this.doJumpGlobal(key);
} else if (markStage.setMode) {
this.doSet(key);
} else if (markStage.jumpMode) {
@@ -56,4 +58,13 @@ export default class MarkComponent {
let { x, y } = marks[key.key];
scrolls.scrollTo(x, y, smoothscroll);
}
+
+ doSetGlobal(key) {
+ let { x, y } = scrolls.getScroll();
+ this.store.dispatch(markActions.setGlobal(key.key, x, y));
+ }
+
+ doJumpGlobal(key) {
+ this.store.dispatch(markActions.jumpGlobal(key.key));
+ }
}
diff --git a/src/shared/messages.js b/src/shared/messages.js
index 1f9c816..cd076ee 100644
--- a/src/shared/messages.js
+++ b/src/shared/messages.js
@@ -43,6 +43,9 @@ export default {
FOLLOW_ACTIVATE: 'follow.activate',
FOLLOW_KEY_PRESS: 'follow.key.press',
+ MARK_SET_GLOBAL: 'mark.set.global',
+ MARK_JUMP_GLOBAL: 'mark.jump.global',
+
FIND_NEXT: 'find.next',
FIND_PREV: 'find.prev',
FIND_GET_KEYWORD: 'find.get.keyword',
diff --git a/test/background/domains/global-mark.test.js b/test/background/domains/global-mark.test.js
new file mode 100644
index 0000000..15d492c
--- /dev/null
+++ b/test/background/domains/global-mark.test.js
@@ -0,0 +1,10 @@
+import GlobalMark from 'background/domains/global-mark';
+
+describe("background/domains/global-mark", () => {
+ describe("constructor and getter", () => {
+ let mark = new GlobalMark(1, 10, 30);
+ expect(mark.tabId).to.equal(1);
+ expect(mark.x).to.equal(10);
+ expect(mark.y).to.equal(30);
+ });
+});
diff --git a/test/background/infrastructures/memory-storage.test.js b/test/background/infrastructures/memory-storage.test.js
index 0fea895..8871749 100644
--- a/test/background/infrastructures/memory-storage.test.js
+++ b/test/background/infrastructures/memory-storage.test.js
@@ -1,8 +1,6 @@
import MemoryStorage from 'background/infrastructures/memory-storage';
describe("background/infrastructures/memory-storage", () => {
- let versionRepository;
-
it('stores values', () => {
let cache = new MemoryStorage();
cache.set('number', 123);
diff --git a/test/background/repositories/mark.test.js b/test/background/repositories/mark.test.js
new file mode 100644
index 0000000..94048ea
--- /dev/null
+++ b/test/background/repositories/mark.test.js
@@ -0,0 +1,23 @@
+import MarkRepository from 'background/repositories/mark';
+import GlobalMark from 'background/domains/global-mark';
+
+describe("background/repositories/version", () => {
+ let repository;
+
+ beforeEach(() => {
+ repository = new MarkRepository;
+ });
+
+ it('get and set', async() => {
+ let mark = new GlobalMark(1, 10, 30);
+
+ repository.setMark('A', mark);
+
+ let got = await repository.getMark('A');
+ expect(got).to.be.a('object');
+ expect(got.tabId).to.equal(1);
+
+ got = await repository.getMark('B');
+ expect(got).to.be.undefined;
+ });
+});