Types on src/background
This commit is contained in:
parent
0cffb09e24
commit
678020a3a2
48 changed files with 446 additions and 431 deletions
|
@ -1,11 +1,13 @@
|
|||
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
|
||||
|
||||
export default class AddonEnabledController {
|
||||
private addonEnabledUseCase: AddonEnabledUseCase;
|
||||
|
||||
constructor() {
|
||||
this.addonEnabledUseCase = new AddonEnabledUseCase();
|
||||
}
|
||||
|
||||
indicate(enabled) {
|
||||
indicate(enabled: boolean): Promise<any> {
|
||||
return this.addonEnabledUseCase.indicate(enabled);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
import CompletionsUseCase from '../usecases/CompletionsUseCase';
|
||||
import CommandUseCase from '../usecases/CommandUseCase';
|
||||
import Completions from '../domains/Completions';
|
||||
import CompletionGroup from '../domains/CompletionGroup';
|
||||
|
||||
const trimStart = (str) => {
|
||||
const trimStart = (str: string): string => {
|
||||
// NOTE String.trimStart is available on Firefox 61
|
||||
return str.replace(/^\s+/, '');
|
||||
};
|
||||
|
||||
export default class CommandController {
|
||||
private completionsUseCase: CompletionsUseCase;
|
||||
|
||||
private commandIndicator: CommandUseCase;
|
||||
|
||||
constructor() {
|
||||
this.completionsUseCase = new CompletionsUseCase();
|
||||
this.commandIndicator = new CommandUseCase();
|
||||
}
|
||||
|
||||
getCompletions(line) {
|
||||
getCompletions(line: string): Promise<CompletionGroup[]> {
|
||||
let trimmed = trimStart(line);
|
||||
let words = trimmed.split(/ +/);
|
||||
let name = words[0];
|
||||
|
@ -45,11 +49,11 @@ export default class CommandController {
|
|||
case 'set':
|
||||
return this.completionsUseCase.querySet(name, keywords);
|
||||
}
|
||||
return Promise.resolve(Completions.empty());
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
exec(line) {
|
||||
exec(line: string): Promise<any> {
|
||||
let trimmed = trimStart(line);
|
||||
let words = trimmed.split(/ +/);
|
||||
let name = words[0];
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import FindUseCase from '../usecases/FindUseCase';
|
||||
|
||||
export default class FindController {
|
||||
private findUseCase: FindUseCase;
|
||||
|
||||
constructor() {
|
||||
this.findUseCase = new FindUseCase();
|
||||
}
|
||||
|
||||
getKeyword() {
|
||||
getKeyword(): Promise<string> {
|
||||
return this.findUseCase.getKeyword();
|
||||
}
|
||||
|
||||
setKeyword(keyword) {
|
||||
setKeyword(keyword: string): Promise<any> {
|
||||
return this.findUseCase.setKeyword(keyword);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import LinkUseCase from '../usecases/LinkUseCase';
|
||||
|
||||
export default class LinkController {
|
||||
private linkUseCase: LinkUseCase;
|
||||
|
||||
constructor() {
|
||||
this.linkUseCase = new LinkUseCase();
|
||||
}
|
||||
|
||||
openToTab(url, tabId) {
|
||||
this.linkUseCase.openToTab(url, tabId);
|
||||
openToTab(url: string, tabId: number): Promise<void> {
|
||||
return this.linkUseCase.openToTab(url, tabId);
|
||||
}
|
||||
|
||||
openNewTab(url, openerId, background) {
|
||||
this.linkUseCase.openNewTab(url, openerId, background);
|
||||
openNewTab(
|
||||
url: string, openerId: number, background: boolean,
|
||||
): Promise<void> {
|
||||
return this.linkUseCase.openNewTab(url, openerId, background);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import MarkUseCase from '../usecases/MarkUseCase';
|
||||
|
||||
export default class MarkController {
|
||||
private markUseCase: MarkUseCase;
|
||||
|
||||
constructor() {
|
||||
this.markUseCase = new MarkUseCase();
|
||||
}
|
||||
|
||||
setGlobal(key, x, y) {
|
||||
this.markUseCase.setGlobal(key, x, y);
|
||||
setGlobal(key: string, x: number, y: number): Promise<any> {
|
||||
return this.markUseCase.setGlobal(key, x, y);
|
||||
}
|
||||
|
||||
jumpGlobal(key) {
|
||||
this.markUseCase.jumpGlobal(key);
|
||||
jumpGlobal(key: string): Promise<any> {
|
||||
return this.markUseCase.jumpGlobal(key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,16 @@ import TabSelectUseCase from '../usecases/TabSelectUseCase';
|
|||
import ZoomUseCase from '../usecases/ZoomUseCase';
|
||||
|
||||
export default class OperationController {
|
||||
private findUseCase: FindUseCase;
|
||||
|
||||
private consoleUseCase: ConsoleUseCase;
|
||||
|
||||
private tabUseCase: TabUseCase;
|
||||
|
||||
private tabSelectUseCase: TabSelectUseCase;
|
||||
|
||||
private zoomUseCase: ZoomUseCase;
|
||||
|
||||
constructor() {
|
||||
this.findUseCase = new FindUseCase();
|
||||
this.consoleUseCase = new ConsoleUseCase();
|
||||
|
@ -15,7 +25,7 @@ export default class OperationController {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line complexity, max-lines-per-function
|
||||
exec(operation) {
|
||||
exec(operation: any): Promise<any> {
|
||||
switch (operation.type) {
|
||||
case operations.TAB_CLOSE:
|
||||
return this.tabUseCase.close(false);
|
||||
|
@ -72,6 +82,7 @@ export default class OperationController {
|
|||
case operations.CANCEL:
|
||||
return this.consoleUseCase.hideConsole();
|
||||
}
|
||||
throw new Error('unknown operation: ' + operation.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,16 +2,20 @@ import SettingUseCase from '../usecases/SettingUseCase';
|
|||
import ContentMessageClient from '../infrastructures/ContentMessageClient';
|
||||
|
||||
export default class SettingController {
|
||||
private settingUseCase: SettingUseCase;
|
||||
|
||||
private contentMessageClient: ContentMessageClient;
|
||||
|
||||
constructor() {
|
||||
this.settingUseCase = new SettingUseCase();
|
||||
this.contentMessageClient = new ContentMessageClient();
|
||||
}
|
||||
|
||||
getSetting() {
|
||||
getSetting(): any {
|
||||
return this.settingUseCase.get();
|
||||
}
|
||||
|
||||
async reload() {
|
||||
async reload(): Promise<any> {
|
||||
await this.settingUseCase.reload();
|
||||
this.contentMessageClient.broadcastSettingsChanged();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import VersionUseCase from '../usecases/VersionUseCase';
|
||||
|
||||
export default class VersionController {
|
||||
private versionUseCase: VersionUseCase;
|
||||
|
||||
constructor() {
|
||||
this.versionUseCase = new VersionUseCase();
|
||||
}
|
||||
|
||||
notify() {
|
||||
this.versionUseCase.notify();
|
||||
notify(): void {
|
||||
return this.versionUseCase.notify();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import VersionInteractor from '../usecases/version';
|
||||
|
||||
export default class VersionController {
|
||||
constructor() {
|
||||
this.versionInteractor = new VersionInteractor();
|
||||
}
|
||||
|
||||
notifyIfUpdated() {
|
||||
browser.runtime.onInstalled.addListener(() => {
|
||||
return this.versionInteractor.notify();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -8,5 +8,4 @@ export default {
|
|||
bdeletes: 'Close all tabs matched by keywords',
|
||||
quit: 'Close the current tab',
|
||||
quitall: 'Close all tabs',
|
||||
};
|
||||
|
||||
} as {[key: string]: string};
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
export default class CompletionGroup {
|
||||
constructor(name, items) {
|
||||
this.name0 = name;
|
||||
this.items0 = items;
|
||||
}
|
||||
import CompletionItem from './CompletionItem';
|
||||
|
||||
get name() {
|
||||
return this.name0;
|
||||
}
|
||||
|
||||
get items() {
|
||||
return this.items0;
|
||||
}
|
||||
export default interface CompletionGroup {
|
||||
name: string;
|
||||
items: CompletionItem[];
|
||||
// eslint-disable-next-line semi
|
||||
}
|
||||
|
|
|
@ -1,24 +1,7 @@
|
|||
export default class CompletionItem {
|
||||
constructor({ caption, content, url, icon }) {
|
||||
this.caption0 = caption;
|
||||
this.content0 = content;
|
||||
this.url0 = url;
|
||||
this.icon0 = icon;
|
||||
}
|
||||
|
||||
get caption() {
|
||||
return this.caption0;
|
||||
}
|
||||
|
||||
get content() {
|
||||
return this.content0;
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this.url0;
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this.icon0;
|
||||
}
|
||||
export default interface CompletionItem {
|
||||
readonly caption?: string;
|
||||
readonly content?: string;
|
||||
readonly url?: string;
|
||||
readonly icon?: string;
|
||||
// eslint-disable-next-line semi
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
export default class Completions {
|
||||
constructor(groups) {
|
||||
this.g = groups;
|
||||
}
|
||||
|
||||
get groups() {
|
||||
return this.g;
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return this.groups.map(group => ({
|
||||
name: group.name,
|
||||
items: group.items.map(item => ({
|
||||
caption: item.caption,
|
||||
content: item.content,
|
||||
url: item.url,
|
||||
icon: item.icon,
|
||||
})),
|
||||
}));
|
||||
}
|
||||
|
||||
static empty() {
|
||||
return EMPTY_COMPLETIONS;
|
||||
}
|
||||
}
|
||||
|
||||
let EMPTY_COMPLETIONS = new Completions([]);
|
|
@ -1,24 +1,6 @@
|
|||
export default class GlobalMark {
|
||||
constructor(tabId, url, x, y) {
|
||||
this.tabId0 = tabId;
|
||||
this.url0 = url;
|
||||
this.x0 = x;
|
||||
this.y0 = y;
|
||||
}
|
||||
|
||||
get tabId() {
|
||||
return this.tabId0;
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this.url0;
|
||||
}
|
||||
|
||||
get x() {
|
||||
return this.x0;
|
||||
}
|
||||
|
||||
get y() {
|
||||
return this.y0;
|
||||
}
|
||||
export interface GlobalMark {
|
||||
readonly tabId: number;
|
||||
readonly url: string;
|
||||
readonly x: number;
|
||||
readonly y: number;
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
import messages from '../../shared/messages';
|
||||
|
||||
export default class ConsoleClient {
|
||||
showCommand(tabId, command) {
|
||||
showCommand(tabId: number, command: string): Promise<any> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.CONSOLE_SHOW_COMMAND,
|
||||
command,
|
||||
});
|
||||
}
|
||||
|
||||
showFind(tabId) {
|
||||
showFind(tabId: number): Promise<any> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.CONSOLE_SHOW_FIND
|
||||
});
|
||||
}
|
||||
|
||||
showInfo(tabId, message) {
|
||||
showInfo(tabId: number, message: string): Promise<any> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.CONSOLE_SHOW_INFO,
|
||||
text: message,
|
||||
});
|
||||
}
|
||||
|
||||
showError(tabId, message) {
|
||||
showError(tabId: number, message: string): Promise<any> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.CONSOLE_SHOW_ERROR,
|
||||
text: message,
|
||||
});
|
||||
}
|
||||
|
||||
hide(tabId) {
|
||||
hide(tabId: number): Promise<any> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.CONSOLE_HIDE,
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import messages from '../../shared/messages';
|
||||
|
||||
export default class ContentMessageClient {
|
||||
async broadcastSettingsChanged() {
|
||||
async broadcastSettingsChanged(): Promise<void> {
|
||||
let tabs = await browser.tabs.query({});
|
||||
for (let tab of tabs) {
|
||||
if (tab.url.startsWith('about:')) {
|
||||
if (!tab.id || tab.url && tab.url.startsWith('about:')) {
|
||||
continue;
|
||||
}
|
||||
browser.tabs.sendMessage(tab.id, {
|
||||
|
@ -13,20 +13,20 @@ export default class ContentMessageClient {
|
|||
}
|
||||
}
|
||||
|
||||
async getAddonEnabled(tabId) {
|
||||
async getAddonEnabled(tabId: number): Promise<boolean> {
|
||||
let { enabled } = await browser.tabs.sendMessage(tabId, {
|
||||
type: messages.ADDON_ENABLED_QUERY,
|
||||
});
|
||||
}) as { enabled: boolean };
|
||||
return enabled;
|
||||
}
|
||||
|
||||
toggleAddonEnabled(tabId) {
|
||||
toggleAddonEnabled(tabId: number): Promise<void> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.ADDON_TOGGLE_ENABLED,
|
||||
});
|
||||
}
|
||||
|
||||
scrollTo(tabId, x, y) {
|
||||
scrollTo(tabId: number, x: number, y: number): Promise<void> {
|
||||
return browser.tabs.sendMessage(tabId, {
|
||||
type: messages.TAB_SCROLL_TO,
|
||||
x,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import messages from '../../shared/messages';
|
||||
import CompletionGroup from '../domains/CompletionGroup';
|
||||
import CommandController from '../controllers/CommandController';
|
||||
import SettingController from '../controllers/SettingController';
|
||||
import FindController from '../controllers/FindController';
|
||||
|
@ -8,6 +9,22 @@ import OperationController from '../controllers/OperationController';
|
|||
import MarkController from '../controllers/MarkController';
|
||||
|
||||
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};
|
||||
|
||||
constructor() {
|
||||
this.settingController = new SettingController();
|
||||
this.commandController = new CommandController();
|
||||
|
@ -20,20 +37,28 @@ export default class ContentMessageListener {
|
|||
this.consolePorts = {};
|
||||
}
|
||||
|
||||
run() {
|
||||
browser.runtime.onMessage.addListener((message, sender) => {
|
||||
run(): void {
|
||||
browser.runtime.onMessage.addListener((
|
||||
message: any, sender: browser.runtime.MessageSender,
|
||||
) => {
|
||||
try {
|
||||
let ret = this.onMessage(message, sender);
|
||||
let ret = this.onMessage(message, sender.tab as browser.tabs.Tab);
|
||||
if (!(ret instanceof Promise)) {
|
||||
return {};
|
||||
}
|
||||
return ret.catch((e) => {
|
||||
if (!sender.tab || !sender.tab.id) {
|
||||
return;
|
||||
}
|
||||
return browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: messages.CONSOLE_SHOW_ERROR,
|
||||
text: e.message,
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
if (!sender.tab || !sender.tab.id) {
|
||||
return;
|
||||
}
|
||||
return browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: messages.CONSOLE_SHOW_ERROR,
|
||||
text: e.message,
|
||||
|
@ -43,7 +68,7 @@ export default class ContentMessageListener {
|
|||
browser.runtime.onConnect.addListener(this.onConnected.bind(this));
|
||||
}
|
||||
|
||||
onMessage(message, sender) {
|
||||
onMessage(message: any, senderTab: browser.tabs.Tab): Promise<any> | any {
|
||||
switch (message.type) {
|
||||
case messages.CONSOLE_QUERY_COMPLETIONS:
|
||||
return this.onConsoleQueryCompletions(message.text);
|
||||
|
@ -59,7 +84,10 @@ export default class ContentMessageListener {
|
|||
return this.onAddonEnabledResponse(message.enabled);
|
||||
case messages.OPEN_URL:
|
||||
return this.onOpenUrl(
|
||||
message.newTab, message.url, sender.tab.id, message.background);
|
||||
message.newTab,
|
||||
message.url,
|
||||
senderTab.id as number,
|
||||
message.background);
|
||||
case messages.BACKGROUND_OPERATION:
|
||||
return this.onBackgroundOperation(message.operation);
|
||||
case messages.MARK_SET_GLOBAL:
|
||||
|
@ -67,56 +95,60 @@ export default class ContentMessageListener {
|
|||
case messages.MARK_JUMP_GLOBAL:
|
||||
return this.onMarkJumpGlobal(message.key);
|
||||
case messages.CONSOLE_FRAME_MESSAGE:
|
||||
return this.onConsoleFrameMessage(sender.tab.id, message.message);
|
||||
return this.onConsoleFrameMessage(
|
||||
senderTab.id as number, message.message,
|
||||
);
|
||||
}
|
||||
throw new Error('unsupported message: ' + message.type);
|
||||
}
|
||||
|
||||
async onConsoleQueryCompletions(line) {
|
||||
async onConsoleQueryCompletions(line: string): Promise<CompletionGroup[]> {
|
||||
let completions = await this.commandController.getCompletions(line);
|
||||
return Promise.resolve(completions.serialize());
|
||||
return Promise.resolve(completions);
|
||||
}
|
||||
|
||||
onConsoleEnterCommand(text) {
|
||||
onConsoleEnterCommand(text: string): Promise<any> {
|
||||
return this.commandController.exec(text);
|
||||
}
|
||||
|
||||
|
||||
onSettingsQuery() {
|
||||
onSettingsQuery(): Promise<any> {
|
||||
return this.settingController.getSetting();
|
||||
}
|
||||
|
||||
onFindGetKeyword() {
|
||||
onFindGetKeyword(): Promise<string> {
|
||||
return this.findController.getKeyword();
|
||||
}
|
||||
|
||||
onFindSetKeyword(keyword) {
|
||||
onFindSetKeyword(keyword: string): Promise<any> {
|
||||
return this.findController.setKeyword(keyword);
|
||||
}
|
||||
|
||||
onAddonEnabledResponse(enabled) {
|
||||
onAddonEnabledResponse(enabled: boolean): Promise<any> {
|
||||
return this.addonEnabledController.indicate(enabled);
|
||||
}
|
||||
|
||||
onOpenUrl(newTab, url, openerId, background) {
|
||||
onOpenUrl(
|
||||
newTab: boolean, url: string, openerId: number, background: boolean,
|
||||
): Promise<any> {
|
||||
if (newTab) {
|
||||
return this.linkController.openNewTab(url, openerId, background);
|
||||
}
|
||||
return this.linkController.openToTab(url, openerId);
|
||||
}
|
||||
|
||||
onBackgroundOperation(operation) {
|
||||
onBackgroundOperation(operation: any): Promise<any> {
|
||||
return this.backgroundOperationController.exec(operation);
|
||||
}
|
||||
|
||||
onMarkSetGlobal(key, x, y) {
|
||||
onMarkSetGlobal(key: string, x: number, y: number): Promise<any> {
|
||||
return this.markController.setGlobal(key, x, y);
|
||||
}
|
||||
|
||||
onMarkJumpGlobal(key) {
|
||||
onMarkJumpGlobal(key: string): Promise<any> {
|
||||
return this.markController.jumpGlobal(key);
|
||||
}
|
||||
|
||||
onConsoleFrameMessage(tabId, message) {
|
||||
onConsoleFrameMessage(tabId: number, message: any): void {
|
||||
let port = this.consolePorts[tabId];
|
||||
if (!port) {
|
||||
return;
|
||||
|
@ -124,12 +156,14 @@ export default class ContentMessageListener {
|
|||
port.postMessage(message);
|
||||
}
|
||||
|
||||
onConnected(port) {
|
||||
onConnected(port: browser.runtime.Port): void {
|
||||
if (port.name !== 'vimvixen-console') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (port.sender && port.sender.tab && port.sender.tab.id) {
|
||||
let id = port.sender.tab.id;
|
||||
this.consolePorts[id] = port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const db = {};
|
||||
const db: {[key: string]: any} = {};
|
||||
|
||||
export default class MemoryStorage {
|
||||
set(name, value) {
|
||||
set(name: string, value: any): void {
|
||||
let data = JSON.stringify(value);
|
||||
if (typeof data === 'undefined') {
|
||||
throw new Error('value is not serializable');
|
||||
|
@ -9,7 +9,7 @@ export default class MemoryStorage {
|
|||
db[name] = data;
|
||||
}
|
||||
|
||||
get(name) {
|
||||
get(name: string): any {
|
||||
let data = db[name];
|
||||
if (!data) {
|
||||
return undefined;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
export default class IndicatorPresenter {
|
||||
indicate(enabled) {
|
||||
indicate(enabled: boolean): Promise<void> {
|
||||
let path = enabled
|
||||
? 'resources/enabled_32x32.png'
|
||||
: 'resources/disabled_32x32.png';
|
||||
return browser.browserAction.setIcon({ path });
|
||||
}
|
||||
|
||||
onClick(listener) {
|
||||
onClick(listener: (arg: browser.tabs.Tab) => void): void {
|
||||
browser.browserAction.onClicked.addListener(listener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
const NOTIFICATION_ID = 'vimvixen-update';
|
||||
|
||||
export default class NotifyPresenter {
|
||||
notify(title, message, onclick) {
|
||||
const listener = (id) => {
|
||||
notify(
|
||||
title: string,
|
||||
message: string,
|
||||
onclick: () => void,
|
||||
): Promise<string> {
|
||||
const listener = (id: string) => {
|
||||
if (id !== NOTIFICATION_ID) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,27 +3,29 @@ import MemoryStorage from '../infrastructures/MemoryStorage';
|
|||
const CURRENT_SELECTED_KEY = 'tabs.current.selected';
|
||||
const LAST_SELECTED_KEY = 'tabs.last.selected';
|
||||
|
||||
type Tab = browser.tabs.Tab;
|
||||
|
||||
export default class TabPresenter {
|
||||
open(url, tabId) {
|
||||
open(url: string, tabId?: number): Promise<Tab> {
|
||||
return browser.tabs.update(tabId, { url });
|
||||
}
|
||||
|
||||
create(url, opts) {
|
||||
create(url: string, opts?: object): Promise<Tab> {
|
||||
return browser.tabs.create({ url, ...opts });
|
||||
}
|
||||
|
||||
async getCurrent() {
|
||||
async getCurrent(): Promise<Tab> {
|
||||
let tabs = await browser.tabs.query({
|
||||
active: true, currentWindow: true
|
||||
});
|
||||
return tabs[0];
|
||||
}
|
||||
|
||||
getAll() {
|
||||
getAll(): Promise<Tab[]> {
|
||||
return browser.tabs.query({ currentWindow: true });
|
||||
}
|
||||
|
||||
async getLastSelectedId() {
|
||||
async getLastSelectedId(): Promise<number | undefined> {
|
||||
let cache = new MemoryStorage();
|
||||
let tabId = await cache.get(LAST_SELECTED_KEY);
|
||||
if (tabId === null || typeof tabId === 'undefined') {
|
||||
|
@ -32,25 +34,25 @@ export default class TabPresenter {
|
|||
return tabId;
|
||||
}
|
||||
|
||||
async getByKeyword(keyword, excludePinned = false) {
|
||||
async getByKeyword(keyword: string, excludePinned = false): Promise<Tab[]> {
|
||||
let tabs = await browser.tabs.query({ currentWindow: true });
|
||||
return tabs.filter((t) => {
|
||||
return t.url.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
return t.url && t.url.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
t.title && t.title.toLowerCase().includes(keyword.toLowerCase());
|
||||
}).filter((t) => {
|
||||
return !(excludePinned && t.pinned);
|
||||
});
|
||||
}
|
||||
|
||||
select(tabId) {
|
||||
select(tabId: number): Promise<Tab> {
|
||||
return browser.tabs.update(tabId, { active: true });
|
||||
}
|
||||
|
||||
remove(ids) {
|
||||
remove(ids: number[]): Promise<void> {
|
||||
return browser.tabs.remove(ids);
|
||||
}
|
||||
|
||||
async reopen() {
|
||||
async reopen(): Promise<any> {
|
||||
let window = await browser.windows.getCurrent();
|
||||
let sessions = await browser.sessions.getRecentlyClosed();
|
||||
let session = sessions.find((s) => {
|
||||
|
@ -59,39 +61,43 @@ export default class TabPresenter {
|
|||
if (!session) {
|
||||
return;
|
||||
}
|
||||
if (session.tab) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
reload(tabId, cache) {
|
||||
reload(tabId: number, cache: boolean): Promise<void> {
|
||||
return browser.tabs.reload(tabId, { bypassCache: cache });
|
||||
}
|
||||
|
||||
setPinned(tabId, pinned) {
|
||||
setPinned(tabId: number, pinned: boolean): Promise<Tab> {
|
||||
return browser.tabs.update(tabId, { pinned });
|
||||
}
|
||||
|
||||
duplicate(id) {
|
||||
duplicate(id: number): Promise<Tab> {
|
||||
return browser.tabs.duplicate(id);
|
||||
}
|
||||
|
||||
getZoom(tabId) {
|
||||
getZoom(tabId: number): Promise<number> {
|
||||
return browser.tabs.getZoom(tabId);
|
||||
}
|
||||
|
||||
setZoom(tabId, factor) {
|
||||
setZoom(tabId: number, factor: number): Promise<void> {
|
||||
return browser.tabs.setZoom(tabId, factor);
|
||||
}
|
||||
|
||||
onSelected(listener) {
|
||||
onSelected(
|
||||
listener: (arg: { tabId: number, windowId: number}) => void,
|
||||
): void {
|
||||
browser.tabs.onActivated.addListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
let tabPresenter = new TabPresenter();
|
||||
tabPresenter.onSelected((tab) => {
|
||||
tabPresenter.onSelected((tab: any) => {
|
||||
let cache = new MemoryStorage();
|
||||
|
||||
let lastId = cache.get(CURRENT_SELECTED_KEY);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default class WindowPresenter {
|
||||
create(url) {
|
||||
create(url: string): Promise<browser.windows.Window> {
|
||||
return browser.windows.create({ url });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
export default class BookmarkRepository {
|
||||
async create(title, url) {
|
||||
async create(
|
||||
title: string, url: string
|
||||
): Promise<browser.bookmarks.BookmarkTreeNode> {
|
||||
let item = await browser.bookmarks.create({
|
||||
type: 'bookmark',
|
||||
title,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as urls from '../../shared/urls';
|
||||
|
||||
export default class BrowserSettingRepository {
|
||||
async getHomepageUrls() {
|
||||
async getHomepageUrls(): Promise<string[]> {
|
||||
let { value } = await browser.browserSettings.homepageOverride.get({});
|
||||
return value.split('|').map(urls.normalizeUrl);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
type Tab = browser.tabs.Tab;
|
||||
type BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
|
||||
|
||||
export default class CompletionsRepository {
|
||||
async queryBookmarks(keywords) {
|
||||
async queryBookmarks(keywords: string): Promise<BookmarkTreeNode[]> {
|
||||
let items = await browser.bookmarks.search({ query: keywords });
|
||||
return items.filter((item) => {
|
||||
if (!item.url) {
|
||||
return false;
|
||||
}
|
||||
let url = undefined;
|
||||
try {
|
||||
url = new URL(item.url);
|
||||
|
@ -12,17 +18,17 @@ export default class CompletionsRepository {
|
|||
});
|
||||
}
|
||||
|
||||
queryHistories(keywords) {
|
||||
queryHistories(keywords: string): Promise<browser.history.HistoryItem[]> {
|
||||
return browser.history.search({
|
||||
text: keywords,
|
||||
startTime: 0,
|
||||
});
|
||||
}
|
||||
|
||||
async queryTabs(keywords, excludePinned) {
|
||||
async queryTabs(keywords: string, excludePinned: boolean): Promise<Tab[]> {
|
||||
let tabs = await browser.tabs.query({ currentWindow: true });
|
||||
return tabs.filter((t) => {
|
||||
return t.url.toLowerCase().includes(keywords.toLowerCase()) ||
|
||||
return t.url && t.url.toLowerCase().includes(keywords.toLowerCase()) ||
|
||||
t.title && t.title.toLowerCase().includes(keywords.toLowerCase());
|
||||
}).filter((t) => {
|
||||
return !(excludePinned && t.pinned);
|
||||
|
|
|
@ -3,15 +3,17 @@ import MemoryStorage from '../infrastructures/MemoryStorage';
|
|||
const FIND_KEYWORD_KEY = 'find-keyword';
|
||||
|
||||
export default class FindRepository {
|
||||
private cache: MemoryStorage;
|
||||
|
||||
constructor() {
|
||||
this.cache = new MemoryStorage();
|
||||
}
|
||||
|
||||
getKeyword() {
|
||||
getKeyword(): Promise<string> {
|
||||
return Promise.resolve(this.cache.get(FIND_KEYWORD_KEY));
|
||||
}
|
||||
|
||||
setKeyword(keyword) {
|
||||
setKeyword(keyword: string): Promise<any> {
|
||||
this.cache.set(FIND_KEYWORD_KEY, keyword);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
|
@ -4,21 +4,23 @@ import GlobalMark from '../domains/GlobalMark';
|
|||
const MARK_KEY = 'mark';
|
||||
|
||||
export default class MarkRepository {
|
||||
private cache: MemoryStorage;
|
||||
|
||||
constructor() {
|
||||
this.cache = new MemoryStorage();
|
||||
}
|
||||
|
||||
getMark(key) {
|
||||
getMark(key: string): Promise<GlobalMark | undefined> {
|
||||
let marks = this.getOrEmptyMarks();
|
||||
let data = marks[key];
|
||||
if (!data) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
let mark = new GlobalMark(data.tabId, data.url, data.x, data.y);
|
||||
let mark = { tabId: data.tabId, url: data.url, x: data.x, y: data.y };
|
||||
return Promise.resolve(mark);
|
||||
}
|
||||
|
||||
setMark(key, mark) {
|
||||
setMark(key: string, mark: GlobalMark): Promise<any> {
|
||||
let marks = this.getOrEmptyMarks();
|
||||
marks[key] = { tabId: mark.tabId, url: mark.url, x: mark.x, y: mark.y };
|
||||
this.cache.set(MARK_KEY, marks);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Setting from '../domains/Setting';
|
||||
|
||||
export default class SettingRepository {
|
||||
async load() {
|
||||
async load(): Promise<any> {
|
||||
let { settings } = await browser.storage.local.get('settings');
|
||||
if (!settings) {
|
||||
return null;
|
||||
|
|
|
@ -3,19 +3,21 @@ import MemoryStorage from '../infrastructures/MemoryStorage';
|
|||
const CACHED_SETTING_KEY = 'setting';
|
||||
|
||||
export default class SettingRepository {
|
||||
private cache: MemoryStorage;
|
||||
|
||||
constructor() {
|
||||
this.cache = new MemoryStorage();
|
||||
}
|
||||
|
||||
get() {
|
||||
get(): Promise<any> {
|
||||
return Promise.resolve(this.cache.get(CACHED_SETTING_KEY));
|
||||
}
|
||||
|
||||
update(value) {
|
||||
update(value: any): any {
|
||||
return this.cache.set(CACHED_SETTING_KEY, value);
|
||||
}
|
||||
|
||||
async setProperty(name, value) {
|
||||
async setProperty(name: string, value: string): Promise<any> {
|
||||
let current = await this.get();
|
||||
current.properties[name] = value;
|
||||
return this.update(current);
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
export default class VersionRepository {
|
||||
async get() {
|
||||
let { version } = await browser.storage.local.get('version');
|
||||
return version;
|
||||
}
|
||||
|
||||
update(version) {
|
||||
return browser.storage.local.set({ version });
|
||||
}
|
||||
}
|
|
@ -3,10 +3,20 @@ import TabPresenter from '../presenters/TabPresenter';
|
|||
import ContentMessageClient from '../infrastructures/ContentMessageClient';
|
||||
|
||||
export default class AddonEnabledUseCase {
|
||||
private indicatorPresentor: IndicatorPresenter;
|
||||
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private contentMessageClient: ContentMessageClient;
|
||||
|
||||
constructor() {
|
||||
this.indicatorPresentor = new IndicatorPresenter();
|
||||
|
||||
this.indicatorPresentor.onClick(tab => this.onIndicatorClick(tab.id));
|
||||
this.indicatorPresentor.onClick((tab) => {
|
||||
if (tab.id) {
|
||||
this.onIndicatorClick(tab.id);
|
||||
}
|
||||
});
|
||||
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.tabPresenter.onSelected(info => this.onTabSelected(info.tabId));
|
||||
|
@ -14,15 +24,15 @@ export default class AddonEnabledUseCase {
|
|||
this.contentMessageClient = new ContentMessageClient();
|
||||
}
|
||||
|
||||
indicate(enabled) {
|
||||
indicate(enabled: boolean): Promise<void> {
|
||||
return this.indicatorPresentor.indicate(enabled);
|
||||
}
|
||||
|
||||
onIndicatorClick(tabId) {
|
||||
onIndicatorClick(tabId: number): Promise<void> {
|
||||
return this.contentMessageClient.toggleAddonEnabled(tabId);
|
||||
}
|
||||
|
||||
async onTabSelected(tabId) {
|
||||
async onTabSelected(tabId: number): Promise<void> {
|
||||
let enabled = await this.contentMessageClient.getAddonEnabled(tabId);
|
||||
return this.indicatorPresentor.indicate(enabled);
|
||||
}
|
||||
|
|
|
@ -6,9 +6,21 @@ import SettingRepository from '../repositories/SettingRepository';
|
|||
import BookmarkRepository from '../repositories/BookmarkRepository';
|
||||
import ConsoleClient from '../infrastructures/ConsoleClient';
|
||||
import ContentMessageClient from '../infrastructures/ContentMessageClient';
|
||||
import * as properties from 'shared/settings/properties';
|
||||
import * as properties from '../../shared/settings/properties';
|
||||
|
||||
export default class CommandIndicator {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private windowPresenter: WindowPresenter;
|
||||
|
||||
private settingRepository: SettingRepository;
|
||||
|
||||
private bookmarkRepository: BookmarkRepository;
|
||||
|
||||
private consoleClient: ConsoleClient;
|
||||
|
||||
private contentMessageClient: ContentMessageClient;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.windowPresenter = new WindowPresenter();
|
||||
|
@ -19,34 +31,34 @@ export default class CommandIndicator {
|
|||
this.contentMessageClient = new ContentMessageClient();
|
||||
}
|
||||
|
||||
async open(keywords) {
|
||||
async open(keywords: string): Promise<browser.tabs.Tab> {
|
||||
let url = await this.urlOrSearch(keywords);
|
||||
return this.tabPresenter.open(url);
|
||||
}
|
||||
|
||||
async tabopen(keywords) {
|
||||
async tabopen(keywords: string): Promise<browser.tabs.Tab> {
|
||||
let url = await this.urlOrSearch(keywords);
|
||||
return this.tabPresenter.create(url);
|
||||
}
|
||||
|
||||
async winopen(keywords) {
|
||||
async winopen(keywords: string): Promise<browser.windows.Window> {
|
||||
let url = await this.urlOrSearch(keywords);
|
||||
return this.windowPresenter.create(url);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-statements
|
||||
async buffer(keywords) {
|
||||
async buffer(keywords: string): Promise<any> {
|
||||
if (keywords.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNaN(keywords)) {
|
||||
if (!isNaN(Number(keywords))) {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
let index = parseInt(keywords, 10) - 1;
|
||||
if (index < 0 || tabs.length <= index) {
|
||||
throw new RangeError(`tab ${index + 1} does not exist`);
|
||||
}
|
||||
return this.tabPresenter.select(tabs[index].id);
|
||||
return this.tabPresenter.select(tabs[index].id as number);
|
||||
} else if (keywords.trim() === '%') {
|
||||
// Select current window
|
||||
return;
|
||||
|
@ -66,13 +78,13 @@ export default class CommandIndicator {
|
|||
}
|
||||
for (let tab of tabs) {
|
||||
if (tab.index > current.index) {
|
||||
return this.tabPresenter.select(tab.id);
|
||||
return this.tabPresenter.select(tab.id as number);
|
||||
}
|
||||
}
|
||||
return this.tabPresenter.select(tabs[0].id);
|
||||
return this.tabPresenter.select(tabs[0].id as number);
|
||||
}
|
||||
|
||||
async bdelete(force, keywords) {
|
||||
async bdelete(force: boolean, keywords: string): Promise<any> {
|
||||
let excludePinned = !force;
|
||||
let tabs = await this.tabPresenter.getByKeyword(keywords, excludePinned);
|
||||
if (tabs.length === 0) {
|
||||
|
@ -80,35 +92,35 @@ export default class CommandIndicator {
|
|||
} else if (tabs.length > 1) {
|
||||
throw new Error('More than one match for ' + keywords);
|
||||
}
|
||||
return this.tabPresenter.remove([tabs[0].id]);
|
||||
return this.tabPresenter.remove([tabs[0].id as number]);
|
||||
}
|
||||
|
||||
async bdeletes(force, keywords) {
|
||||
async bdeletes(force: boolean, keywords: string): Promise<any> {
|
||||
let excludePinned = !force;
|
||||
let tabs = await this.tabPresenter.getByKeyword(keywords, excludePinned);
|
||||
let ids = tabs.map(tab => tab.id);
|
||||
let ids = tabs.map(tab => tab.id as number);
|
||||
return this.tabPresenter.remove(ids);
|
||||
}
|
||||
|
||||
async quit() {
|
||||
async quit(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.tabPresenter.remove([tab.id]);
|
||||
return this.tabPresenter.remove([tab.id as number]);
|
||||
}
|
||||
|
||||
async quitAll() {
|
||||
async quitAll(): Promise<any> {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
let ids = tabs.map(tab => tab.id);
|
||||
let ids = tabs.map(tab => tab.id as number);
|
||||
this.tabPresenter.remove(ids);
|
||||
}
|
||||
|
||||
async addbookmark(title) {
|
||||
async addbookmark(title: string): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let item = await this.bookmarkRepository.create(title, tab.url);
|
||||
let message = 'Saved current page: ' + item.url;
|
||||
return this.consoleClient.showInfo(tab.id, message);
|
||||
}
|
||||
|
||||
async set(keywords) {
|
||||
async set(keywords: string): Promise<any> {
|
||||
if (keywords.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -118,7 +130,7 @@ export default class CommandIndicator {
|
|||
return this.contentMessageClient.broadcastSettingsChanged();
|
||||
}
|
||||
|
||||
async urlOrSearch(keywords) {
|
||||
async urlOrSearch(keywords: string): Promise<any> {
|
||||
let settings = await this.settingRepository.get();
|
||||
return urls.searchUrl(keywords, settings.search);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import CompletionItem from '../domains/CompletionItem';
|
||||
import CompletionGroup from '../domains/CompletionGroup';
|
||||
import Completions from '../domains/Completions';
|
||||
import CompletionGroup from '../domains/CompletionGroup';
|
||||
import CommandDocs from '../domains/CommandDocs';
|
||||
import CompletionsRepository from '../repositories/CompletionsRepository';
|
||||
import * as filters from './filters';
|
||||
|
@ -10,14 +9,23 @@ import * as properties from '../../shared/settings/properties';
|
|||
|
||||
const COMPLETION_ITEM_LIMIT = 10;
|
||||
|
||||
type Tab = browser.tabs.Tab;
|
||||
type HistoryItem = browser.history.HistoryItem;
|
||||
|
||||
export default class CompletionsUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private completionsRepository: CompletionsRepository;
|
||||
|
||||
private settingRepository: SettingRepository;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.completionsRepository = new CompletionsRepository();
|
||||
this.settingRepository = new SettingRepository();
|
||||
}
|
||||
|
||||
queryConsoleCommand(prefix) {
|
||||
queryConsoleCommand(prefix: string): Promise<Completions> {
|
||||
let keys = Object.keys(CommandDocs);
|
||||
let items = keys
|
||||
.filter(name => name.startsWith(prefix))
|
||||
|
@ -28,16 +36,14 @@ export default class CompletionsUseCase {
|
|||
}));
|
||||
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve(Completions.empty());
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return Promise.resolve(
|
||||
new Completions([new CompletionGroup('Console Command', items)])
|
||||
);
|
||||
return Promise.resolve([{ name: 'Console CompletionGroup', items }]);
|
||||
}
|
||||
|
||||
async queryOpen(name, keywords) {
|
||||
async queryOpen(name: string, keywords: string): Promise<Completions> {
|
||||
let settings = await this.settingRepository.get();
|
||||
let groups = [];
|
||||
let groups: CompletionGroup[] = [];
|
||||
|
||||
let complete = settings.properties.complete || properties.defaults.complete;
|
||||
for (let c of complete) {
|
||||
|
@ -45,31 +51,31 @@ export default class CompletionsUseCase {
|
|||
// eslint-disable-next-line no-await-in-loop
|
||||
let engines = await this.querySearchEngineItems(name, keywords);
|
||||
if (engines.length > 0) {
|
||||
groups.push(new CompletionGroup('Search Engines', engines));
|
||||
groups.push({ name: 'Search Engines', items: engines });
|
||||
}
|
||||
} else if (c === 'h') {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
let histories = await this.queryHistoryItems(name, keywords);
|
||||
if (histories.length > 0) {
|
||||
groups.push(new CompletionGroup('History', histories));
|
||||
groups.push({ name: 'History', items: histories });
|
||||
}
|
||||
} else if (c === 'b') {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
let bookmarks = await this.queryBookmarkItems(name, keywords);
|
||||
if (bookmarks.length > 0) {
|
||||
groups.push(new CompletionGroup('Bookmarks', bookmarks));
|
||||
groups.push({ name: 'Bookmarks', items: bookmarks });
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Completions(groups);
|
||||
return groups;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-statements
|
||||
async queryBuffer(name, keywords) {
|
||||
async queryBuffer(name: string, keywords: string): Promise<Completions> {
|
||||
let lastId = await this.tabPresenter.getLastSelectedId();
|
||||
let trimmed = keywords.trim();
|
||||
let tabs = [];
|
||||
if (trimmed.length > 0 && !isNaN(trimmed)) {
|
||||
let tabs: Tab[] = [];
|
||||
if (trimmed.length > 0 && !isNaN(Number(trimmed))) {
|
||||
let all = await this.tabPresenter.getAll();
|
||||
let index = parseInt(trimmed, 10) - 1;
|
||||
if (index >= 0 && index < all.length) {
|
||||
|
@ -77,18 +83,18 @@ export default class CompletionsUseCase {
|
|||
}
|
||||
} else if (trimmed === '%') {
|
||||
let all = await this.tabPresenter.getAll();
|
||||
let tab = all.find(t => t.active);
|
||||
let tab = all.find(t => t.active) as Tab;
|
||||
tabs = [tab];
|
||||
} else if (trimmed === '#') {
|
||||
if (typeof lastId !== 'undefined' && lastId !== null) {
|
||||
let all = await this.tabPresenter.getAll();
|
||||
let tab = all.find(t => t.id === lastId);
|
||||
let tab = all.find(t => t.id === lastId) as Tab;
|
||||
tabs = [tab];
|
||||
}
|
||||
} else {
|
||||
tabs = await this.completionsRepository.queryTabs(keywords, false);
|
||||
}
|
||||
const flag = (tab) => {
|
||||
const flag = (tab: Tab) => {
|
||||
if (tab.active) {
|
||||
return '%';
|
||||
} else if (tab.id === lastId) {
|
||||
|
@ -96,87 +102,90 @@ export default class CompletionsUseCase {
|
|||
}
|
||||
return ' ';
|
||||
};
|
||||
let items = tabs.map(tab => new CompletionItem({
|
||||
let items = tabs.map(tab => ({
|
||||
caption: tab.index + 1 + ': ' + flag(tab) + ' ' + tab.title,
|
||||
content: name + ' ' + tab.title,
|
||||
url: tab.url,
|
||||
icon: tab.favIconUrl
|
||||
icon: tab.favIconUrl,
|
||||
}));
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve(Completions.empty());
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return new Completions([new CompletionGroup('Buffers', items)]);
|
||||
return [{ name: 'Buffers', items }];
|
||||
}
|
||||
|
||||
queryBdelete(name, keywords) {
|
||||
queryBdelete(name: string, keywords: string): Promise<CompletionGroup[]> {
|
||||
return this.queryTabs(name, true, keywords);
|
||||
}
|
||||
|
||||
queryBdeleteForce(name, keywords) {
|
||||
queryBdeleteForce(
|
||||
name: string, keywords: string,
|
||||
): Promise<CompletionGroup[]> {
|
||||
return this.queryTabs(name, false, keywords);
|
||||
}
|
||||
|
||||
querySet(name, keywords) {
|
||||
querySet(name: string, keywords: string): Promise<CompletionGroup[]> {
|
||||
let items = Object.keys(properties.docs).map((key) => {
|
||||
if (properties.types[key] === 'boolean') {
|
||||
return [
|
||||
new CompletionItem({
|
||||
{
|
||||
caption: key,
|
||||
content: name + ' ' + key,
|
||||
url: 'Enable ' + properties.docs[key],
|
||||
}),
|
||||
new CompletionItem({
|
||||
}, {
|
||||
caption: 'no' + key,
|
||||
content: name + ' no' + key,
|
||||
url: 'Disable ' + properties.docs[key],
|
||||
}),
|
||||
}
|
||||
];
|
||||
}
|
||||
return [
|
||||
new CompletionItem({
|
||||
{
|
||||
caption: key,
|
||||
content: name + ' ' + key,
|
||||
url: 'Set ' + properties.docs[key],
|
||||
})
|
||||
}
|
||||
];
|
||||
});
|
||||
items = items.reduce((acc, val) => acc.concat(val), []);
|
||||
items = items.filter((item) => {
|
||||
let flatten = items.reduce((acc, val) => acc.concat(val), []);
|
||||
flatten = flatten.filter((item) => {
|
||||
return item.caption.startsWith(keywords);
|
||||
});
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve(Completions.empty());
|
||||
if (flatten.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return Promise.resolve(
|
||||
new Completions([new CompletionGroup('Properties', items)])
|
||||
[{ name: 'Properties', items: flatten }],
|
||||
);
|
||||
}
|
||||
|
||||
async queryTabs(name, excludePinned, args) {
|
||||
async queryTabs(
|
||||
name: string, excludePinned: boolean, args: string,
|
||||
): Promise<CompletionGroup[]> {
|
||||
let tabs = await this.completionsRepository.queryTabs(args, excludePinned);
|
||||
let items = tabs.map(tab => new CompletionItem({
|
||||
let items = tabs.map(tab => ({
|
||||
caption: tab.title,
|
||||
content: name + ' ' + tab.title,
|
||||
url: tab.url,
|
||||
icon: tab.favIconUrl
|
||||
}));
|
||||
if (items.length === 0) {
|
||||
return Promise.resolve(Completions.empty());
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return new Completions([new CompletionGroup('Buffers', items)]);
|
||||
return [{ name: 'Buffers', items }];
|
||||
}
|
||||
|
||||
async querySearchEngineItems(name, keywords) {
|
||||
async querySearchEngineItems(name: string, keywords: string) {
|
||||
let settings = await this.settingRepository.get();
|
||||
let engines = Object.keys(settings.search.engines)
|
||||
.filter(key => key.startsWith(keywords));
|
||||
return engines.map(key => new CompletionItem({
|
||||
return engines.map(key => ({
|
||||
caption: key,
|
||||
content: name + ' ' + key,
|
||||
}));
|
||||
}
|
||||
|
||||
async queryHistoryItems(name, keywords) {
|
||||
async queryHistoryItems(name: string, keywords: string) {
|
||||
let histories = await this.completionsRepository.queryHistories(keywords);
|
||||
histories = [histories]
|
||||
.map(filters.filterBlankTitle)
|
||||
|
@ -184,19 +193,21 @@ export default class CompletionsUseCase {
|
|||
.map(filters.filterByTailingSlash)
|
||||
.map(pages => filters.filterByPathname(pages, COMPLETION_ITEM_LIMIT))
|
||||
.map(pages => filters.filterByOrigin(pages, COMPLETION_ITEM_LIMIT))[0]
|
||||
.sort((x, y) => x.visitCount < y.visitCount)
|
||||
.sort((x: HistoryItem, y: HistoryItem) => {
|
||||
return Number(x.visitCount) < Number(y.visitCount);
|
||||
})
|
||||
.slice(0, COMPLETION_ITEM_LIMIT);
|
||||
return histories.map(page => new CompletionItem({
|
||||
return histories.map(page => ({
|
||||
caption: page.title,
|
||||
content: name + ' ' + page.url,
|
||||
url: page.url
|
||||
}));
|
||||
}
|
||||
|
||||
async queryBookmarkItems(name, keywords) {
|
||||
async queryBookmarkItems(name: string, keywords: string) {
|
||||
let bookmarks = await this.completionsRepository.queryBookmarks(keywords);
|
||||
return bookmarks.slice(0, COMPLETION_ITEM_LIMIT)
|
||||
.map(page => new CompletionItem({
|
||||
.map(page => ({
|
||||
caption: page.title,
|
||||
content: name + ' ' + page.url,
|
||||
url: page.url
|
||||
|
|
|
@ -2,60 +2,64 @@ import TabPresenter from '../presenters/TabPresenter';
|
|||
import ConsoleClient from '../infrastructures/ConsoleClient';
|
||||
|
||||
export default class ConsoleUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private consoleClient: ConsoleClient;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.consoleClient = new ConsoleClient();
|
||||
}
|
||||
|
||||
async showCommand() {
|
||||
async showCommand(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.consoleClient.showCommand(tab.id, '');
|
||||
return this.consoleClient.showCommand(tab.id as number, '');
|
||||
}
|
||||
|
||||
async showOpenCommand(alter) {
|
||||
async showOpenCommand(alter: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let command = 'open ';
|
||||
if (alter) {
|
||||
command += tab.url;
|
||||
command += tab.url || '';
|
||||
}
|
||||
return this.consoleClient.showCommand(tab.id, command);
|
||||
return this.consoleClient.showCommand(tab.id as number, command);
|
||||
}
|
||||
|
||||
async showTabopenCommand(alter) {
|
||||
async showTabopenCommand(alter: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let command = 'tabopen ';
|
||||
if (alter) {
|
||||
command += tab.url;
|
||||
command += tab.url || '';
|
||||
}
|
||||
return this.consoleClient.showCommand(tab.id, command);
|
||||
return this.consoleClient.showCommand(tab.id as number, command);
|
||||
}
|
||||
|
||||
async showWinopenCommand(alter) {
|
||||
async showWinopenCommand(alter: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let command = 'winopen ';
|
||||
if (alter) {
|
||||
command += tab.url;
|
||||
command += tab.url || '';
|
||||
}
|
||||
return this.consoleClient.showCommand(tab.id, command);
|
||||
return this.consoleClient.showCommand(tab.id as number, command);
|
||||
}
|
||||
|
||||
async showBufferCommand() {
|
||||
async showBufferCommand(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let command = 'buffer ';
|
||||
return this.consoleClient.showCommand(tab.id, command);
|
||||
return this.consoleClient.showCommand(tab.id as number, command);
|
||||
}
|
||||
|
||||
async showAddbookmarkCommand(alter) {
|
||||
async showAddbookmarkCommand(alter: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let command = 'addbookmark ';
|
||||
if (alter) {
|
||||
command += tab.title;
|
||||
command += tab.title || '';
|
||||
}
|
||||
return this.consoleClient.showCommand(tab.id, command);
|
||||
return this.consoleClient.showCommand(tab.id as number, command);
|
||||
}
|
||||
|
||||
async hideConsole() {
|
||||
async hideConsole(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.consoleClient.hide(tab.id);
|
||||
return this.consoleClient.hide(tab.id as number);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,22 +3,28 @@ import TabPresenter from '../presenters/TabPresenter';
|
|||
import ConsoleClient from '../infrastructures/ConsoleClient';
|
||||
|
||||
export default class FindUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private findRepository: FindRepository;
|
||||
|
||||
private consoleClient: ConsoleClient;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.findRepository = new FindRepository();
|
||||
this.consoleClient = new ConsoleClient();
|
||||
}
|
||||
|
||||
getKeyword() {
|
||||
getKeyword(): Promise<string> {
|
||||
return this.findRepository.getKeyword();
|
||||
}
|
||||
|
||||
setKeyword(keyword) {
|
||||
setKeyword(keyword: string): Promise<any> {
|
||||
return this.findRepository.setKeyword(keyword);
|
||||
}
|
||||
|
||||
async findStart() {
|
||||
async findStart(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.consoleClient.showFind(tab.id);
|
||||
return this.consoleClient.showFind(tab.id as number);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import SettingRepository from '../repositories/SettingRepository';
|
||||
import TabPresenter from '../presenters/TabPresenter';
|
||||
|
||||
export default class LinkUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
constructor() {
|
||||
this.settingRepository = new SettingRepository();
|
||||
this.tabPresenter = new TabPresenter();
|
||||
}
|
||||
|
||||
openToTab(url, tabId) {
|
||||
openToTab(url: string, tabId: number): Promise<any> {
|
||||
return this.tabPresenter.open(url, tabId);
|
||||
}
|
||||
|
||||
openNewTab(url, openerId, background) {
|
||||
openNewTab(url: string, openerId: number, background: boolean): Promise<any> {
|
||||
return this.tabPresenter.create(url, {
|
||||
openerTabId: openerId, active: !background
|
||||
});
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import GlobalMark from '../domains/GlobalMark';
|
||||
import TabPresenter from '../presenters/TabPresenter';
|
||||
import MarkRepository from '../repositories/MarkRepository';
|
||||
import ConsoleClient from '../infrastructures/ConsoleClient';
|
||||
import ContentMessageClient from '../infrastructures/ContentMessageClient';
|
||||
|
||||
export default class MarkUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private markRepository: MarkRepository;
|
||||
|
||||
private consoleClient: ConsoleClient;
|
||||
|
||||
private contentMessageClient: ContentMessageClient;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.markRepository = new MarkRepository();
|
||||
|
@ -12,18 +19,19 @@ export default class MarkUseCase {
|
|||
this.contentMessageClient = new ContentMessageClient();
|
||||
}
|
||||
|
||||
async setGlobal(key, x, y) {
|
||||
async setGlobal(key: string, x: number, y: number): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let mark = new GlobalMark(tab.id, tab.url, x, y);
|
||||
let mark = { tabId: tab.id, url: tab.url, x, y };
|
||||
return this.markRepository.setMark(key, mark);
|
||||
}
|
||||
|
||||
async jumpGlobal(key) {
|
||||
async jumpGlobal(key: string): Promise<any> {
|
||||
let current = await this.tabPresenter.getCurrent();
|
||||
|
||||
let mark = await this.markRepository.getMark(key);
|
||||
if (!mark) {
|
||||
return this.consoleClient.showError(current.id, 'Mark is not set');
|
||||
return this.consoleClient.showError(
|
||||
current.id as number, 'Mark is not set');
|
||||
}
|
||||
|
||||
return this.contentMessageClient.scrollTo(
|
||||
|
@ -32,7 +40,7 @@ export default class MarkUseCase {
|
|||
return this.tabPresenter.select(mark.tabId);
|
||||
}).catch(async() => {
|
||||
let tab = await this.tabPresenter.create(mark.url);
|
||||
let mark2 = new GlobalMark(tab.id, mark.url, mark.x, mark.y);
|
||||
let mark2 = { tabId: tab.id, url: mark.url, x: mark.x, y: mark.y };
|
||||
return this.markRepository.setMark(key, mark2);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,16 +4,20 @@ import PersistentSettingRepository from '../repositories/PersistentSettingReposi
|
|||
import SettingRepository from '../repositories/SettingRepository';
|
||||
|
||||
export default class SettingUseCase {
|
||||
private persistentSettingRepository: PersistentSettingRepository;
|
||||
|
||||
private settingRepository: SettingRepository;
|
||||
|
||||
constructor() {
|
||||
this.persistentSettingRepository = new PersistentSettingRepository();
|
||||
this.settingRepository = new SettingRepository();
|
||||
}
|
||||
|
||||
get() {
|
||||
get(): Promise<any> {
|
||||
return this.settingRepository.get();
|
||||
}
|
||||
|
||||
async reload() {
|
||||
async reload(): Promise<any> {
|
||||
let settings = await this.persistentSettingRepository.load();
|
||||
if (!settings) {
|
||||
settings = Setting.defaultSettings();
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import TabPresenter from '../presenters/TabPresenter';
|
||||
|
||||
export default class TabSelectUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
}
|
||||
|
||||
async selectPrev(count) {
|
||||
async selectPrev(count: number): Promise<any> {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
if (tabs.length < 2) {
|
||||
return;
|
||||
|
@ -15,10 +17,10 @@ export default class TabSelectUseCase {
|
|||
return;
|
||||
}
|
||||
let select = (tab.index - count + tabs.length) % tabs.length;
|
||||
return this.tabPresenter.select(tabs[select].id);
|
||||
return this.tabPresenter.select(tabs[select].id as number);
|
||||
}
|
||||
|
||||
async selectNext(count) {
|
||||
async selectNext(count: number): Promise<any> {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
if (tabs.length < 2) {
|
||||
return;
|
||||
|
@ -28,24 +30,24 @@ export default class TabSelectUseCase {
|
|||
return;
|
||||
}
|
||||
let select = (tab.index + count) % tabs.length;
|
||||
return this.tabPresenter.select(tabs[select].id);
|
||||
return this.tabPresenter.select(tabs[select].id as number);
|
||||
}
|
||||
|
||||
async selectFirst() {
|
||||
async selectFirst(): Promise<any> {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
return this.tabPresenter.select(tabs[0].id);
|
||||
return this.tabPresenter.select(tabs[0].id as number);
|
||||
}
|
||||
|
||||
async selectLast() {
|
||||
async selectLast(): Promise<any> {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
return this.tabPresenter.select(tabs[tabs.length - 1].id);
|
||||
return this.tabPresenter.select(tabs[tabs.length - 1].id as number);
|
||||
}
|
||||
|
||||
async selectPrevSelected() {
|
||||
async selectPrevSelected(): Promise<any> {
|
||||
let tabId = await this.tabPresenter.getLastSelectedId();
|
||||
if (tabId === null || typeof tabId === 'undefined') {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.tabPresenter.select(tabId);
|
||||
return this.tabPresenter.select(tabId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,24 @@ import TabPresenter from '../presenters/TabPresenter';
|
|||
import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
|
||||
|
||||
export default class TabUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private browserSettingRepository: BrowserSettingRepository;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.browserSettingRepository = new BrowserSettingRepository();
|
||||
}
|
||||
|
||||
async close(force) {
|
||||
async close(force: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
if (!force && tab.pinned) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this.tabPresenter.remove([tab.id]);
|
||||
return this.tabPresenter.remove([tab.id as number]);
|
||||
}
|
||||
|
||||
async closeRight() {
|
||||
async closeRight(): Promise<any> {
|
||||
let tabs = await this.tabPresenter.getAll();
|
||||
tabs.sort((t1, t2) => t1.index - t2.index);
|
||||
let index = tabs.findIndex(t => t.active);
|
||||
|
@ -25,42 +29,42 @@ export default class TabUseCase {
|
|||
for (let i = index + 1; i < tabs.length; ++i) {
|
||||
let tab = tabs[i];
|
||||
if (!tab.pinned) {
|
||||
this.tabPresenter.remove(tab.id);
|
||||
this.tabPresenter.remove([tab.id as number]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reopen() {
|
||||
reopen(): Promise<any> {
|
||||
return this.tabPresenter.reopen();
|
||||
}
|
||||
|
||||
async reload(cache) {
|
||||
async reload(cache: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.tabPresenter.reload(tab.id, cache);
|
||||
return this.tabPresenter.reload(tab.id as number, cache);
|
||||
}
|
||||
|
||||
async setPinned(pinned) {
|
||||
async setPinned(pinned: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.tabPresenter.setPinned(tab.id, pinned);
|
||||
return this.tabPresenter.setPinned(tab.id as number, pinned);
|
||||
}
|
||||
|
||||
async togglePinned() {
|
||||
async togglePinned(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.tabPresenter.setPinned(tab.id, !tab.pinned);
|
||||
return this.tabPresenter.setPinned(tab.id as number, !tab.pinned);
|
||||
}
|
||||
|
||||
async duplicate() {
|
||||
async duplicate(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.tabPresenter.duplicate(tab.id);
|
||||
return this.tabPresenter.duplicate(tab.id as number);
|
||||
}
|
||||
|
||||
async openPageSource() {
|
||||
async openPageSource(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let url = 'view-source:' + tab.url;
|
||||
return this.tabPresenter.create(url);
|
||||
}
|
||||
|
||||
async openHome(newTab) {
|
||||
async openHome(newTab: boolean): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let urls = await this.browserSettingRepository.getHomepageUrls();
|
||||
if (urls.length === 1 && urls[0] === 'about:home') {
|
||||
|
|
|
@ -3,21 +3,25 @@ import TabPresenter from '../presenters/TabPresenter';
|
|||
import NotifyPresenter from '../presenters/NotifyPresenter';
|
||||
|
||||
export default class VersionUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
private notifyPresenter: NotifyPresenter;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
this.notifyPresenter = new NotifyPresenter();
|
||||
}
|
||||
|
||||
notify() {
|
||||
notify(): Promise<string> {
|
||||
let title = `Vim Vixen ${manifest.version} has been installed`;
|
||||
let message = 'Click here to see release notes';
|
||||
let url = this.releaseNoteUrl(manifest.version);
|
||||
this.notifyPresenter.notify(title, message, () => {
|
||||
return this.notifyPresenter.notify(title, message, () => {
|
||||
this.tabPresenter.create(url);
|
||||
});
|
||||
}
|
||||
|
||||
releaseNoteUrl(version) {
|
||||
releaseNoteUrl(version?: string): string {
|
||||
if (version) {
|
||||
return `https://github.com/ueokande/vim-vixen/releases/tag/${version}`;
|
||||
}
|
||||
|
|
|
@ -1,35 +1,39 @@
|
|||
import TabPresenter from '../presenters/TabPresenter';
|
||||
|
||||
const ZOOM_SETTINGS = [
|
||||
const ZOOM_SETTINGS: number[] = [
|
||||
0.33, 0.50, 0.66, 0.75, 0.80, 0.90, 1.00,
|
||||
1.10, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00
|
||||
];
|
||||
|
||||
export default class ZoomUseCase {
|
||||
private tabPresenter: TabPresenter;
|
||||
|
||||
constructor() {
|
||||
this.tabPresenter = new TabPresenter();
|
||||
}
|
||||
|
||||
async zoomIn(tabId) {
|
||||
async zoomIn(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let current = await this.tabPresenter.getZoom(tab.id);
|
||||
let tabId = tab.id as number;
|
||||
let current = await this.tabPresenter.getZoom(tabId);
|
||||
let factor = ZOOM_SETTINGS.find(f => f > current);
|
||||
if (factor) {
|
||||
return this.tabPresenter.setZoom(tabId, factor);
|
||||
return this.tabPresenter.setZoom(tabId as number, factor);
|
||||
}
|
||||
}
|
||||
|
||||
async zoomOut(tabId) {
|
||||
async zoomOut(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
let current = await this.tabPresenter.getZoom(tab.id);
|
||||
let factor = [].concat(ZOOM_SETTINGS).reverse().find(f => f < current);
|
||||
let tabId = tab.id as number;
|
||||
let current = await this.tabPresenter.getZoom(tabId);
|
||||
let factor = ZOOM_SETTINGS.slice(0).reverse().find(f => f < current);
|
||||
if (factor) {
|
||||
return this.tabPresenter.setZoom(tabId, factor);
|
||||
return this.tabPresenter.setZoom(tabId as number, factor);
|
||||
}
|
||||
}
|
||||
|
||||
zoomNutoral(tabId) {
|
||||
return this.tabPresenter.setZoom(tabId, 1);
|
||||
async zoomNutoral(): Promise<any> {
|
||||
let tab = await this.tabPresenter.getCurrent();
|
||||
return this.tabPresenter.setZoom(tab.id as number, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,40 +1,42 @@
|
|||
const filterHttp = (items) => {
|
||||
let httpsHosts = items.map(x => new URL(x.url))
|
||||
type Item = browser.history.HistoryItem;
|
||||
|
||||
const filterHttp = (items: Item[]): Item[] => {
|
||||
let httpsHosts = items.map(x => new URL(x.url as string))
|
||||
.filter(x => x.protocol === 'https:')
|
||||
.map(x => x.host);
|
||||
httpsHosts = new Set(httpsHosts);
|
||||
let hostsSet = new Set(httpsHosts);
|
||||
|
||||
return items.filter((item) => {
|
||||
let url = new URL(item.url);
|
||||
return url.protocol === 'https:' || !httpsHosts.has(url.host);
|
||||
return items.filter((item: Item) => {
|
||||
let url = new URL(item.url as string);
|
||||
return url.protocol === 'https:' || !hostsSet.has(url.host);
|
||||
});
|
||||
};
|
||||
|
||||
const filterBlankTitle = (items) => {
|
||||
const filterBlankTitle = (items: Item[]): Item[] => {
|
||||
return items.filter(item => item.title && item.title !== '');
|
||||
};
|
||||
|
||||
const filterByTailingSlash = (items) => {
|
||||
let urls = items.map(item => new URL(item.url));
|
||||
const filterByTailingSlash = (items: Item[]): Item[] => {
|
||||
let urls = items.map(item => new URL(item.url as string));
|
||||
let simplePaths = urls
|
||||
.filter(url => url.hash === '' && url.search === '')
|
||||
.map(url => url.origin + url.pathname);
|
||||
simplePaths = new Set(simplePaths);
|
||||
let pathsSet = new Set(simplePaths);
|
||||
|
||||
return items.filter((item) => {
|
||||
let url = new URL(item.url);
|
||||
let url = new URL(item.url as string);
|
||||
if (url.hash !== '' || url.search !== '' ||
|
||||
url.pathname.slice(-1) !== '/') {
|
||||
return true;
|
||||
}
|
||||
return !simplePaths.has(url.origin + url.pathname.slice(0, -1));
|
||||
return !pathsSet.has(url.origin + url.pathname.slice(0, -1));
|
||||
});
|
||||
};
|
||||
|
||||
const filterByPathname = (items, min) => {
|
||||
let hash = {};
|
||||
const filterByPathname = (items: Item[], min: number): Item[] => {
|
||||
let hash: {[key: string]: Item} = {};
|
||||
for (let item of items) {
|
||||
let url = new URL(item.url);
|
||||
let url = new URL(item.url as string);
|
||||
let pathname = url.origin + url.pathname;
|
||||
if (!hash[pathname]) {
|
||||
hash[pathname] = item;
|
||||
|
@ -49,10 +51,10 @@ const filterByPathname = (items, min) => {
|
|||
return filtered;
|
||||
};
|
||||
|
||||
const filterByOrigin = (items, min) => {
|
||||
let hash = {};
|
||||
const filterByOrigin = (items: Item[], min: number): Item[] => {
|
||||
let hash: {[key: string]: Item} = {};
|
||||
for (let item of items) {
|
||||
let origin = new URL(item.url).origin;
|
||||
let origin = new URL(item.url as string).origin;
|
||||
if (!hash[origin]) {
|
||||
hash[origin] = item;
|
||||
} else if (hash[origin].url.length > item.url.length) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const mustNumber = (v) => {
|
||||
const mustNumber = (v: any): number => {
|
||||
let num = Number(v);
|
||||
if (isNaN(num)) {
|
||||
throw new Error('Not number: ' + v);
|
||||
|
@ -6,8 +6,11 @@ const mustNumber = (v) => {
|
|||
return num;
|
||||
};
|
||||
|
||||
const parseSetOption = (word, types) => {
|
||||
let [key, value] = word.split('=');
|
||||
const parseSetOption = (
|
||||
word: string,
|
||||
types: { [key: string]: string },
|
||||
): any[] => {
|
||||
let [key, value]: any[] = word.split('=');
|
||||
if (value === undefined) {
|
||||
value = !key.startsWith('no');
|
||||
key = value ? key : key.slice(2);
|
||||
|
@ -26,6 +29,7 @@ const parseSetOption = (word, types) => {
|
|||
case 'number': return [key, mustNumber(value)];
|
||||
case 'boolean': return [key, value];
|
||||
}
|
||||
throw new Error('Unknown property type: ' + type);
|
||||
};
|
||||
|
||||
export { parseSetOption };
|
||||
|
|
|
@ -90,16 +90,6 @@ class Scroller {
|
|||
}
|
||||
}
|
||||
|
||||
class RoughtScroller {
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
scroll(x, y) {
|
||||
this.element.scrollTo(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
const getScroll = () => {
|
||||
let target = scrollTarget();
|
||||
return { x: target.scrollLeft, y: target.scrollTop };
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import GlobalMark from 'background/domains/GlobalMark';
|
||||
|
||||
describe('background/domains/global-mark', () => {
|
||||
describe('constructor and getter', () => {
|
||||
let mark = new GlobalMark(1, 'http://example.com', 10, 30);
|
||||
expect(mark.tabId).to.equal(1);
|
||||
expect(mark.url).to.equal('http://example.com');
|
||||
expect(mark.x).to.equal(10);
|
||||
expect(mark.y).to.equal(30);
|
||||
});
|
||||
});
|
|
@ -9,12 +9,11 @@ describe('background/repositories/mark', () => {
|
|||
});
|
||||
|
||||
it('get and set', async() => {
|
||||
let mark = new GlobalMark(1, 'http://example.com', 10, 30);
|
||||
let mark = { tabId: 1, url: 'http://example.com', x: 10, y: 30 };
|
||||
|
||||
repository.setMark('A', mark);
|
||||
|
||||
let got = await repository.getMark('A');
|
||||
expect(got).to.be.a('object');
|
||||
expect(got.tabId).to.equal(1);
|
||||
expect(got.url).to.equal('http://example.com');
|
||||
expect(got.x).to.equal(10);
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import VersionRepository from 'background/repositories/Version';
|
||||
|
||||
describe("background/repositories/version", () => {
|
||||
let versionRepository;
|
||||
|
||||
beforeEach(() => {
|
||||
versionRepository = new VersionRepository;
|
||||
});
|
||||
|
||||
describe('#get', () => {
|
||||
beforeEach(() => {
|
||||
return browser.storage.local.remove('version');
|
||||
});
|
||||
|
||||
it('loads saved version', async() => {
|
||||
await browser.storage.local.set({ version: '1.2.3' });
|
||||
let version = await this.versionRepository.get();
|
||||
expect(version).to.equal('1.2.3');
|
||||
});
|
||||
|
||||
it('returns undefined if no versions in storage', async() => {
|
||||
let version = await storage.load();
|
||||
expect(version).to.be.a('undefined');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('saves version string', async() => {
|
||||
await versionRepository.update('2.3.4');
|
||||
let { version } = await browser.storage.local.get('version');
|
||||
expect(version).to.equal('2.3.4');
|
||||
});
|
||||
});
|
||||
});
|
Reference in a new issue