From 2ec912c262b51fe9523ebf74d5062d0b9bbdab71 Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Tue, 14 May 2019 20:28:22 +0900
Subject: Mark keys as a clean archtecture

---
 src/content/controllers/AddonEnabledController.ts | 19 +++++++++
 src/content/controllers/KeymapController.ts       | 15 +++++--
 src/content/controllers/MarkController.ts         | 16 +++++++
 src/content/controllers/MarkKeyController.ts      | 31 ++++++++++++++
 src/content/index.ts                              | 30 ++++++++++++-
 src/content/repositories/MarkKeyRepository.ts     | 52 +++++++++++++++++++++++
 src/content/usecases/MarkKeyUseCase.ts            | 36 ++++++++++++++++
 src/content/usecases/MarkUseCase.ts               |  8 +++-
 8 files changed, 200 insertions(+), 7 deletions(-)
 create mode 100644 src/content/controllers/AddonEnabledController.ts
 create mode 100644 src/content/controllers/MarkController.ts
 create mode 100644 src/content/controllers/MarkKeyController.ts
 create mode 100644 src/content/repositories/MarkKeyRepository.ts
 create mode 100644 src/content/usecases/MarkKeyUseCase.ts

(limited to 'src')

diff --git a/src/content/controllers/AddonEnabledController.ts b/src/content/controllers/AddonEnabledController.ts
new file mode 100644
index 0000000..4e19b6a
--- /dev/null
+++ b/src/content/controllers/AddonEnabledController.ts
@@ -0,0 +1,19 @@
+import * as messages from '../../shared/messages';
+import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
+
+export default class AddonEnabledController {
+  private addonEnabledUseCase: AddonEnabledUseCase;
+
+  constructor({
+    addonEnabledUseCase = new AddonEnabledUseCase(),
+  } = {}) {
+    this.addonEnabledUseCase = addonEnabledUseCase;
+  }
+
+  getAddonEnabled(
+    _message: messages.AddonEnabledQueryMessage,
+  ): Promise<boolean> {
+    let enabled = this.addonEnabledUseCase.getEnabled();
+    return Promise.resolve(enabled);
+  }
+}
diff --git a/src/content/controllers/KeymapController.ts b/src/content/controllers/KeymapController.ts
index 09e5b0c..b7a7bc2 100644
--- a/src/content/controllers/KeymapController.ts
+++ b/src/content/controllers/KeymapController.ts
@@ -7,6 +7,7 @@ import NavigateUseCase from '../usecases/NavigateUseCase';
 import FocusUseCase from '../usecases/FocusUseCase';
 import ClipboardUseCase from '../usecases/ClipboardUseCase';
 import BackgroundClient from '../client/BackgroundClient';
+import MarkKeyyUseCase from '../usecases/MarkKeyUseCase';
 import { Key } from '../../shared/utils/keys';
 
 export default class KeymapController {
@@ -26,6 +27,8 @@ export default class KeymapController {
 
   private backgroundClient: BackgroundClient;
 
+  private markKeyUseCase: MarkKeyyUseCase;
+
   constructor({
     keymapUseCase = new KeymapUseCase(),
     addonEnabledUseCase = new AddonEnabledUseCase(),
@@ -35,6 +38,7 @@ export default class KeymapController {
     focusUseCase = new FocusUseCase(),
     clipbaordUseCase = new ClipboardUseCase(),
     backgroundClient = new BackgroundClient(),
+    markKeyUseCase = new MarkKeyyUseCase(),
   } = {}) {
     this.keymapUseCase = keymapUseCase;
     this.addonEnabledUseCase = addonEnabledUseCase;
@@ -44,6 +48,7 @@ export default class KeymapController {
     this.focusUseCase = focusUseCase;
     this.clipbaordUseCase = clipbaordUseCase;
     this.backgroundClient = backgroundClient;
+    this.markKeyUseCase = markKeyUseCase;
   }
 
   // eslint-disable-next-line complexity, max-lines-per-function
@@ -98,10 +103,12 @@ export default class KeymapController {
     //     background: operation.background,
     //   }), '*');
     //   break;
-    // case operations.MARK_SET_PREFIX:
-    //   return markActions.startSet();
-    // case operations.MARK_JUMP_PREFIX:
-    //   return markActions.startJump();
+    case operations.MARK_SET_PREFIX:
+      this.markKeyUseCase.enableSetMode();
+      break;
+    case operations.MARK_JUMP_PREFIX:
+      this.markKeyUseCase.enableJumpMode();
+      break;
     case operations.NAVIGATE_HISTORY_PREV:
       this.navigateUseCase.openHistoryPrev();
       break;
diff --git a/src/content/controllers/MarkController.ts b/src/content/controllers/MarkController.ts
new file mode 100644
index 0000000..365794c
--- /dev/null
+++ b/src/content/controllers/MarkController.ts
@@ -0,0 +1,16 @@
+import * as messages from '../../shared/messages';
+import MarkUseCase from '../usecases/MarkUseCase';
+
+export default class MarkController {
+  private markUseCase: MarkUseCase;
+
+  constructor({
+    markUseCase = new MarkUseCase(),
+  } = {}) {
+    this.markUseCase = markUseCase;
+  }
+
+  scrollTo(message: messages.TabScrollToMessage) {
+    this.markUseCase.scroll(message.x, message.y);
+  }
+}
diff --git a/src/content/controllers/MarkKeyController.ts b/src/content/controllers/MarkKeyController.ts
new file mode 100644
index 0000000..9406fbf
--- /dev/null
+++ b/src/content/controllers/MarkKeyController.ts
@@ -0,0 +1,31 @@
+import MarkUseCase from '../usecases/MarkUseCase';
+import MarkKeyyUseCase from '../usecases/MarkKeyUseCase';
+import * as keys from '../../shared/utils/keys';
+
+export default class MarkKeyController {
+  private markUseCase: MarkUseCase;
+
+  private markKeyUseCase: MarkKeyyUseCase;
+
+  constructor({
+    markUseCase = new MarkUseCase(),
+    markKeyUseCase = new MarkKeyyUseCase(),
+  } = {}) {
+    this.markUseCase = markUseCase;
+    this.markKeyUseCase = markKeyUseCase;
+  }
+
+  press(key: keys.Key): boolean {
+    if (this.markKeyUseCase.isSetMode()) {
+      this.markUseCase.set(key.key);
+      this.markKeyUseCase.disableSetMode();
+      return true;
+    }
+    if (this.markKeyUseCase.isJumpMode()) {
+      this.markUseCase.jump(key.key);
+      this.markKeyUseCase.disableJumpMode();
+      return true;
+    }
+    return false;
+  }
+}
diff --git a/src/content/index.ts b/src/content/index.ts
index f983f9f..9b3d652 100644
--- a/src/content/index.ts
+++ b/src/content/index.ts
@@ -4,12 +4,15 @@ import consoleFrameStyle from './site-style';
 // import { newStore } from './store';
 import MessageListener from './MessageListener';
 import FindController from './controllers/FindController';
+import MarkController from './controllers/MarkController';
 import * as messages from '../shared/messages';
 import InputDriver from './InputDriver';
 import KeymapController from './controllers/KeymapController';
 import AddonEnabledUseCase from './usecases/AddonEnabledUseCase';
 import SettingUseCase from './usecases/SettingUseCase';
 import * as blacklists from '../shared/blacklists';
+import MarkKeyController from './controllers/MarkKeyController';
+import AddonEnabledController from './controllers/AddonEnabledController';
 
 // const store = newStore();
 
@@ -28,14 +31,28 @@ if (window.self === window.top) {
     }
     return undefined;
   });
+
+  let markController = new MarkController();
+  let addonEnabledController = new AddonEnabledController();
+
+  new MessageListener().onBackgroundMessage((message: messages.Message) => {
+    switch (message.type) {
+    case messages.ADDON_ENABLED_QUERY:
+      return addonEnabledController.getAddonEnabled(message);
+    case messages.TAB_SCROLL_TO:
+      return markController.scrollTo(message);
+    }
+    return undefined;
+  });
 } else {
   // new FrameContentComponent(window, store); // eslint-disable-line no-new
 }
 
 let keymapController = new KeymapController();
+let markKeyController = new MarkKeyController();
 let inputDriver = new InputDriver(document.body);
 // inputDriver.onKey(key => followSlaveController.pressKey(key));
-// inputDriver.onKey(key => markController.pressKey(key));
+inputDriver.onKey(key => markKeyController.press(key));
 inputDriver.onKey(key => keymapController.press(key));
 
 let style = window.document.createElement('style');
@@ -64,3 +81,14 @@ const reloadSettings = async() => {
   }
 };
 reloadSettings();
+
+new MessageListener().onBackgroundMessage((message: messages.Message): any => {
+  let addonEnabledUseCase = new AddonEnabledUseCase();
+
+  switch (message.type) {
+  case messages.SETTINGS_CHANGED:
+    return reloadSettings();
+  case messages.ADDON_TOGGLE_ENABLED:
+    return addonEnabledUseCase.toggle();
+  }
+});
diff --git a/src/content/repositories/MarkKeyRepository.ts b/src/content/repositories/MarkKeyRepository.ts
new file mode 100644
index 0000000..c24548a
--- /dev/null
+++ b/src/content/repositories/MarkKeyRepository.ts
@@ -0,0 +1,52 @@
+export default interface MarkKeyRepository {
+  isSetMode(): boolean;
+
+  enableSetMode(): void;
+
+  disabeSetMode(): void;
+
+  isJumpMode(): boolean;
+
+  enableJumpMode(): void;
+
+  disabeJumpMode(): void;
+
+  // eslint-disable-next-line semi
+}
+
+interface Mode {
+  setMode: boolean;
+  jumpMode: boolean;
+}
+
+let current: Mode = {
+  setMode: false,
+  jumpMode: false,
+};
+
+export class MarkKeyRepositoryImpl implements MarkKeyRepository {
+
+  isSetMode(): boolean {
+    return current.setMode;
+  }
+
+  enableSetMode(): void {
+    current.setMode = true;
+  }
+
+  disabeSetMode(): void {
+    current.setMode = false;
+  }
+
+  isJumpMode(): boolean {
+    return current.jumpMode;
+  }
+
+  enableJumpMode(): void {
+    current.jumpMode = true;
+  }
+
+  disabeJumpMode(): void {
+    current.jumpMode = false;
+  }
+}
diff --git a/src/content/usecases/MarkKeyUseCase.ts b/src/content/usecases/MarkKeyUseCase.ts
new file mode 100644
index 0000000..c0aa655
--- /dev/null
+++ b/src/content/usecases/MarkKeyUseCase.ts
@@ -0,0 +1,36 @@
+import MarkKeyRepository, { MarkKeyRepositoryImpl }
+  from '../repositories/MarkKeyRepository';
+
+export default class MarkKeyUseCase {
+  private repository: MarkKeyRepository;
+
+  constructor({
+    repository = new MarkKeyRepositoryImpl()
+  } = {}) {
+    this.repository = repository;
+  }
+
+  isSetMode(): boolean {
+    return this.repository.isSetMode();
+  }
+
+  isJumpMode(): boolean {
+    return this.repository.isJumpMode();
+  }
+
+  enableSetMode(): void {
+    this.repository.enableSetMode();
+  }
+
+  disableSetMode(): void {
+    this.repository.disabeSetMode();
+  }
+
+  enableJumpMode(): void {
+    this.repository.enableJumpMode();
+  }
+
+  disableJumpMode(): void {
+    this.repository.disabeJumpMode();
+  }
+}
diff --git a/src/content/usecases/MarkUseCase.ts b/src/content/usecases/MarkUseCase.ts
index ec63f2b..530f141 100644
--- a/src/content/usecases/MarkUseCase.ts
+++ b/src/content/usecases/MarkUseCase.ts
@@ -51,11 +51,15 @@ export default class MarkUseCase {
       if (!pos) {
         throw new Error('Mark is not set');
       }
-      let smooth = this.settingRepository.get().properties.smoothscroll;
-      this.scrollPresenter.scrollTo(pos.x, pos.y, smooth);
+      this.scroll(pos.x, pos.y);
     }
   }
 
+  scroll(x: number, y: number): void {
+    let smooth = this.settingRepository.get().properties.smoothscroll;
+    this.scrollPresenter.scrollTo(x, y, smooth);
+  }
+
   private globalKey(key: string) {
     return (/^[A-Z0-9]$/).test(key);
   }
-- 
cgit v1.2.3