Merge pull request #588 from ueokande/tsyringe

Use tsyringe for DI container
jh-changes
Shin'ya Ueoka 6 years ago committed by GitHub
commit c1f64927b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .eslintrc
  2. 1288
      package-lock.json
  3. 13
      package.json
  4. 35
      src/background/Application.ts
  5. 8
      src/background/controllers/AddonEnabledController.ts
  6. 13
      src/background/controllers/CommandController.ts
  7. 9
      src/background/controllers/FindController.ts
  8. 9
      src/background/controllers/LinkController.ts
  9. 9
      src/background/controllers/MarkController.ts
  10. 25
      src/background/controllers/OperationController.ts
  11. 13
      src/background/controllers/SettingController.ts
  12. 9
      src/background/controllers/VersionController.ts
  13. 27
      src/background/index.ts
  14. 2
      src/background/infrastructures/ConsoleClient.ts
  15. 2
      src/background/infrastructures/ContentMessageClient.ts
  16. 34
      src/background/infrastructures/ContentMessageListener.ts
  17. 3
      src/background/presenters/IndicatorPresenter.ts
  18. 3
      src/background/presenters/NotifyPresenter.ts
  19. 2
      src/background/presenters/TabPresenter.ts
  20. 3
      src/background/presenters/WindowPresenter.ts
  21. 3
      src/background/repositories/BookmarkRepository.ts
  22. 2
      src/background/repositories/BrowserSettingRepository.ts
  23. 3
      src/background/repositories/CompletionsRepository.ts
  24. 2
      src/background/repositories/FindRepository.ts
  25. 2
      src/background/repositories/MarkRepository.ts
  26. 2
      src/background/repositories/PersistentSettingRepository.ts
  27. 2
      src/background/repositories/SettingRepository.ts
  28. 20
      src/background/usecases/AddonEnabledUseCase.ts
  29. 30
      src/background/usecases/CommandUseCase.ts
  30. 17
      src/background/usecases/CompletionsUseCase.ts
  31. 12
      src/background/usecases/ConsoleUseCase.ts
  32. 17
      src/background/usecases/FindUseCase.ts
  33. 9
      src/background/usecases/LinkUseCase.ts
  34. 21
      src/background/usecases/MarkUseCase.ts
  35. 16
      src/background/usecases/SettingUseCase.ts
  36. 9
      src/background/usecases/TabSelectUseCase.ts
  37. 13
      src/background/usecases/TabUseCase.ts
  38. 13
      src/background/usecases/VersionUseCase.ts
  39. 9
      src/background/usecases/ZoomUseCase.ts
  40. 111
      src/content/Application.ts
  41. 2
      src/content/MessageListener.ts
  42. 2
      src/content/client/BackgroundClient.ts
  43. 13
      src/content/client/FollowSlaveClientFactory.ts
  44. 11
      src/content/controllers/AddonEnabledController.ts
  45. 11
      src/content/controllers/ConsoleFrameController.ts
  46. 11
      src/content/controllers/FindController.ts
  47. 11
      src/content/controllers/FollowKeyController.ts
  48. 11
      src/content/controllers/FollowMasterController.ts
  49. 11
      src/content/controllers/FollowSlaveController.ts
  50. 59
      src/content/controllers/KeymapController.ts
  51. 11
      src/content/controllers/MarkController.ts
  52. 16
      src/content/controllers/MarkKeyController.ts
  53. 15
      src/content/controllers/SettingController.ts
  54. 54
      src/content/di.ts
  55. 16
      src/content/index.ts
  56. 97
      src/content/routes.ts
  57. 22
      src/content/usecases/AddonEnabledUseCase.ts
  58. 37
      src/content/usecases/ClipboardUseCase.ts
  59. 15
      src/content/usecases/ConsoleFrameUseCase.ts
  60. 14
      src/content/usecases/FindSlaveUseCase.ts
  61. 35
      src/content/usecases/FindUseCase.ts
  62. 14
      src/content/usecases/FocusUseCase.ts
  63. 50
      src/content/usecases/FollowMasterUseCase.ts
  64. 38
      src/content/usecases/FollowSlaveUseCase.ts
  65. 33
      src/content/usecases/KeymapUseCase.ts
  66. 14
      src/content/usecases/MarkKeyUseCase.ts
  67. 46
      src/content/usecases/MarkUseCase.ts
  68. 15
      src/content/usecases/NavigateUseCase.ts
  69. 22
      src/content/usecases/ScrollUseCase.ts
  70. 21
      src/content/usecases/SettingUseCase.ts
  71. 2
      test/content/usecases/AddonEnabledUseCase.test.ts
  72. 8
      test/content/usecases/ClipboardUseCase.test.ts
  73. 2
      test/content/usecases/FindUseCase.test.ts
  74. 11
      test/content/usecases/MarkUseCase.test.ts
  75. 2
      test/content/usecases/SettingUseCaase.test.ts
  76. 6
      test/main.ts
  77. 6
      tsconfig.json
  78. 19
      webpack.config.js

@ -36,7 +36,7 @@
"jsx-quotes": ["error", "prefer-single"], "jsx-quotes": ["error", "prefer-single"],
"max-classes-per-file": "off", "max-classes-per-file": "off",
"max-lines": "off", "max-lines": "off",
"max-params": ["error", 5], "max-params": ["error", 10],
"max-statements": ["error", 15], "max-statements": ["error", 15],
"multiline-comment-style": "off", "multiline-comment-style": "off",
"multiline-ternary": "off", "multiline-ternary": "off",
@ -57,6 +57,7 @@
"no-undef-init": "off", "no-undef-init": "off",
"no-unused-vars": "off", "no-unused-vars": "off",
"no-use-before-define": "off", "no-use-before-define": "off",
"no-useless-constructor": "off",
"no-warning-comments": "off", "no-warning-comments": "off",
"object-curly-newline": ["error", { "consistent": true }], "object-curly-newline": ["error", { "consistent": true }],
"object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], "object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }],

1288
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -6,7 +6,7 @@
"build": "NODE_ENV=production webpack --mode production --progress --display-error-details", "build": "NODE_ENV=production webpack --mode production --progress --display-error-details",
"package": "npm run build && script/package", "package": "npm run build && script/package",
"lint": "eslint --ext .js,.jsx,.ts,.tsx src", "lint": "eslint --ext .js,.jsx,.ts,.tsx src",
"type-checks": "tsc", "type-checks": "tsc --noEmit",
"test": "karma start", "test": "karma start",
"test:e2e": "mocha --timeout 8000 e2e" "test:e2e": "mocha --timeout 8000 e2e"
}, },
@ -21,11 +21,6 @@
}, },
"homepage": "https://github.com/ueokande/vim-vixen", "homepage": "https://github.com/ueokande/vim-vixen",
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.4",
"@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@types/chai": "^4.1.7", "@types/chai": "^4.1.7",
"@types/mocha": "^5.2.6", "@types/mocha": "^5.2.6",
"@types/prop-types": "^15.7.1", "@types/prop-types": "^15.7.1",
@ -34,8 +29,6 @@
"@types/react-redux": "^7.0.8", "@types/react-redux": "^7.0.8",
"@types/redux-promise": "^0.5.28", "@types/redux-promise": "^0.5.28",
"@typescript-eslint/eslint-plugin": "^1.7.0", "@typescript-eslint/eslint-plugin": "^1.7.0",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.5",
"chai": "^4.2.0", "chai": "^4.2.0",
"css-loader": "^2.1.1", "css-loader": "^2.1.1",
"eslint": "^5.16.0", "eslint": "^5.16.0",
@ -43,7 +36,6 @@
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"jszip": "^3.2.1", "jszip": "^3.2.1",
"karma": "^4.1.0", "karma": "^4.1.0",
"karma-babel-preprocessor": "^8.0.0-beta.0",
"karma-firefox-launcher": "^1.1.0", "karma-firefox-launcher": "^1.1.0",
"karma-html2js-preprocessor": "^1.1.0", "karma-html2js-preprocessor": "^1.1.0",
"karma-mocha": "^1.3.0", "karma-mocha": "^1.3.0",
@ -60,9 +52,12 @@
"react-test-renderer": "^16.8.6", "react-test-renderer": "^16.8.6",
"redux": "^4.0.1", "redux": "^4.0.1",
"redux-promise": "^0.6.0", "redux-promise": "^0.6.0",
"reflect-metadata": "^0.1.13",
"sass-loader": "^7.1.0", "sass-loader": "^7.1.0",
"sinon-chrome": "^3.0.1", "sinon-chrome": "^3.0.1",
"style-loader": "^0.23.1", "style-loader": "^0.23.1",
"ts-loader": "^6.0.1",
"tsyringe": "^3.2.0",
"typescript": "^3.4.5", "typescript": "^3.4.5",
"web-ext-types": "^3.1.0", "web-ext-types": "^3.1.0",
"webextensions-api-fake": "^0.7.4", "webextensions-api-fake": "^0.7.4",

@ -0,0 +1,35 @@
import { injectable } from 'tsyringe';
import ContentMessageListener from './infrastructures/ContentMessageListener';
import SettingController from './controllers/SettingController';
import VersionController from './controllers/VersionController';
@injectable()
export default class Application {
constructor(
private contentMessageListener: ContentMessageListener,
private settingController: SettingController,
private versionController: VersionController,
) {
}
run() {
this.settingController.reload();
browser.runtime.onInstalled.addListener((details) => {
if (details.reason !== 'install' && details.reason !== 'update') {
return;
}
this.versionController.notify();
});
this.contentMessageListener.run();
browser.storage.onChanged.addListener((changes, area) => {
if (area !== 'local') {
return;
}
if (changes.settings) {
this.settingController.reload();
}
});
}
}

@ -1,10 +1,12 @@
import { injectable } from 'tsyringe';
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase'; import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
@injectable()
export default class AddonEnabledController { export default class AddonEnabledController {
private addonEnabledUseCase: AddonEnabledUseCase;
constructor() { constructor(
this.addonEnabledUseCase = new AddonEnabledUseCase(); private addonEnabledUseCase: AddonEnabledUseCase,
) {
} }
indicate(enabled: boolean): Promise<any> { indicate(enabled: boolean): Promise<any> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import CompletionsUseCase from '../usecases/CompletionsUseCase'; import CompletionsUseCase from '../usecases/CompletionsUseCase';
import CommandUseCase from '../usecases/CommandUseCase'; import CommandUseCase from '../usecases/CommandUseCase';
import CompletionGroup from '../domains/CompletionGroup'; import CompletionGroup from '../domains/CompletionGroup';
@ -7,14 +8,12 @@ const trimStart = (str: string): string => {
return str.replace(/^\s+/, ''); return str.replace(/^\s+/, '');
}; };
@injectable()
export default class CommandController { export default class CommandController {
private completionsUseCase: CompletionsUseCase; constructor(
private completionsUseCase: CompletionsUseCase,
private commandIndicator: CommandUseCase; private commandIndicator: CommandUseCase,
) {
constructor() {
this.completionsUseCase = new CompletionsUseCase();
this.commandIndicator = new CommandUseCase();
} }
getCompletions(line: string): Promise<CompletionGroup[]> { getCompletions(line: string): Promise<CompletionGroup[]> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import FindUseCase from '../usecases/FindUseCase'; import FindUseCase from '../usecases/FindUseCase';
@injectable()
export default class FindController { export default class FindController {
private findUseCase: FindUseCase; constructor(
private findUseCase: FindUseCase,
constructor() { ) {
this.findUseCase = new FindUseCase();
} }
getKeyword(): Promise<string> { getKeyword(): Promise<string> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import LinkUseCase from '../usecases/LinkUseCase'; import LinkUseCase from '../usecases/LinkUseCase';
@injectable()
export default class LinkController { export default class LinkController {
private linkUseCase: LinkUseCase; constructor(
private linkUseCase: LinkUseCase,
constructor() { ) {
this.linkUseCase = new LinkUseCase();
} }
openToTab(url: string, tabId: number): Promise<void> { openToTab(url: string, tabId: number): Promise<void> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import MarkUseCase from '../usecases/MarkUseCase'; import MarkUseCase from '../usecases/MarkUseCase';
@injectable()
export default class MarkController { export default class MarkController {
private markUseCase: MarkUseCase; constructor(
private markUseCase: MarkUseCase,
constructor() { ) {
this.markUseCase = new MarkUseCase();
} }
setGlobal(key: string, x: number, y: number): Promise<any> { setGlobal(key: string, x: number, y: number): Promise<any> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as operations from '../../shared/operations'; import * as operations from '../../shared/operations';
import FindUseCase from '../usecases/FindUseCase'; import FindUseCase from '../usecases/FindUseCase';
import ConsoleUseCase from '../usecases/ConsoleUseCase'; import ConsoleUseCase from '../usecases/ConsoleUseCase';
@ -5,23 +6,15 @@ import TabUseCase from '../usecases/TabUseCase';
import TabSelectUseCase from '../usecases/TabSelectUseCase'; import TabSelectUseCase from '../usecases/TabSelectUseCase';
import ZoomUseCase from '../usecases/ZoomUseCase'; import ZoomUseCase from '../usecases/ZoomUseCase';
@injectable()
export default class OperationController { export default class OperationController {
private findUseCase: FindUseCase; constructor(
private findUseCase: FindUseCase,
private consoleUseCase: ConsoleUseCase; private consoleUseCase: ConsoleUseCase,
private tabUseCase: TabUseCase,
private tabUseCase: TabUseCase; private tabSelectUseCase: TabSelectUseCase,
private zoomUseCase: ZoomUseCase,
private tabSelectUseCase: TabSelectUseCase; ) {
private zoomUseCase: ZoomUseCase;
constructor() {
this.findUseCase = new FindUseCase();
this.consoleUseCase = new ConsoleUseCase();
this.tabUseCase = new TabUseCase();
this.tabSelectUseCase = new TabSelectUseCase();
this.zoomUseCase = new ZoomUseCase();
} }
// eslint-disable-next-line complexity, max-lines-per-function // eslint-disable-next-line complexity, max-lines-per-function

@ -1,15 +1,14 @@
import { injectable } from 'tsyringe';
import SettingUseCase from '../usecases/SettingUseCase'; import SettingUseCase from '../usecases/SettingUseCase';
import ContentMessageClient from '../infrastructures/ContentMessageClient'; import ContentMessageClient from '../infrastructures/ContentMessageClient';
import Settings from '../../shared/Settings'; import Settings from '../../shared/Settings';
@injectable()
export default class SettingController { export default class SettingController {
private settingUseCase: SettingUseCase; constructor(
private settingUseCase: SettingUseCase,
private contentMessageClient: ContentMessageClient; private contentMessageClient: ContentMessageClient,
) {
constructor() {
this.settingUseCase = new SettingUseCase();
this.contentMessageClient = new ContentMessageClient();
} }
getSetting(): Promise<Settings> { getSetting(): Promise<Settings> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import VersionUseCase from '../usecases/VersionUseCase'; import VersionUseCase from '../usecases/VersionUseCase';
@injectable()
export default class VersionController { export default class VersionController {
private versionUseCase: VersionUseCase; constructor(
private versionUseCase: VersionUseCase,
constructor() { ) {
this.versionUseCase = new VersionUseCase();
} }
notify(): Promise<void> { notify(): Promise<void> {

@ -1,23 +1,6 @@
import ContentMessageListener from './infrastructures/ContentMessageListener'; import 'reflect-metadata';
import SettingController from './controllers/SettingController'; import { container } from 'tsyringe';
import VersionController from './controllers/VersionController'; import Application from './Application';
let settingController = new SettingController(); let app = container.resolve(Application);
settingController.reload(); app.run();
browser.runtime.onInstalled.addListener((details) => {
if (details.reason !== 'install' && details.reason !== 'update') {
return;
}
new VersionController().notify();
});
new ContentMessageListener().run();
browser.storage.onChanged.addListener((changes, area) => {
if (area !== 'local') {
return;
}
if (changes.settings) {
settingController.reload();
}
});

@ -1,5 +1,7 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
@injectable()
export default class ConsoleClient { export default class ConsoleClient {
showCommand(tabId: number, command: string): Promise<any> { showCommand(tabId: number, command: string): Promise<any> {
return browser.tabs.sendMessage(tabId, { return browser.tabs.sendMessage(tabId, {

@ -1,5 +1,7 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
@injectable()
export default class ContentMessageClient { export default class ContentMessageClient {
async broadcastSettingsChanged(): Promise<void> { async broadcastSettingsChanged(): Promise<void> {
let tabs = await browser.tabs.query({}); let tabs = await browser.tabs.query({});

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
import CompletionGroup from '../domains/CompletionGroup'; import CompletionGroup from '../domains/CompletionGroup';
import CommandController from '../controllers/CommandController'; import CommandController from '../controllers/CommandController';
@ -8,32 +9,19 @@ import LinkController from '../controllers/LinkController';
import OperationController from '../controllers/OperationController'; import OperationController from '../controllers/OperationController';
import MarkController from '../controllers/MarkController'; import MarkController from '../controllers/MarkController';
@injectable()
export default class ContentMessageListener { export default class ContentMessageListener {
private settingController: SettingController;
private commandController: CommandController;
private findController: FindController;
private addonEnabledController: AddonEnabledController;
private linkController: LinkController;
private backgroundOperationController: OperationController;
private markController: MarkController;
private consolePorts: {[tabId: number]: browser.runtime.Port}; private consolePorts: {[tabId: number]: browser.runtime.Port};
constructor() { constructor(
this.settingController = new SettingController(); private settingController: SettingController,
this.commandController = new CommandController(); private commandController: CommandController,
this.findController = new FindController(); private findController: FindController,
this.addonEnabledController = new AddonEnabledController(); private addonEnabledController: AddonEnabledController,
this.linkController = new LinkController(); private linkController: LinkController,
this.backgroundOperationController = new OperationController(); private backgroundOperationController: OperationController,
this.markController = new MarkController(); private markController: MarkController,
) {
this.consolePorts = {}; this.consolePorts = {};
} }

@ -1,3 +1,6 @@
import { injectable } from 'tsyringe';
@injectable()
export default class IndicatorPresenter { export default class IndicatorPresenter {
indicate(enabled: boolean): Promise<void> { indicate(enabled: boolean): Promise<void> {
let path = enabled let path = enabled

@ -1,5 +1,8 @@
import { injectable } from 'tsyringe';
const NOTIFICATION_ID = 'vimvixen-update'; const NOTIFICATION_ID = 'vimvixen-update';
@injectable()
export default class NotifyPresenter { export default class NotifyPresenter {
async notify( async notify(
title: string, title: string,

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage'; import MemoryStorage from '../infrastructures/MemoryStorage';
const CURRENT_SELECTED_KEY = 'tabs.current.selected'; const CURRENT_SELECTED_KEY = 'tabs.current.selected';
@ -5,6 +6,7 @@ const LAST_SELECTED_KEY = 'tabs.last.selected';
type Tab = browser.tabs.Tab; type Tab = browser.tabs.Tab;
@injectable()
export default class TabPresenter { export default class TabPresenter {
open(url: string, tabId?: number): Promise<Tab> { open(url: string, tabId?: number): Promise<Tab> {
return browser.tabs.update(tabId, { url }); return browser.tabs.update(tabId, { url });

@ -1,3 +1,6 @@
import { injectable } from 'tsyringe';
@injectable()
export default class WindowPresenter { export default class WindowPresenter {
create(url: string): Promise<browser.windows.Window> { create(url: string): Promise<browser.windows.Window> {
return browser.windows.create({ url }); return browser.windows.create({ url });

@ -1,3 +1,6 @@
import { injectable } from 'tsyringe';
@injectable()
export default class BookmarkRepository { export default class BookmarkRepository {
async create( async create(
title: string, url: string title: string, url: string

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as urls from '../../shared/urls'; import * as urls from '../../shared/urls';
declare namespace browser.browserSettings.homepageOverride { declare namespace browser.browserSettings.homepageOverride {
@ -16,6 +17,7 @@ declare namespace browser.browserSettings.homepageOverride {
function get(param: object): Promise<BrowserSettings>; function get(param: object): Promise<BrowserSettings>;
} }
@injectable()
export default class BrowserSettingRepository { export default class BrowserSettingRepository {
async getHomepageUrls(): Promise<string[]> { async getHomepageUrls(): Promise<string[]> {
let { value } = await browser.browserSettings.homepageOverride.get({}); let { value } = await browser.browserSettings.homepageOverride.get({});

@ -1,6 +1,9 @@
import { injectable } from 'tsyringe';
type Tab = browser.tabs.Tab; type Tab = browser.tabs.Tab;
type BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; type BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
@injectable()
export default class CompletionsRepository { export default class CompletionsRepository {
async queryBookmarks(keywords: string): Promise<BookmarkTreeNode[]> { async queryBookmarks(keywords: string): Promise<BookmarkTreeNode[]> {
let items = await browser.bookmarks.search({ query: keywords }); let items = await browser.bookmarks.search({ query: keywords });

@ -1,7 +1,9 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage'; import MemoryStorage from '../infrastructures/MemoryStorage';
const FIND_KEYWORD_KEY = 'find-keyword'; const FIND_KEYWORD_KEY = 'find-keyword';
@injectable()
export default class FindRepository { export default class FindRepository {
private cache: MemoryStorage; private cache: MemoryStorage;

@ -1,8 +1,10 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage'; import MemoryStorage from '../infrastructures/MemoryStorage';
import GlobalMark from '../domains/GlobalMark'; import GlobalMark from '../domains/GlobalMark';
const MARK_KEY = 'mark'; const MARK_KEY = 'mark';
@injectable()
export default class MarkRepository { export default class MarkRepository {
private cache: MemoryStorage; private cache: MemoryStorage;

@ -1,5 +1,7 @@
import { injectable } from 'tsyringe';
import SettingData from '../../shared/SettingData'; import SettingData from '../../shared/SettingData';
@injectable()
export default class SettingRepository { export default class SettingRepository {
async load(): Promise<SettingData | null> { async load(): Promise<SettingData | null> {
let { settings } = await browser.storage.local.get('settings'); let { settings } = await browser.storage.local.get('settings');

@ -1,9 +1,11 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage'; import MemoryStorage from '../infrastructures/MemoryStorage';
import Settings from '../../shared/Settings'; import Settings from '../../shared/Settings';
import * as PropertyDefs from '../../shared/property-defs'; import * as PropertyDefs from '../../shared/property-defs';
const CACHED_SETTING_KEY = 'setting'; const CACHED_SETTING_KEY = 'setting';
@injectable()
export default class SettingRepository { export default class SettingRepository {
private cache: MemoryStorage; private cache: MemoryStorage;

@ -1,27 +1,21 @@
import { injectable } from 'tsyringe';
import IndicatorPresenter from '../presenters/IndicatorPresenter'; import IndicatorPresenter from '../presenters/IndicatorPresenter';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
import ContentMessageClient from '../infrastructures/ContentMessageClient'; import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class AddonEnabledUseCase { export default class AddonEnabledUseCase {
private indicatorPresentor: IndicatorPresenter; constructor(
private indicatorPresentor: IndicatorPresenter,
private tabPresenter: TabPresenter; private tabPresenter: TabPresenter,
private contentMessageClient: ContentMessageClient,
private contentMessageClient: ContentMessageClient; ) {
constructor() {
this.indicatorPresentor = new IndicatorPresenter();
this.indicatorPresentor.onClick((tab) => { this.indicatorPresentor.onClick((tab) => {
if (tab.id) { if (tab.id) {
this.onIndicatorClick(tab.id); this.onIndicatorClick(tab.id);
} }
}); });
this.tabPresenter = new TabPresenter();
this.tabPresenter.onSelected(info => this.onTabSelected(info.tabId)); this.tabPresenter.onSelected(info => this.onTabSelected(info.tabId));
this.contentMessageClient = new ContentMessageClient();
} }
indicate(enabled: boolean): Promise<void> { indicate(enabled: boolean): Promise<void> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as parsers from './parsers'; import * as parsers from './parsers';
import * as urls from '../../shared/urls'; import * as urls from '../../shared/urls';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
@ -7,27 +8,16 @@ import BookmarkRepository from '../repositories/BookmarkRepository';
import ConsoleClient from '../infrastructures/ConsoleClient'; import ConsoleClient from '../infrastructures/ConsoleClient';
import ContentMessageClient from '../infrastructures/ContentMessageClient'; import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class CommandIndicator { export default class CommandIndicator {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
private windowPresenter: WindowPresenter; private windowPresenter: WindowPresenter,
private settingRepository: SettingRepository,
private settingRepository: SettingRepository; private bookmarkRepository: BookmarkRepository,
private consoleClient: ConsoleClient,
private bookmarkRepository: BookmarkRepository; private contentMessageClient: ContentMessageClient,
) {
private consoleClient: ConsoleClient;
private contentMessageClient: ContentMessageClient;
constructor() {
this.tabPresenter = new TabPresenter();
this.windowPresenter = new WindowPresenter();
this.settingRepository = new SettingRepository();
this.bookmarkRepository = new BookmarkRepository();
this.consoleClient = new ConsoleClient();
this.contentMessageClient = new ContentMessageClient();
} }
async open(keywords: string): Promise<browser.tabs.Tab> { async open(keywords: string): Promise<browser.tabs.Tab> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import CompletionGroup from '../domains/CompletionGroup'; import CompletionGroup from '../domains/CompletionGroup';
import CommandDocs from '../domains/CommandDocs'; import CommandDocs from '../domains/CommandDocs';
import CompletionsRepository from '../repositories/CompletionsRepository'; import CompletionsRepository from '../repositories/CompletionsRepository';
@ -11,17 +12,13 @@ const COMPLETION_ITEM_LIMIT = 10;
type Tab = browser.tabs.Tab; type Tab = browser.tabs.Tab;
type HistoryItem = browser.history.HistoryItem; type HistoryItem = browser.history.HistoryItem;
@injectable()
export default class CompletionsUseCase { export default class CompletionsUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
private completionsRepository: CompletionsRepository; private completionsRepository: CompletionsRepository,
private settingRepository: SettingRepository,
private settingRepository: SettingRepository; ) {
constructor() {
this.tabPresenter = new TabPresenter();
this.completionsRepository = new CompletionsRepository();
this.settingRepository = new SettingRepository();
} }
queryConsoleCommand(prefix: string): Promise<CompletionGroup[]> { queryConsoleCommand(prefix: string): Promise<CompletionGroup[]> {

@ -1,14 +1,14 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
import ConsoleClient from '../infrastructures/ConsoleClient'; import ConsoleClient from '../infrastructures/ConsoleClient';
@injectable()
export default class ConsoleUseCase { export default class ConsoleUseCase {
private tabPresenter: TabPresenter;
private consoleClient: ConsoleClient; constructor(
private tabPresenter: TabPresenter,
constructor() { private consoleClient: ConsoleClient,
this.tabPresenter = new TabPresenter(); ) {
this.consoleClient = new ConsoleClient();
} }
async showCommand(): Promise<any> { async showCommand(): Promise<any> {

@ -1,18 +1,15 @@
import { injectable } from 'tsyringe';
import FindRepository from '../repositories/FindRepository'; import FindRepository from '../repositories/FindRepository';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
import ConsoleClient from '../infrastructures/ConsoleClient'; import ConsoleClient from '../infrastructures/ConsoleClient';
@injectable()
export default class FindUseCase { export default class FindUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
private findRepository: FindRepository; private findRepository: FindRepository,
private consoleClient: ConsoleClient,
private consoleClient: ConsoleClient; ) {
constructor() {
this.tabPresenter = new TabPresenter();
this.findRepository = new FindRepository();
this.consoleClient = new ConsoleClient();
} }
getKeyword(): Promise<string> { getKeyword(): Promise<string> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class LinkUseCase { export default class LinkUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
constructor() { ) {
this.tabPresenter = new TabPresenter();
} }
openToTab(url: string, tabId: number): Promise<any> { openToTab(url: string, tabId: number): Promise<any> {

@ -1,22 +1,17 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
import MarkRepository from '../repositories/MarkRepository'; import MarkRepository from '../repositories/MarkRepository';
import ConsoleClient from '../infrastructures/ConsoleClient'; import ConsoleClient from '../infrastructures/ConsoleClient';
import ContentMessageClient from '../infrastructures/ContentMessageClient'; import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class MarkUseCase { export default class MarkUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
private markRepository: MarkRepository; private markRepository: MarkRepository,
private consoleClient: ConsoleClient,
private consoleClient: ConsoleClient; private contentMessageClient: ContentMessageClient,
) {
private contentMessageClient: ContentMessageClient;
constructor() {
this.tabPresenter = new TabPresenter();
this.markRepository = new MarkRepository();
this.consoleClient = new ConsoleClient();
this.contentMessageClient = new ContentMessageClient();
} }
async setGlobal(key: string, x: number, y: number): Promise<any> { async setGlobal(key: string, x: number, y: number): Promise<any> {

@ -1,17 +1,17 @@
// eslint-disable-next-line max-len import { injectable } from 'tsyringe';
import PersistentSettingRepository from '../repositories/PersistentSettingRepository'; import PersistentSettingRepository
from '../repositories/PersistentSettingRepository';
import SettingRepository from '../repositories/SettingRepository'; import SettingRepository from '../repositories/SettingRepository';
import { DefaultSettingData } from '../../shared/SettingData'; import { DefaultSettingData } from '../../shared/SettingData';
import Settings from '../../shared/Settings'; import Settings from '../../shared/Settings';
@injectable()
export default class SettingUseCase { export default class SettingUseCase {
private persistentSettingRepository: PersistentSettingRepository;
private settingRepository: SettingRepository; constructor(
private persistentSettingRepository: PersistentSettingRepository,
constructor() { private settingRepository: SettingRepository,
this.persistentSettingRepository = new PersistentSettingRepository(); ) {
this.settingRepository = new SettingRepository();
} }
get(): Promise<Settings> { get(): Promise<Settings> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class TabSelectUseCase { export default class TabSelectUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
constructor() { ) {
this.tabPresenter = new TabPresenter();
} }
async selectPrev(count: number): Promise<any> { async selectPrev(count: number): Promise<any> {

@ -1,14 +1,13 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
import BrowserSettingRepository from '../repositories/BrowserSettingRepository'; import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
@injectable()
export default class TabUseCase { export default class TabUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
private browserSettingRepository: BrowserSettingRepository; private browserSettingRepository: BrowserSettingRepository,
) {
constructor() {
this.tabPresenter = new TabPresenter();
this.browserSettingRepository = new BrowserSettingRepository();
} }
async close(force: boolean): Promise<any> { async close(force: boolean): Promise<any> {

@ -1,14 +1,13 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
import NotifyPresenter from '../presenters/NotifyPresenter'; import NotifyPresenter from '../presenters/NotifyPresenter';
@injectable()
export default class VersionUseCase { export default class VersionUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
private notifyPresenter: NotifyPresenter; private notifyPresenter: NotifyPresenter,
) {
constructor() {
this.tabPresenter = new TabPresenter();
this.notifyPresenter = new NotifyPresenter();
} }
notify(): Promise<void> { notify(): Promise<void> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter'; import TabPresenter from '../presenters/TabPresenter';
const ZOOM_SETTINGS: number[] = [ const ZOOM_SETTINGS: number[] = [
@ -5,11 +6,11 @@ const ZOOM_SETTINGS: number[] = [
1.10, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00 1.10, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00
]; ];
@injectable()
export default class ZoomUseCase { export default class ZoomUseCase {
private tabPresenter: TabPresenter; constructor(
private tabPresenter: TabPresenter,
constructor() { ) {
this.tabPresenter = new TabPresenter();
} }
async zoomIn(): Promise<any> { async zoomIn(): Promise<any> {

@ -0,0 +1,111 @@
import { injectable } from 'tsyringe';
import MessageListener from './MessageListener';
import FindController from './controllers/FindController';
import MarkController from './controllers/MarkController';
import FollowMasterController from './controllers/FollowMasterController';
import FollowSlaveController from './controllers/FollowSlaveController';
import FollowKeyController from './controllers/FollowKeyController';
import InputDriver from './InputDriver';
import KeymapController from './controllers/KeymapController';
import AddonEnabledUseCase from './usecases/AddonEnabledUseCase';
import MarkKeyController from './controllers/MarkKeyController';
import AddonEnabledController from './controllers/AddonEnabledController';
import SettingController from './controllers/SettingController';
import ConsoleFrameController from './controllers/ConsoleFrameController';
import * as messages from '../shared/messages';
type Message = messages.Message;
@injectable()
export default class Application {
// eslint-disable-next-line max-params
constructor(
private messageListener: MessageListener,
private findController: FindController,
private markController: MarkController,
private followMasterController: FollowMasterController,
private followSlaveController: FollowSlaveController,
private followKeyController: FollowKeyController,
private keymapController: KeymapController,
private addonEnabledUseCase: AddonEnabledUseCase,
private markKeyController: MarkKeyController,
private addonEnabledController: AddonEnabledController,
private settingController: SettingController,
private consoleFrameController: ConsoleFrameController,
) {
}
run() {
this.routeCommonComponents();
if (window.self === window.top) {
this.routeMasterComponents();
}
}
private routeMasterComponents() {
this.messageListener.onWebMessage((msg: Message, sender: Window) => {
switch (msg.type) {
case messages.CONSOLE_ENTER_FIND:
return this.findController.start(msg);
case messages.FIND_NEXT:
return this.findController.next(msg);
case messages.FIND_PREV:
return this.findController.prev(msg);
case messages.CONSOLE_UNFOCUS:
return this.consoleFrameController.unfocus(msg);
case messages.FOLLOW_START:
return this.followMasterController.followStart(msg);
case messages.FOLLOW_RESPONSE_COUNT_TARGETS:
return this.followMasterController.responseCountTargets(msg, sender);
case messages.FOLLOW_KEY_PRESS:
return this.followMasterController.keyPress(msg);
}
return undefined;
});
this.messageListener.onBackgroundMessage((msg: Message) => {
switch (msg.type) {
case messages.ADDON_ENABLED_QUERY:
return this.addonEnabledController.getAddonEnabled(msg);
case messages.TAB_SCROLL_TO:
return this.markController.scrollTo(msg);
}
return undefined;
});
}
private routeCommonComponents() {
this.messageListener.onWebMessage((msg: Message) => {
switch (msg.type) {
case messages.FOLLOW_REQUEST_COUNT_TARGETS:
return this.followSlaveController.countTargets(msg);
case messages.FOLLOW_CREATE_HINTS:
return this.followSlaveController.createHints(msg);
case messages.FOLLOW_SHOW_HINTS:
return this.followSlaveController.showHints(msg);
case messages.FOLLOW_ACTIVATE:
return this.followSlaveController.activate(msg);
case messages.FOLLOW_REMOVE_HINTS:
return this.followSlaveController.clear(msg);
}
return undefined;
});
this.messageListener.onBackgroundMessage((msg: Message): any => {
switch (msg.type) {
case messages.SETTINGS_CHANGED:
return this.settingController.reloadSettings(msg);
case messages.ADDON_TOGGLE_ENABLED:
return this.addonEnabledUseCase.toggle();
}
});
let inputDriver = new InputDriver(window.document.body);
inputDriver.onKey(key => this.followKeyController.press(key));
inputDriver.onKey(key => this.markKeyController.press(key));
inputDriver.onKey(key => this.keymapController.press(key));
this.settingController.initSettings();
}
}

@ -1,7 +1,9 @@
import { injectable } from 'tsyringe';
import { Message, valueOf } from '../shared/messages'; import { Message, valueOf } from '../shared/messages';
export type WebExtMessageSender = browser.runtime.MessageSender; export type WebExtMessageSender = browser.runtime.MessageSender;
@injectable()
export default class MessageListener { export default class MessageListener {
onWebMessage( onWebMessage(
listener: (msg: Message, sender: Window) => void, listener: (msg: Message, sender: Window) => void,

@ -1,6 +1,8 @@
import { injectable } from 'tsyringe';
import * as operations from '../../shared/operations'; import * as operations from '../../shared/operations';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
@injectable()
export default class BackgroundClient { export default class BackgroundClient {
execBackgroundOp(op: operations.Operation): Promise<void> { execBackgroundOp(op: operations.Operation): Promise<void> {
return browser.runtime.sendMessage({ return browser.runtime.sendMessage({

@ -0,0 +1,13 @@
import FollowSlaveClient, { FollowSlaveClientImpl } from './FollowSlaveClient';
export default interface FollowSlaveClientFactory {
create(window: Window): FollowSlaveClient;
// eslint-disable-next-line semi
}
export class FollowSlaveClientFactoryImpl implements FollowSlaveClientFactory {
create(window: Window): FollowSlaveClient {
return new FollowSlaveClientImpl(window);
}
}

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase'; import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
@injectable()
export default class AddonEnabledController { export default class AddonEnabledController {
private addonEnabledUseCase: AddonEnabledUseCase; constructor(
private addonEnabledUseCase: AddonEnabledUseCase,
constructor({ ) {
addonEnabledUseCase = new AddonEnabledUseCase(),
} = {}) {
this.addonEnabledUseCase = addonEnabledUseCase;
} }
getAddonEnabled( getAddonEnabled(

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import ConsoleFrameUseCase from '../usecases/ConsoleFrameUseCase'; import ConsoleFrameUseCase from '../usecases/ConsoleFrameUseCase';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
@injectable()
export default class ConsoleFrameController { export default class ConsoleFrameController {
private consoleFrameUseCase: ConsoleFrameUseCase; constructor(
private consoleFrameUseCase: ConsoleFrameUseCase,
constructor({ ) {
consoleFrameUseCase = new ConsoleFrameUseCase(),
} = {}) {
this.consoleFrameUseCase = consoleFrameUseCase;
} }
unfocus(_message: messages.Message) { unfocus(_message: messages.Message) {

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
import FindUseCase from '../usecases/FindUseCase'; import FindUseCase from '../usecases/FindUseCase';
@injectable()
export default class FindController { export default class FindController {
private findUseCase: FindUseCase; constructor(
private findUseCase: FindUseCase,
constructor({ ) {
findUseCase = new FindUseCase(),
} = {}) {
this.findUseCase = findUseCase;
} }
async start(m: messages.ConsoleEnterFindMessage): Promise<void> { async start(m: messages.ConsoleEnterFindMessage): Promise<void> {

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import FollowSlaveUseCase from '../usecases/FollowSlaveUseCase'; import FollowSlaveUseCase from '../usecases/FollowSlaveUseCase';
import Key from '../domains/Key'; import Key from '../domains/Key';
@injectable()
export default class FollowKeyController { export default class FollowKeyController {
private followSlaveUseCase: FollowSlaveUseCase; constructor(
private followSlaveUseCase: FollowSlaveUseCase,
constructor({ ) {
followSlaveUseCase = new FollowSlaveUseCase(),
} = {}) {
this.followSlaveUseCase = followSlaveUseCase;
} }
press(key: Key): boolean { press(key: Key): boolean {

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import FollowMasterUseCase from '../usecases/FollowMasterUseCase'; import FollowMasterUseCase from '../usecases/FollowMasterUseCase';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
@injectable()
export default class FollowMasterController { export default class FollowMasterController {
private followMasterUseCase: FollowMasterUseCase; constructor(
private followMasterUseCase: FollowMasterUseCase,
constructor({ ) {
followMasterUseCase = new FollowMasterUseCase(),
} = {}) {
this.followMasterUseCase = followMasterUseCase;
} }
followStart(m: messages.FollowStartMessage): void { followStart(m: messages.FollowStartMessage): void {

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
import FollowSlaveUseCase from '../usecases/FollowSlaveUseCase'; import FollowSlaveUseCase from '../usecases/FollowSlaveUseCase';
@injectable()
export default class FollowSlaveController { export default class FollowSlaveController {
private usecase: FollowSlaveUseCase; constructor(
private usecase: FollowSlaveUseCase,
constructor({ ) {
usecase = new FollowSlaveUseCase(),
} = {}) {
this.usecase = usecase;
} }
countTargets(m: messages.FollowRequestCountTargetsMessage): void { countTargets(m: messages.FollowRequestCountTargetsMessage): void {

@ -1,3 +1,4 @@
import { injectable, inject } from 'tsyringe';
import * as operations from '../../shared/operations'; import * as operations from '../../shared/operations';
import KeymapUseCase from '../usecases/KeymapUseCase'; import KeymapUseCase from '../usecases/KeymapUseCase';
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase'; import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
@ -8,53 +9,25 @@ import FocusUseCase from '../usecases/FocusUseCase';
import ClipboardUseCase from '../usecases/ClipboardUseCase'; import ClipboardUseCase from '../usecases/ClipboardUseCase';
import BackgroundClient from '../client/BackgroundClient'; import BackgroundClient from '../client/BackgroundClient';
import MarkKeyyUseCase from '../usecases/MarkKeyUseCase'; import MarkKeyyUseCase from '../usecases/MarkKeyUseCase';
import FollowMasterClient, { FollowMasterClientImpl } import FollowMasterClient from '../client/FollowMasterClient';
from '../client/FollowMasterClient';
import Key from '../domains/Key'; import Key from '../domains/Key';
@injectable()
export default class KeymapController { export default class KeymapController {
private keymapUseCase: KeymapUseCase; constructor(
private keymapUseCase: KeymapUseCase,
private addonEnabledUseCase: AddonEnabledUseCase,
private findSlaveUseCase: FindSlaveUseCase,
private scrollUseCase: ScrollUseCase,
private navigateUseCase: NavigateUseCase,
private focusUseCase: FocusUseCase,
private clipbaordUseCase: ClipboardUseCase,
private backgroundClient: BackgroundClient,
private markKeyUseCase: MarkKeyyUseCase,
private addonEnabledUseCase: AddonEnabledUseCase; @inject('FollowMasterClient')
private followMasterClient: FollowMasterClient,
private findSlaveUseCase: FindSlaveUseCase; ) {
private scrollUseCase: ScrollUseCase;
private navigateUseCase: NavigateUseCase;
private focusUseCase: FocusUseCase;
private clipbaordUseCase: ClipboardUseCase;
private backgroundClient: BackgroundClient;
private markKeyUseCase: MarkKeyyUseCase;
private followMasterClient: FollowMasterClient;
constructor({
keymapUseCase = new KeymapUseCase(),
addonEnabledUseCase = new AddonEnabledUseCase(),
findSlaveUseCase = new FindSlaveUseCase(),
scrollUseCase = new ScrollUseCase(),
navigateUseCase = new NavigateUseCase(),
focusUseCase = new FocusUseCase(),
clipbaordUseCase = new ClipboardUseCase(),
backgroundClient = new BackgroundClient(),
markKeyUseCase = new MarkKeyyUseCase(),
followMasterClient = new FollowMasterClientImpl(window.top),
} = {}) {
this.keymapUseCase = keymapUseCase;
this.addonEnabledUseCase = addonEnabledUseCase;
this.findSlaveUseCase = findSlaveUseCase;
this.scrollUseCase = scrollUseCase;
this.navigateUseCase = navigateUseCase;
this.focusUseCase = focusUseCase;
this.clipbaordUseCase = clipbaordUseCase;
this.backgroundClient = backgroundClient;
this.markKeyUseCase = markKeyUseCase;
this.followMasterClient = followMasterClient;
} }
// eslint-disable-next-line complexity, max-lines-per-function // eslint-disable-next-line complexity, max-lines-per-function

@ -1,13 +1,12 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
import MarkUseCase from '../usecases/MarkUseCase'; import MarkUseCase from '../usecases/MarkUseCase';
@injectable()
export default class MarkController { export default class MarkController {
private markUseCase: MarkUseCase; constructor(
private markUseCase: MarkUseCase,
constructor({ ) {
markUseCase = new MarkUseCase(),
} = {}) {
this.markUseCase = markUseCase;
} }
scrollTo(message: messages.TabScrollToMessage) { scrollTo(message: messages.TabScrollToMessage) {

@ -1,18 +1,14 @@
import { injectable } from 'tsyringe';
import MarkUseCase from '../usecases/MarkUseCase'; import MarkUseCase from '../usecases/MarkUseCase';
import MarkKeyyUseCase from '../usecases/MarkKeyUseCase'; import MarkKeyyUseCase from '../usecases/MarkKeyUseCase';
import Key from '../domains/Key'; import Key from '../domains/Key';
@injectable()
export default class MarkKeyController { export default class MarkKeyController {
private markUseCase: MarkUseCase; constructor(
private markUseCase: MarkUseCase,
private markKeyUseCase: MarkKeyyUseCase; private markKeyUseCase: MarkKeyyUseCase,
) {
constructor({
markUseCase = new MarkUseCase(),
markKeyUseCase = new MarkKeyyUseCase(),
} = {}) {
this.markUseCase = markUseCase;
this.markKeyUseCase = markKeyUseCase;
} }
press(key: Key): boolean { press(key: Key): boolean {

@ -1,20 +1,17 @@
import { injectable } from 'tsyringe';
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase'; import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
import SettingUseCase from '../usecases/SettingUseCase'; import SettingUseCase from '../usecases/SettingUseCase';
import * as blacklists from '../../shared/blacklists'; import * as blacklists from '../../shared/blacklists';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
@injectable()
export default class SettingController { export default class SettingController {
private addonEnabledUseCase: AddonEnabledUseCase;
private settingUseCase: SettingUseCase; constructor(
private addonEnabledUseCase: AddonEnabledUseCase,
constructor({ private settingUseCase: SettingUseCase,
addonEnabledUseCase = new AddonEnabledUseCase(), ) {
settingUseCase = new SettingUseCase(),
} = {}) {
this.addonEnabledUseCase = addonEnabledUseCase;
this.settingUseCase = settingUseCase;
} }
async initSettings(): Promise<void> { async initSettings(): Promise<void> {

@ -0,0 +1,54 @@
/* eslint-disable max-len */
import { AddonEnabledRepositoryImpl } from './repositories/AddonEnabledRepository';
import { AddonIndicatorClientImpl } from './client/AddonIndicatorClient';
import { ClipboardRepositoryImpl } from './repositories/ClipboardRepository';
import { ConsoleClientImpl } from './client/ConsoleClient';
import { ConsoleFramePresenterImpl } from './presenters/ConsoleFramePresenter';
import { FindClientImpl } from './client/FindClient';
import { FindMasterClientImpl } from './client/FindMasterClient';
import { FindPresenterImpl } from './presenters/FindPresenter';
import { FindRepositoryImpl } from './repositories/FindRepository';
import { FocusPresenterImpl } from './presenters/FocusPresenter';
import { FollowKeyRepositoryImpl } from './repositories/FollowKeyRepository';
import { FollowMasterClientImpl } from './client/FollowMasterClient';
import { FollowMasterRepositoryImpl } from './repositories/FollowMasterRepository';
import { FollowPresenterImpl } from './presenters/FollowPresenter';
import { FollowSlaveClientFactoryImpl } from './client/FollowSlaveClientFactory';
import { FollowSlaveRepositoryImpl } from './repositories/FollowSlaveRepository';
import { KeymapRepositoryImpl } from './repositories/KeymapRepository';
import { MarkClientImpl } from './client/MarkClient';
import { MarkKeyRepositoryImpl } from './repositories/MarkKeyRepository';
import { MarkRepositoryImpl } from './repositories/MarkRepository';
import { NavigationPresenterImpl } from './presenters/NavigationPresenter';
import { ScrollPresenterImpl } from './presenters/ScrollPresenter';
import { SettingClientImpl } from './client/SettingClient';
import { SettingRepositoryImpl } from './repositories/SettingRepository';
import { TabsClientImpl } from './client/TabsClient';
import { container } from 'tsyringe';
container.register('FollowMasterClient', { useValue: new FollowMasterClientImpl(window.top) });
container.register('AddonEnabledRepository', { useClass: AddonEnabledRepositoryImpl });
container.register('AddonIndicatorClient', { useClass: AddonIndicatorClientImpl });
container.register('ClipboardRepository', { useClass: ClipboardRepositoryImpl });
container.register('ConsoleClient', { useClass: ConsoleClientImpl });
container.register('ConsoleFramePresenter', { useClass: ConsoleFramePresenterImpl });
container.register('FindClient', { useClass: FindClientImpl });
container.register('FindMasterClient', { useClass: FindMasterClientImpl });
container.register('FindPresenter', { useClass: FindPresenterImpl });
container.register('FindRepository', { useClass: FindRepositoryImpl });
container.register('FocusPresenter', { useClass: FocusPresenterImpl });
container.register('FollowKeyRepository', { useClass: FollowKeyRepositoryImpl });
container.register('FollowMasterRepository', { useClass: FollowMasterRepositoryImpl });
container.register('FollowPresenter', { useClass: FollowPresenterImpl });
container.register('FollowSlaveClientFactory', { useClass: FollowSlaveClientFactoryImpl });
container.register('FollowSlaveRepository', { useClass: FollowSlaveRepositoryImpl });
container.register('KeymapRepository', { useClass: KeymapRepositoryImpl });
container.register('MarkClient', { useClass: MarkClientImpl });
container.register('MarkKeyRepository', { useClass: MarkKeyRepositoryImpl });
container.register('MarkRepository', { useClass: MarkRepositoryImpl });
container.register('NavigationPresenter', { useClass: NavigationPresenterImpl });
container.register('ScrollPresenter', { useClass: ScrollPresenterImpl });
container.register('SettingClient', { useClass: SettingClientImpl });
container.register('SettingRepository', { useClass: SettingRepositoryImpl });
container.register('TabsClient', { useClass: TabsClientImpl });

@ -1,15 +1,19 @@
import { ConsoleFramePresenterImpl } from './presenters/ConsoleFramePresenter'; import 'reflect-metadata';
import Application from './Application';
import consoleFrameStyle from './site-style'; import consoleFrameStyle from './site-style';
import * as routes from './routes'; import { ConsoleFramePresenterImpl } from './presenters/ConsoleFramePresenter';
import { container } from 'tsyringe';
import './di';
if (window.self === window.top) { if (window.self === window.top) {
routes.routeMasterComponents();
new ConsoleFramePresenterImpl().initialize(); new ConsoleFramePresenterImpl().initialize();
} }
routes.routeComponents(); try {
let app = container.resolve(Application);
app.run();
} catch (e) { console.error(e); }
let style = window.document.createElement('style'); let style = window.document.createElement('style');
style.textContent = consoleFrameStyle; style.textContent = consoleFrameStyle;

@ -1,97 +0,0 @@
import MessageListener from './MessageListener';
import FindController from './controllers/FindController';
import MarkController from './controllers/MarkController';
import FollowMasterController from './controllers/FollowMasterController';
import FollowSlaveController from './controllers/FollowSlaveController';
import FollowKeyController from './controllers/FollowKeyController';
import InputDriver from './InputDriver';
import KeymapController from './controllers/KeymapController';
import AddonEnabledUseCase from './usecases/AddonEnabledUseCase';
import MarkKeyController from './controllers/MarkKeyController';
import AddonEnabledController from './controllers/AddonEnabledController';
import SettingController from './controllers/SettingController';
import ConsoleFrameController from './controllers/ConsoleFrameController';
import * as messages from '../shared/messages';
export const routeComponents = () => {
let listener = new MessageListener();
let followSlaveController = new FollowSlaveController();
listener.onWebMessage((message: messages.Message) => {
switch (message.type) {
case messages.FOLLOW_REQUEST_COUNT_TARGETS:
return followSlaveController.countTargets(message);
case messages.FOLLOW_CREATE_HINTS:
return followSlaveController.createHints(message);
case messages.FOLLOW_SHOW_HINTS:
return followSlaveController.showHints(message);
case messages.FOLLOW_ACTIVATE:
return followSlaveController.activate(message);
case messages.FOLLOW_REMOVE_HINTS:
return followSlaveController.clear(message);
}
return undefined;
});
let keymapController = new KeymapController();
let markKeyController = new MarkKeyController();
let followKeyController = new FollowKeyController();
let inputDriver = new InputDriver(document.body);
inputDriver.onKey(key => followKeyController.press(key));
inputDriver.onKey(key => markKeyController.press(key));
inputDriver.onKey(key => keymapController.press(key));
let settingController = new SettingController();
settingController.initSettings();
listener.onBackgroundMessage((message: messages.Message): any => {
let addonEnabledUseCase = new AddonEnabledUseCase();
switch (message.type) {
case messages.SETTINGS_CHANGED:
return settingController.reloadSettings(message);
case messages.ADDON_TOGGLE_ENABLED:
return addonEnabledUseCase.toggle();
}
});
};
export const routeMasterComponents = () => {
let listener = new MessageListener();
let findController = new FindController();
let followMasterController = new FollowMasterController();
let markController = new MarkController();
let addonEnabledController = new AddonEnabledController();
let consoleFrameController = new ConsoleFrameController();
listener.onWebMessage((message: messages.Message, sender: Window) => {
switch (message.type) {
case messages.CONSOLE_ENTER_FIND:
return findController.start(message);
case messages.FIND_NEXT:
return findController.next(message);
case messages.FIND_PREV:
return findController.prev(message);
case messages.CONSOLE_UNFOCUS:
return consoleFrameController.unfocus(message);
case messages.FOLLOW_START:
return followMasterController.followStart(message);
case messages.FOLLOW_RESPONSE_COUNT_TARGETS:
return followMasterController.responseCountTargets(message, sender);
case messages.FOLLOW_KEY_PRESS:
return followMasterController.keyPress(message);
}
return undefined;
});
listener.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;
});
};

@ -1,19 +1,17 @@
import AddonIndicatorClient, { AddonIndicatorClientImpl } import { injectable, inject } from 'tsyringe';
from '../client/AddonIndicatorClient'; import AddonIndicatorClient from '../client/AddonIndicatorClient';
import AddonEnabledRepository, { AddonEnabledRepositoryImpl } import AddonEnabledRepository from '../repositories/AddonEnabledRepository';
from '../repositories/AddonEnabledRepository';
@injectable()
export default class AddonEnabledUseCase { export default class AddonEnabledUseCase {
private indicator: AddonIndicatorClient;
private repository: AddonEnabledRepository; constructor(
@inject('AddonIndicatorClient')
private indicator: AddonIndicatorClient,
constructor({ @inject('AddonEnabledRepository')
indicator = new AddonIndicatorClientImpl(), private repository: AddonEnabledRepository,
repository = new AddonEnabledRepositoryImpl(), ) {
} = {}) {
this.indicator = indicator;
this.repository = repository;
} }
async enable(): Promise<void> { async enable(): Promise<void> {

@ -1,31 +1,18 @@
import { injectable, inject } from 'tsyringe';
import * as urls from '../../shared/urls'; import * as urls from '../../shared/urls';
import ClipboardRepository, { ClipboardRepositoryImpl } import ClipboardRepository from '../repositories/ClipboardRepository';
from '../repositories/ClipboardRepository'; import SettingRepository from '../repositories/SettingRepository';
import SettingRepository, { SettingRepositoryImpl } import TabsClient from '../client/TabsClient';
from '../repositories/SettingRepository'; import ConsoleClient from '../client/ConsoleClient';
import TabsClient, { TabsClientImpl }
from '../client/TabsClient';
import ConsoleClient, { ConsoleClientImpl } from '../client/ConsoleClient';
@injectable()
export default class ClipboardUseCase { export default class ClipboardUseCase {
private repository: ClipboardRepository; constructor(
@inject('ClipboardRepository') private repository: ClipboardRepository,
private settingRepository: SettingRepository; @inject('SettingRepository') private settingRepository: SettingRepository,
@inject('TabsClient') private client: TabsClient,
private client: TabsClient; @inject('ConsoleClient') private consoleClient: ConsoleClient,
) {
private consoleClient: ConsoleClient;
constructor({
repository = new ClipboardRepositoryImpl(),
settingRepository = new SettingRepositoryImpl(),
client = new TabsClientImpl(),
consoleClient = new ConsoleClientImpl(),
} = {}) {
this.repository = repository;
this.settingRepository = settingRepository;
this.client = client;
this.consoleClient = consoleClient;
} }
async yankCurrentURL(): Promise<string> { async yankCurrentURL(): Promise<string> {

@ -1,13 +1,12 @@
import ConsoleFramePresenter, { ConsoleFramePresenterImpl } import { injectable, inject } from 'tsyringe';
from '../presenters/ConsoleFramePresenter'; import ConsoleFramePresenter from '../presenters/ConsoleFramePresenter';
@injectable()
export default class ConsoleFrameUseCase { export default class ConsoleFrameUseCase {
private consoleFramePresenter: ConsoleFramePresenter; constructor(
@inject('ConsoleFramePresenter')
constructor({ private consoleFramePresenter: ConsoleFramePresenter,
consoleFramePresenter = new ConsoleFramePresenterImpl(), ) {
} = {}) {
this.consoleFramePresenter = consoleFramePresenter;
} }
unfocus() { unfocus() {

@ -1,13 +1,11 @@
import FindMasterClient, { FindMasterClientImpl } import { injectable, inject } from 'tsyringe';
from '../client/FindMasterClient'; import FindMasterClient from '../client/FindMasterClient';
@injectable()
export default class FindSlaveUseCase { export default class FindSlaveUseCase {
private findMasterClient: FindMasterClient; constructor(
@inject('FindMasterClient') private findMasterClient: FindMasterClient,
constructor({ ) {
findMasterClient = new FindMasterClientImpl(),
} = {}) {
this.findMasterClient = findMasterClient;
} }
findNext() { findNext() {

@ -1,28 +1,17 @@
import FindPresenter, { FindPresenterImpl } from '../presenters/FindPresenter'; import { injectable, inject } from 'tsyringe';
import FindRepository, { FindRepositoryImpl } import FindPresenter from '../presenters/FindPresenter';
from '../repositories/FindRepository'; import FindRepository from '../repositories/FindRepository';
import FindClient, { FindClientImpl } from '../client/FindClient'; import FindClient from '../client/FindClient';
import ConsoleClient, { ConsoleClientImpl } from '../client/ConsoleClient'; import ConsoleClient from '../client/ConsoleClient';
@injectable()
export default class FindUseCase { export default class FindUseCase {
private presenter: FindPresenter; constructor(
@inject('FindPresenter') private presenter: FindPresenter,
private repository: FindRepository; @inject('FindRepository') private repository: FindRepository,
@inject('FindClient') private client: FindClient,
private client: FindClient; @inject('ConsoleClient') private consoleClient: ConsoleClient,
) {
private consoleClient: ConsoleClient;
constructor({
presenter = new FindPresenterImpl() as FindPresenter,
repository = new FindRepositoryImpl(),
client = new FindClientImpl(),
consoleClient = new ConsoleClientImpl(),
} = {}) {
this.presenter = presenter;
this.repository = repository;
this.client = client;
this.consoleClient = consoleClient;
} }
async startFind(keyword?: string): Promise<void> { async startFind(keyword?: string): Promise<void> {

@ -1,13 +1,11 @@
import FocusPresenter, { FocusPresenterImpl } import { injectable, inject } from 'tsyringe';
from '../presenters/FocusPresenter'; import FocusPresenter from '../presenters/FocusPresenter';
@injectable()
export default class FocusUseCases { export default class FocusUseCases {
private presenter: FocusPresenter; constructor(
@inject('FocusPresenter') private presenter: FocusPresenter,
constructor({ ) {
presenter = new FocusPresenterImpl(),
} = {}) {
this.presenter = presenter;
} }
focusFirstInput() { focusFirstInput() {

@ -1,31 +1,29 @@
import FollowKeyRepository, { FollowKeyRepositoryImpl } import { injectable, inject } from 'tsyringe';
from '../repositories/FollowKeyRepository'; import FollowKeyRepository from '../repositories/FollowKeyRepository';
import FollowMasterRepository, { FollowMasterRepositoryImpl } import FollowMasterRepository from '../repositories/FollowMasterRepository';
from '../repositories/FollowMasterRepository'; import FollowSlaveClient from '../client/FollowSlaveClient';
import FollowSlaveClient, { FollowSlaveClientImpl } import FollowSlaveClientFactory from '../client/FollowSlaveClientFactory';
from '../client/FollowSlaveClient'; import SettingRepository from '../repositories/SettingRepository';
import HintKeyProducer from './HintKeyProducer'; import HintKeyProducer from './HintKeyProducer';
import SettingRepository, { SettingRepositoryImpl }
from '../repositories/SettingRepository';
@injectable()
export default class FollowMasterUseCase { export default class FollowMasterUseCase {
private followKeyRepository: FollowKeyRepository; // TODO Make repository
private producer: HintKeyProducer | null;
private followMasterRepository: FollowMasterRepository; constructor(
@inject('FollowKeyRepository')
private followKeyRepository: FollowKeyRepository,
private settingRepository: SettingRepository; @inject('FollowMasterRepository')
private followMasterRepository: FollowMasterRepository,
// TODO Make repository @inject('SettingRepository')
private producer: HintKeyProducer | null; private settingRepository: SettingRepository,
constructor({ @inject('FollowSlaveClientFactory')
followKeyRepository = new FollowKeyRepositoryImpl(), private followSlaveClientFactory: FollowSlaveClientFactory,
followMasterRepository = new FollowMasterRepositoryImpl(), ) {
settingRepository = new SettingRepositoryImpl(),
} = {}) {
this.followKeyRepository = followKeyRepository;
this.followMasterRepository = followMasterRepository;
this.settingRepository = settingRepository;
this.producer = null; this.producer = null;
} }
@ -38,7 +36,7 @@ export default class FollowMasterUseCase {
let viewWidth = window.top.innerWidth; let viewWidth = window.top.innerWidth;
let viewHeight = window.top.innerHeight; let viewHeight = window.top.innerHeight;
new FollowSlaveClientImpl(window.top).requestHintCount( this.followSlaveClientFactory.create(window.top).requestHintCount(
{ width: viewWidth, height: viewHeight }, { width: viewWidth, height: viewHeight },
{ x: 0, y: 0 }, { x: 0, y: 0 },
); );
@ -47,7 +45,8 @@ export default class FollowMasterUseCase {
for (let i = 0; i < frameElements.length; ++i) { for (let i = 0; i < frameElements.length; ++i) {
let ele = frameElements[i] as HTMLFrameElement | HTMLIFrameElement; let ele = frameElements[i] as HTMLFrameElement | HTMLIFrameElement;
let { left: frameX, top: frameY } = ele.getBoundingClientRect(); let { left: frameX, top: frameY } = ele.getBoundingClientRect();
new FollowSlaveClientImpl(ele.contentWindow!!).requestHintCount( let client = this.followSlaveClientFactory.create(ele.contentWindow!!);
client.requestHintCount(
{ width: viewWidth, height: viewHeight }, { width: viewWidth, height: viewHeight },
{ x: frameX, y: frameY }, { x: frameX, y: frameY },
); );
@ -77,7 +76,8 @@ export default class FollowMasterUseCase {
let { left: frameX, top: frameY } = ele.getBoundingClientRect(); let { left: frameX, top: frameY } = ele.getBoundingClientRect();
pos = { x: frameX, y: frameY }; pos = { x: frameX, y: frameY };
} }
new FollowSlaveClientImpl(sender).createHints( let client = this.followSlaveClientFactory.create(sender);
client.createHints(
{ width: viewWidth, height: viewHeight }, { width: viewWidth, height: viewHeight },
pos, pos,
produced, produced,
@ -138,7 +138,7 @@ export default class FollowMasterUseCase {
private broadcastToSlaves(handler: (client: FollowSlaveClient) => void) { private broadcastToSlaves(handler: (client: FollowSlaveClient) => void) {
let allFrames = [window.self].concat(Array.from(window.frames as any)); let allFrames = [window.self].concat(Array.from(window.frames as any));
let clients = allFrames.map(frame => new FollowSlaveClientImpl(frame)); let clients = allFrames.map(w => this.followSlaveClientFactory.create(w));
for (let client of clients) { for (let client of clients) {
handler(client); handler(client);
} }

@ -1,11 +1,9 @@
import FollowSlaveRepository, { FollowSlaveRepositoryImpl } import { injectable, inject } from 'tsyringe';
from '../repositories/FollowSlaveRepository'; import FollowSlaveRepository from '../repositories/FollowSlaveRepository';
import FollowPresenter, { FollowPresenterImpl } import FollowPresenter from '../presenters/FollowPresenter';
from '../presenters/FollowPresenter'; import TabsClient from '../client/TabsClient';
import TabsClient, { TabsClientImpl } from '../client/TabsClient'; import FollowMasterClient from '../client/FollowMasterClient';
import { LinkHint, InputHint } from '../presenters/Hint'; import { LinkHint, InputHint } from '../presenters/Hint';
import FollowMasterClient, { FollowMasterClientImpl }
from '../client/FollowMasterClient';
import Key from '../domains/Key'; import Key from '../domains/Key';
interface Size { interface Size {
@ -18,25 +16,21 @@ interface Point {
y: number; y: number;
} }
@injectable()
export default class FollowSlaveUseCase { export default class FollowSlaveUseCase {
private presenter: FollowPresenter; constructor(
@inject('FollowPresenter')
private presenter: FollowPresenter,
private tabsClient: TabsClient; @inject('TabsClient')
private tabsClient: TabsClient,
private followMasterClient: FollowMasterClient; @inject('FollowMasterClient')
private followMasterClient: FollowMasterClient,
private followSlaveRepository: FollowSlaveRepository; @inject('FollowSlaveRepository')
private followSlaveRepository: FollowSlaveRepository,
constructor({ ) {
presenter = new FollowPresenterImpl(),
tabsClient = new TabsClientImpl(),
followMasterClient = new FollowMasterClientImpl(window.top),
followSlaveRepository = new FollowSlaveRepositoryImpl(),
} = {}) {
this.presenter = presenter;
this.tabsClient = tabsClient;
this.followMasterClient = followMasterClient;
this.followSlaveRepository = followSlaveRepository;
} }
countTargets(viewSize: Size, framePosition: Point): void { countTargets(viewSize: Size, framePosition: Point): void {

@ -1,10 +1,7 @@
import KeymapRepository, { KeymapRepositoryImpl } import { injectable, inject } from 'tsyringe';
from '../repositories/KeymapRepository'; import KeymapRepository from '../repositories/KeymapRepository';
import SettingRepository, { SettingRepositoryImpl } import SettingRepository from '../repositories/SettingRepository';
from '../repositories/SettingRepository'; import AddonEnabledRepository from '../repositories/AddonEnabledRepository';
import AddonEnabledRepository, { AddonEnabledRepositoryImpl }
from '../repositories/AddonEnabledRepository';
import * as operations from '../../shared/operations'; import * as operations from '../../shared/operations';
import { Keymaps } from '../../shared/Settings'; import { Keymaps } from '../../shared/Settings';
import Key from '../domains/Key'; import Key from '../domains/Key';
@ -17,22 +14,18 @@ const reservedKeymaps: Keymaps = {
'<C-[>': { type: operations.CANCEL }, '<C-[>': { type: operations.CANCEL },
}; };
@injectable()
export default class KeymapUseCase { export default class KeymapUseCase {
private repository: KeymapRepository; constructor(
@inject('KeymapRepository')
private settingRepository: SettingRepository; private repository: KeymapRepository,
private addonEnabledRepository: AddonEnabledRepository; @inject('SettingRepository')
private settingRepository: SettingRepository,
constructor({ @inject('AddonEnabledRepository')
repository = new KeymapRepositoryImpl(), private addonEnabledRepository: AddonEnabledRepository,
settingRepository = new SettingRepositoryImpl(), ) {
addonEnabledRepository = new AddonEnabledRepositoryImpl(),
} = {}) {
this.repository = repository;
this.settingRepository = settingRepository;
this.addonEnabledRepository = addonEnabledRepository;
} }
nextOp(key: Key): operations.Operation | null { nextOp(key: Key): operations.Operation | null {

@ -1,13 +1,11 @@
import MarkKeyRepository, { MarkKeyRepositoryImpl } import { injectable, inject } from 'tsyringe';
from '../repositories/MarkKeyRepository'; import MarkKeyRepository from '../repositories/MarkKeyRepository';
@injectable()
export default class MarkKeyUseCase { export default class MarkKeyUseCase {
private repository: MarkKeyRepository; constructor(
@inject('MarkKeyRepository') private repository: MarkKeyRepository,
constructor({ ) {
repository = new MarkKeyRepositoryImpl()
} = {}) {
this.repository = repository;
} }
isSetMode(): boolean { isSetMode(): boolean {

@ -1,35 +1,19 @@
import ScrollPresenter, { ScrollPresenterImpl } import { injectable, inject } from 'tsyringe';
from '../presenters/ScrollPresenter'; import ScrollPresenter from '../presenters/ScrollPresenter';
import MarkClient, { MarkClientImpl } from '../client/MarkClient'; import MarkClient from '../client/MarkClient';
import MarkRepository, { MarkRepositoryImpl } import MarkRepository from '../repositories/MarkRepository';
from '../repositories/MarkRepository'; import SettingRepository from '../repositories/SettingRepository';
import SettingRepository, { SettingRepositoryImpl } import ConsoleClient from '../client/ConsoleClient';
from '../repositories/SettingRepository';
import ConsoleClient, { ConsoleClientImpl } from '../client/ConsoleClient'; @injectable()
export default class MarkUseCase { export default class MarkUseCase {
private scrollPresenter: ScrollPresenter; constructor(
@inject('ScrollPresenter') private scrollPresenter: ScrollPresenter,
private client: MarkClient; @inject('MarkClient') private client: MarkClient,
@inject('MarkRepository') private repository: MarkRepository,
private repository: MarkRepository; @inject('SettingRepository') private settingRepository: SettingRepository,
@inject('ConsoleClient') private consoleClient: ConsoleClient,
private settingRepository: SettingRepository; ) {
private consoleClient: ConsoleClient;
constructor({
scrollPresenter = new ScrollPresenterImpl(),
client = new MarkClientImpl(),
repository = new MarkRepositoryImpl(),
settingRepository = new SettingRepositoryImpl(),
consoleClient = new ConsoleClientImpl(),
} = {}) {
this.scrollPresenter = scrollPresenter;
this.client = client;
this.repository = repository;
this.settingRepository = settingRepository;
this.consoleClient = consoleClient;
} }
async set(key: string): Promise<void> { async set(key: string): Promise<void> {

@ -1,13 +1,12 @@
import NavigationPresenter, { NavigationPresenterImpl } import { injectable, inject } from 'tsyringe';
from '../presenters/NavigationPresenter'; import NavigationPresenter from '../presenters/NavigationPresenter';
@injectable()
export default class NavigateUseCase { export default class NavigateUseCase {
private navigationPresenter: NavigationPresenter; constructor(
@inject('NavigationPresenter')
constructor({ private navigationPresenter: NavigationPresenter,
navigationPresenter = new NavigationPresenterImpl(), ) {
} = {}) {
this.navigationPresenter = navigationPresenter;
} }
openHistoryPrev(): void { openHistoryPrev(): void {

@ -1,19 +1,13 @@
import ScrollPresenter, { ScrollPresenterImpl } import { injectable, inject } from 'tsyringe';
from '../presenters/ScrollPresenter'; import ScrollPresenter from '../presenters/ScrollPresenter';
import SettingRepository, { SettingRepositoryImpl } import SettingRepository from '../repositories/SettingRepository';
from '../repositories/SettingRepository';
@injectable()
export default class ScrollUseCase { export default class ScrollUseCase {
private presenter: ScrollPresenter; constructor(
@inject('ScrollPresenter') private presenter: ScrollPresenter,
private settingRepository: SettingRepository; @inject('SettingRepository') private settingRepository: SettingRepository,
) {
constructor({
presenter = new ScrollPresenterImpl(),
settingRepository = new SettingRepositoryImpl(),
} = {}) {
this.presenter = presenter;
this.settingRepository = settingRepository;
} }
scrollVertically(count: number): void { scrollVertically(count: number): void {

@ -1,19 +1,14 @@
import SettingRepository, { SettingRepositoryImpl } import { injectable, inject } from 'tsyringe';
from '../repositories/SettingRepository'; import SettingRepository from '../repositories/SettingRepository';
import SettingClient, { SettingClientImpl } from '../client/SettingClient'; import SettingClient from '../client/SettingClient';
import Settings from '../../shared/Settings'; import Settings from '../../shared/Settings';
@injectable()
export default class SettingUseCase { export default class SettingUseCase {
private repository: SettingRepository; constructor(
@inject('SettingRepository') private repository: SettingRepository,
private client: SettingClient; @inject('SettingClient') private client: SettingClient,
) {
constructor({
repository = new SettingRepositoryImpl(),
client = new SettingClientImpl(),
} = {}) {
this.repository = repository;
this.client = client;
} }
async reload(): Promise<Settings> { async reload(): Promise<Settings> {

@ -40,7 +40,7 @@ describe('AddonEnabledUseCase', () => {
beforeEach(() => { beforeEach(() => {
repository = new MockAddonEnabledRepository(true); repository = new MockAddonEnabledRepository(true);
indicator = new MockAddonIndicatorClient(false); indicator = new MockAddonIndicatorClient(false);
sut = new AddonEnabledUseCase({ repository, indicator }); sut = new AddonEnabledUseCase(indicator, repository);
}); });
describe('#enable', () => { describe('#enable', () => {

@ -1,4 +1,5 @@
import ClipboardRepository from '../../../src/content/repositories/ClipboardRepository'; import ClipboardRepository from '../../../src/content/repositories/ClipboardRepository';
import { SettingRepositoryImpl } from '../../../src/content/repositories/SettingRepository';
import TabsClient from '../../../src/content/client/TabsClient'; import TabsClient from '../../../src/content/client/TabsClient';
import MockConsoleClient from '../mock/MockConsoleClient'; import MockConsoleClient from '../mock/MockConsoleClient';
import ClipboardUseCase from '../../../src/content/usecases/ClipboardUseCase'; import ClipboardUseCase from '../../../src/content/usecases/ClipboardUseCase';
@ -43,7 +44,12 @@ describe('ClipboardUseCase', () => {
repository = new MockClipboardRepository(); repository = new MockClipboardRepository();
client = new MockTabsClient(); client = new MockTabsClient();
consoleClient = new MockConsoleClient(); consoleClient = new MockConsoleClient();
sut = new ClipboardUseCase({ repository, client: client, consoleClient }); sut = new ClipboardUseCase(
repository,
new SettingRepositoryImpl(),
client,
consoleClient
);
}); });
describe('#yankCurrentURL', () => { describe('#yankCurrentURL', () => {

@ -71,7 +71,7 @@ describe('FindUseCase', () => {
presenter = new MockFindPresenter(); presenter = new MockFindPresenter();
client = new MockFindClient(); client = new MockFindClient();
consoleClient = new MockConsoleClient(); consoleClient = new MockConsoleClient();
sut = new FindUseCase({ repository, presenter, client, consoleClient }); sut = new FindUseCase(presenter, repository, client, consoleClient);
}); });
describe('#startFind', () => { describe('#startFind', () => {

@ -1,4 +1,5 @@
import MarkRepository from '../../../src/content/repositories/MarkRepository'; import MarkRepository from '../../../src/content/repositories/MarkRepository';
import { SettingRepositoryImpl } from '../../../src/content/repositories/SettingRepository';
import MarkUseCase from '../../../src/content/usecases/MarkUseCase'; import MarkUseCase from '../../../src/content/usecases/MarkUseCase';
import MarkClient from '../../../src/content/client/MarkClient'; import MarkClient from '../../../src/content/client/MarkClient';
import MockConsoleClient from '../mock/MockConsoleClient'; import MockConsoleClient from '../mock/MockConsoleClient';
@ -54,9 +55,13 @@ describe('MarkUseCase', () => {
client = new MockMarkClient(); client = new MockMarkClient();
consoleClient = new MockConsoleClient(); consoleClient = new MockConsoleClient();
scrollPresenter = new MockScrollPresenter(); scrollPresenter = new MockScrollPresenter();
sut = new MarkUseCase({ sut = new MarkUseCase(
repository, client, consoleClient, scrollPresenter, scrollPresenter,
}); client,
repository,
new SettingRepositoryImpl(),
consoleClient,
);
}); });
describe('#set', () => { describe('#set', () => {

@ -56,7 +56,7 @@ describe('AddonEnabledUseCase', () => {
repository = new MockSettingRepository(); repository = new MockSettingRepository();
client = new MockSettingClient(testSettings); client = new MockSettingClient(testSettings);
sut = new SettingUseCase({ repository, client }); sut = new SettingUseCase(repository, client);
}); });
describe('#reload', () => { describe('#reload', () => {

@ -1,6 +1,8 @@
import chai from 'chai'; import 'reflect-metadata';
import { expect } from 'chai';
const browserFake = require('webextensions-api-fake'); const browserFake = require('webextensions-api-fake');
const browser = browserFake(); const browser = browserFake();
global.expect = chai.expect; global.expect = expect;
global.browser = browser; global.browser = browser;

@ -5,7 +5,6 @@
"lib": ["es6", "dom", "es2017"], "lib": ["es6", "dom", "es2017"],
"allowJs": true, "allowJs": true,
"checkJs": true, "checkJs": true,
"noEmit": true,
"jsx": "react", "jsx": "react",
"sourceMap": true, "sourceMap": true,
"outDir": "./build", "outDir": "./build",
@ -28,7 +27,10 @@
"moduleResolution": "node", "moduleResolution": "node",
"esModuleInterop": true, "esModuleInterop": true,
"typeRoots": ["node_modules/@types", "node_modules/web-ext-types"] "typeRoots": ["node_modules/@types", "node_modules/web-ext-types"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}, },
"include": [ "include": [
"src" "src"

@ -17,19 +17,20 @@ config = {
filename: '[name].js' filename: '[name].js'
}, },
optimization: {
minimize: false
},
performance: {
hints: false
},
module: { module: {
rules: [ rules: [
{ {
test: [ /\.js$/, /\.jsx$/, /\.ts$/, /\.tsx$/], test: [ /\.ts$/, /\.tsx$/],
exclude: /node_modules/, exclude: /node_modules/,
loader: 'babel-loader', loader: 'ts-loader'
options: {
presets: [
{ plugins: ['@babel/plugin-proposal-class-properties'] },
'@babel/react',
'@babel/preset-typescript'
]
},
}, },
{ {
test: /\.css$/, test: /\.css$/,