aboutsummaryrefslogtreecommitdiff
path: root/src/background
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2020-03-28 21:35:06 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2020-03-28 21:43:40 +0900
commitea63c5f78b4c985e9d6dd106afe4f97bfeedbcd0 (patch)
treef0accb862f9f3b75c8c86f78361e2acab46f11ef /src/background
parenta8d78f1286fb3fe456a786b2c0e534d212835560 (diff)
Complete tabs by the completion packages
Diffstat (limited to 'src/background')
-rw-r--r--src/background/completion/OpenCompletionUseCase.ts (renamed from src/background/completion/CompletionUseCase.ts)2
-rw-r--r--src/background/completion/TabCompletionUseCase.ts34
-rw-r--r--src/background/completion/TabItem.ts11
-rw-r--r--src/background/completion/TabRepository.ts12
-rw-r--r--src/background/completion/impl/TabRepositoryImpl.ts27
-rw-r--r--src/background/controllers/CompletionController.ts15
-rw-r--r--src/background/di.ts4
-rw-r--r--src/background/infrastructures/ContentMessageListener.ts2
-rw-r--r--src/background/presenters/TabPresenter.ts65
-rw-r--r--src/background/usecases/AddonEnabledUseCase.ts4
-rw-r--r--src/background/usecases/CommandUseCase.ts4
-rw-r--r--src/background/usecases/CompletionsUseCase.ts6
-rw-r--r--src/background/usecases/ConsoleUseCase.ts4
-rw-r--r--src/background/usecases/FindUseCase.ts4
-rw-r--r--src/background/usecases/LinkUseCase.ts4
-rw-r--r--src/background/usecases/MarkUseCase.ts4
-rw-r--r--src/background/usecases/NavigateUseCase.ts4
-rw-r--r--src/background/usecases/TabSelectUseCase.ts4
-rw-r--r--src/background/usecases/TabUseCase.ts4
-rw-r--r--src/background/usecases/VersionUseCase.ts2
-rw-r--r--src/background/usecases/ZoomUseCase.ts4
21 files changed, 175 insertions, 45 deletions
diff --git a/src/background/completion/CompletionUseCase.ts b/src/background/completion/OpenCompletionUseCase.ts
index f7531e7..1b63e7c 100644
--- a/src/background/completion/CompletionUseCase.ts
+++ b/src/background/completion/OpenCompletionUseCase.ts
@@ -15,7 +15,7 @@ export type HistoryItem = {
}
@injectable()
-export default class CompletionUseCase {
+export default class OpenCompletionUseCase {
constructor(
@inject('BookmarkRepository') private bookmarkRepository: BookmarkRepository,
@inject('HistoryRepository') private historyRepository: HistoryRepository,
diff --git a/src/background/completion/TabCompletionUseCase.ts b/src/background/completion/TabCompletionUseCase.ts
new file mode 100644
index 0000000..7e6dce3
--- /dev/null
+++ b/src/background/completion/TabCompletionUseCase.ts
@@ -0,0 +1,34 @@
+import { inject, injectable } from "tsyringe";
+import TabItem from "./TabItem";
+import TabRepository from "./TabRepository";
+import TabPresenter from "../presenters/TabPresenter";
+import TabFlag from "../../shared/TabFlag";
+
+@injectable()
+export default class TabCompletionUseCase {
+ constructor(
+ @inject('TabRepository') private tabRepository: TabRepository,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
+ ) {
+ }
+
+ async queryTabs(query: string, excludePinned: boolean): Promise<TabItem[]> {
+ const lastTabId = await this.tabPresenter.getLastSelectedId();
+ const tabs = await this.tabRepository.queryTabs(query, excludePinned);
+ return tabs.map(tab => {
+ let flag = TabFlag.None;
+ if (tab.active) {
+ flag = TabFlag.CurrentTab
+ } else if (tab.id == lastTabId) {
+ flag = TabFlag.LastTab
+ }
+ return {
+ index: tab.index + 1,
+ flag: flag,
+ title: tab.title,
+ url: tab.url,
+ faviconUrl : tab.faviconUrl
+ }
+ });
+ }
+}
diff --git a/src/background/completion/TabItem.ts b/src/background/completion/TabItem.ts
new file mode 100644
index 0000000..630855a
--- /dev/null
+++ b/src/background/completion/TabItem.ts
@@ -0,0 +1,11 @@
+import TabFlag from "../../shared/TabFlag";
+
+type TabItem = {
+ index: number
+ flag: TabFlag
+ title: string
+ url: string
+ faviconUrl?: string
+}
+
+export default TabItem; \ No newline at end of file
diff --git a/src/background/completion/TabRepository.ts b/src/background/completion/TabRepository.ts
new file mode 100644
index 0000000..61fac3b
--- /dev/null
+++ b/src/background/completion/TabRepository.ts
@@ -0,0 +1,12 @@
+export type Tab = {
+ id: number
+ index: number
+ active: boolean
+ title: string
+ url: string
+ faviconUrl?: string
+}
+
+export default interface TabRepository {
+ queryTabs(query: string, excludePinned: boolean): Promise<Tab[]>;
+}
diff --git a/src/background/completion/impl/TabRepositoryImpl.ts b/src/background/completion/impl/TabRepositoryImpl.ts
new file mode 100644
index 0000000..6692b27
--- /dev/null
+++ b/src/background/completion/impl/TabRepositoryImpl.ts
@@ -0,0 +1,27 @@
+import TabRepository, { Tab } from "../TabRepository";
+
+const COMPLETION_ITEM_LIMIT = 10;
+
+export default class TabRepositoryImpl implements TabRepository {
+ async queryTabs(query: string, excludePinned: boolean): Promise<Tab[]> {
+ const tabs = await browser.tabs.query({ currentWindow: true });
+ return tabs
+ .filter((t) => {
+ return t.url && t.url.toLowerCase().includes(query.toLowerCase()) ||
+ t.title && t.title.toLowerCase().includes(query.toLowerCase());
+ })
+ .filter((t) => {
+ return !(excludePinned && t.pinned);
+ })
+ .filter(item => item.id && item.title && item.url)
+ .slice(0, COMPLETION_ITEM_LIMIT)
+ .map(item => ({
+ id: item.id!!,
+ url: item.url!!,
+ active: item.active,
+ title: item.title!!,
+ faviconUrl: item.favIconUrl,
+ index: item.index,
+ }))
+ }
+} \ No newline at end of file
diff --git a/src/background/controllers/CompletionController.ts b/src/background/controllers/CompletionController.ts
index 313f38b..a268d15 100644
--- a/src/background/controllers/CompletionController.ts
+++ b/src/background/controllers/CompletionController.ts
@@ -1,14 +1,19 @@
import {
ConsoleGetCompletionTypesResponse,
- ConsoleRequestBookmarksResponse, ConsoleRequestHistoryResponse, ConsoleRequestSearchEnginesResponse
+ ConsoleRequestBookmarksResponse,
+ ConsoleRequestHistoryResponse,
+ ConsoleRequestSearchEnginesResponse,
+ ConsoleRequesttabsResponse
} from "../../shared/messages";
import { injectable } from "tsyringe";
-import CompletionUseCase from "../completion/CompletionUseCase";
+import OpenCompletionUseCase from "../completion/OpenCompletionUseCase";
+import TabCompletionUseCase from "../completion/TabCompletionUseCase";
@injectable()
export default class CompletionController {
constructor(
- private completionUseCase: CompletionUseCase,
+ private completionUseCase: OpenCompletionUseCase,
+ private tabCompletionUseCase: TabCompletionUseCase,
) {
}
@@ -28,4 +33,8 @@ export default class CompletionController {
async requestHistory(query: string): Promise<ConsoleRequestHistoryResponse> {
return this.completionUseCase.requestHistory(query);
}
+
+ async queryTabs(query: string, excludePinned: boolean): Promise<ConsoleRequesttabsResponse> {
+ return this.tabCompletionUseCase.queryTabs(query, excludePinned);
+ }
} \ No newline at end of file
diff --git a/src/background/di.ts b/src/background/di.ts
index 0b52e0b..c186262 100644
--- a/src/background/di.ts
+++ b/src/background/di.ts
@@ -6,6 +6,8 @@ import { CachedSettingRepositoryImpl } from "./repositories/CachedSettingReposit
import { container } from 'tsyringe';
import HistoryRepositoryImpl from "./completion/impl/HistoryRepositoryImpl";
import BookmarkRepositoryImpl from "./completion/impl/BookmarkRepositoryImpl";
+import TabRepositoryImpl from "./completion/impl/TabRepositoryImpl";
+import {TabPresenterImpl} from "./presenters/TabPresenter";
container.register('LocalSettingRepository', { useValue: LocalSettingRepository });
container.register('SyncSettingRepository', { useClass: SyncSettingRepository });
@@ -13,3 +15,5 @@ container.register('CachedSettingRepository', { useClass: CachedSettingRepositor
container.register('Notifier', { useClass: NotifierImpl });
container.register('HistoryRepository', { useClass: HistoryRepositoryImpl });
container.register('BookmarkRepository', { useClass: BookmarkRepositoryImpl });
+container.register('TabRepository', { useClass: TabRepositoryImpl });
+container.register('TabPresenter', { useClass: TabPresenterImpl });
diff --git a/src/background/infrastructures/ContentMessageListener.ts b/src/background/infrastructures/ContentMessageListener.ts
index 62cd49f..13aa763 100644
--- a/src/background/infrastructures/ContentMessageListener.ts
+++ b/src/background/infrastructures/ContentMessageListener.ts
@@ -73,6 +73,8 @@ export default class ContentMessageListener {
return this.completionController.requestBookmarks(message.query);
case messages.CONSOLE_REQUEST_HISTORY:
return this.completionController.requestHistory(message.query);
+ case messages.CONSOLE_REQUEST_TABS:
+ return this.completionController.queryTabs(message.query, message.excludePinned);
case messages.CONSOLE_ENTER_COMMAND:
return this.onConsoleEnterCommand(message.text);
case messages.SETTINGS_QUERY:
diff --git a/src/background/presenters/TabPresenter.ts b/src/background/presenters/TabPresenter.ts
index 33d8bea..bded5a2 100644
--- a/src/background/presenters/TabPresenter.ts
+++ b/src/background/presenters/TabPresenter.ts
@@ -1,4 +1,3 @@
-import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage';
const CURRENT_SELECTED_KEY = 'tabs.current.selected';
@@ -6,8 +5,41 @@ const LAST_SELECTED_KEY = 'tabs.last.selected';
type Tab = browser.tabs.Tab;
-@injectable()
-export default class TabPresenter {
+export default interface TabPresenter {
+ open(url: string, tabId?: number): Promise<Tab>;
+
+ create(url: string, opts?: object): Promise<Tab>;
+
+ getCurrent(): Promise<Tab>;
+
+ getAll(): Promise<Tab[]>;
+
+ getLastSelectedId(): Promise<number | undefined>;
+
+ getByKeyword(keyword: string, excludePinned: boolean): Promise<Tab[]>;
+
+ select(tabId: number): Promise<void>;
+
+ remove(ids: number[]): Promise<void>;
+
+ reopen(): Promise<void>;
+
+ reload(tabId: number, cache: boolean): Promise<void>;
+
+ setPinned(tabId: number, pinned: boolean): Promise<void>;
+
+ duplicate(id: number): Promise<Tab>;
+
+ getZoom(tabId: number): Promise<number>;
+
+ setZoom(tabId: number, factor: number): Promise<void>;
+
+ onSelected(
+ listener: (arg: { tabId: number, windowId: number}) => void,
+ ): void;
+}
+
+export class TabPresenterImpl implements TabPresenter {
open(url: string, tabId?: number): Promise<Tab> {
return browser.tabs.update(tabId, { url });
}
@@ -48,15 +80,15 @@ export default class TabPresenter {
});
}
- select(tabId: number): Promise<Tab> {
- return browser.tabs.update(tabId, { active: true });
+ async select(tabId: number): Promise<void> {
+ await browser.tabs.update(tabId, { active: true });
}
- remove(ids: number[]): Promise<void> {
- return browser.tabs.remove(ids);
+ async remove(ids: number[]): Promise<void> {
+ await browser.tabs.remove(ids);
}
- async reopen(): Promise<any> {
+ async reopen(): Promise<void> {
const window = await browser.windows.getCurrent();
const sessions = await browser.sessions.getRecentlyClosed();
const session = sessions.find((s) => {
@@ -66,19 +98,18 @@ export default class TabPresenter {
return;
}
if (session.tab && session.tab.sessionId) {
- return browser.sessions.restore(session.tab.sessionId);
- }
- if (session.window && session.window.sessionId) {
- return browser.sessions.restore(session.window.sessionId);
+ await browser.sessions.restore(session.tab.sessionId);
+ } else if (session.window && session.window.sessionId) {
+ await browser.sessions.restore(session.window.sessionId);
}
}
- reload(tabId: number, cache: boolean): Promise<void> {
- return browser.tabs.reload(tabId, { bypassCache: cache });
+ async reload(tabId: number, cache: boolean): Promise<void> {
+ await browser.tabs.reload(tabId, { bypassCache: cache });
}
- setPinned(tabId: number, pinned: boolean): Promise<Tab> {
- return browser.tabs.update(tabId, { pinned });
+ async setPinned(tabId: number, pinned: boolean): Promise<void> {
+ await browser.tabs.update(tabId, { pinned });
}
duplicate(id: number): Promise<Tab> {
@@ -100,7 +131,7 @@ export default class TabPresenter {
}
}
-const tabPresenter = new TabPresenter();
+const tabPresenter = new TabPresenterImpl();
tabPresenter.onSelected((tab: any) => {
const cache = new MemoryStorage();
diff --git a/src/background/usecases/AddonEnabledUseCase.ts b/src/background/usecases/AddonEnabledUseCase.ts
index 9abd3dc..51f02e1 100644
--- a/src/background/usecases/AddonEnabledUseCase.ts
+++ b/src/background/usecases/AddonEnabledUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import IndicatorPresenter from '../presenters/IndicatorPresenter';
import TabPresenter from '../presenters/TabPresenter';
import ContentMessageClient from '../infrastructures/ContentMessageClient';
@@ -7,7 +7,7 @@ import ContentMessageClient from '../infrastructures/ContentMessageClient';
export default class AddonEnabledUseCase {
constructor(
private indicatorPresentor: IndicatorPresenter,
- private tabPresenter: TabPresenter,
+ @inject("TabPresenter") private tabPresenter: TabPresenter,
private contentMessageClient: ContentMessageClient,
) {
this.indicatorPresentor.onClick((tab) => {
diff --git a/src/background/usecases/CommandUseCase.ts b/src/background/usecases/CommandUseCase.ts
index 7dba664..d2d707e 100644
--- a/src/background/usecases/CommandUseCase.ts
+++ b/src/background/usecases/CommandUseCase.ts
@@ -14,7 +14,7 @@ import RepeatUseCase from '../usecases/RepeatUseCase';
@injectable()
export default class CommandIndicator {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private windowPresenter: WindowPresenter,
private helpPresenter: HelpPresenter,
@inject("CachedSettingRepository") private cachedSettingRepository: CachedSettingRepository,
@@ -80,7 +80,7 @@ export default class CommandIndicator {
}
const current = await this.tabPresenter.getCurrent();
- const tabs = await this.tabPresenter.getByKeyword(keywords);
+ const tabs = await this.tabPresenter.getByKeyword(keywords, false);
if (tabs.length === 0) {
throw new RangeError('No matching buffer for ' + keywords);
}
diff --git a/src/background/usecases/CompletionsUseCase.ts b/src/background/usecases/CompletionsUseCase.ts
index b75b635..439c81a 100644
--- a/src/background/usecases/CompletionsUseCase.ts
+++ b/src/background/usecases/CompletionsUseCase.ts
@@ -5,17 +5,17 @@ import CompletionsRepository from '../repositories/CompletionsRepository';
import CachedSettingRepository from '../repositories/CachedSettingRepository';
import TabPresenter from '../presenters/TabPresenter';
import Properties from '../../shared/settings/Properties';
-import CompletionUseCase from "../completion/CompletionUseCase";
+import OpenCompletionUseCase from "../completion/OpenCompletionUseCase";
type Tab = browser.tabs.Tab;
@injectable()
export default class CompletionsUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private completionsRepository: CompletionsRepository,
@inject("CachedSettingRepository") private cachedSettingRepository: CachedSettingRepository,
- private completionUseCase: CompletionUseCase
+ private completionUseCase: OpenCompletionUseCase
) {
}
diff --git a/src/background/usecases/ConsoleUseCase.ts b/src/background/usecases/ConsoleUseCase.ts
index 775a1e0..2de5bc1 100644
--- a/src/background/usecases/ConsoleUseCase.ts
+++ b/src/background/usecases/ConsoleUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import ConsoleClient from '../infrastructures/ConsoleClient';
@@ -6,7 +6,7 @@ import ConsoleClient from '../infrastructures/ConsoleClient';
export default class ConsoleUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private consoleClient: ConsoleClient,
) {
}
diff --git a/src/background/usecases/FindUseCase.ts b/src/background/usecases/FindUseCase.ts
index b8593c6..cb41cd5 100644
--- a/src/background/usecases/FindUseCase.ts
+++ b/src/background/usecases/FindUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import FindRepository from '../repositories/FindRepository';
import TabPresenter from '../presenters/TabPresenter';
import ConsoleClient from '../infrastructures/ConsoleClient';
@@ -6,7 +6,7 @@ import ConsoleClient from '../infrastructures/ConsoleClient';
@injectable()
export default class FindUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private findRepository: FindRepository,
private consoleClient: ConsoleClient,
) {
diff --git a/src/background/usecases/LinkUseCase.ts b/src/background/usecases/LinkUseCase.ts
index 9c0eab5..be076c7 100644
--- a/src/background/usecases/LinkUseCase.ts
+++ b/src/background/usecases/LinkUseCase.ts
@@ -1,10 +1,10 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class LinkUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
) {
}
diff --git a/src/background/usecases/MarkUseCase.ts b/src/background/usecases/MarkUseCase.ts
index eeac40f..2c0bc13 100644
--- a/src/background/usecases/MarkUseCase.ts
+++ b/src/background/usecases/MarkUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import MarkRepository from '../repositories/MarkRepository';
import ConsoleClient from '../infrastructures/ConsoleClient';
@@ -7,7 +7,7 @@ import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class MarkUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private markRepository: MarkRepository,
private consoleClient: ConsoleClient,
private contentMessageClient: ContentMessageClient,
diff --git a/src/background/usecases/NavigateUseCase.ts b/src/background/usecases/NavigateUseCase.ts
index 25e7f20..3aa1ed6 100644
--- a/src/background/usecases/NavigateUseCase.ts
+++ b/src/background/usecases/NavigateUseCase.ts
@@ -1,11 +1,11 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import NavigateClient from '../clients/NavigateClient';
import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class NavigateUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private navigateClient: NavigateClient,
) {
}
diff --git a/src/background/usecases/TabSelectUseCase.ts b/src/background/usecases/TabSelectUseCase.ts
index 62098de..271bb6c 100644
--- a/src/background/usecases/TabSelectUseCase.ts
+++ b/src/background/usecases/TabSelectUseCase.ts
@@ -1,10 +1,10 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class TabSelectUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
) {
}
diff --git a/src/background/usecases/TabUseCase.ts b/src/background/usecases/TabUseCase.ts
index 66f8573..418dde5 100644
--- a/src/background/usecases/TabUseCase.ts
+++ b/src/background/usecases/TabUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'tsyringe';
+import {inject, injectable} from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import WindowPresenter from '../presenters/WindowPresenter';
import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
@@ -6,7 +6,7 @@ import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
@injectable()
export default class TabUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
private windowPresenter: WindowPresenter,
private browserSettingRepository: BrowserSettingRepository,
) {
diff --git a/src/background/usecases/VersionUseCase.ts b/src/background/usecases/VersionUseCase.ts
index 9ea8af9..21a5e2c 100644
--- a/src/background/usecases/VersionUseCase.ts
+++ b/src/background/usecases/VersionUseCase.ts
@@ -5,7 +5,7 @@ import Notifier from '../presenters/Notifier';
@injectable()
export default class VersionUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
@inject("Notifier") private notifier: Notifier,
) {
}
diff --git a/src/background/usecases/ZoomUseCase.ts b/src/background/usecases/ZoomUseCase.ts
index f598871..ca1368d 100644
--- a/src/background/usecases/ZoomUseCase.ts
+++ b/src/background/usecases/ZoomUseCase.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'tsyringe';
+import { inject, injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
const ZOOM_SETTINGS: number[] = [
@@ -9,7 +9,7 @@ const ZOOM_SETTINGS: number[] = [
@injectable()
export default class ZoomUseCase {
constructor(
- private tabPresenter: TabPresenter,
+ @inject('TabPresenter') private tabPresenter: TabPresenter,
) {
}