Repeat open, tabopen and winopen command
This commit is contained in:
parent
a2ee6897bf
commit
48e005dc82
7 changed files with 93 additions and 4 deletions
|
@ -105,6 +105,9 @@ export default class OperationController {
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
case operations.INTERNAL_OPEN_URL:
|
||||||
|
return this.tabUseCase.openURL(
|
||||||
|
operation.url, operation.newTab, operation.newWindow);
|
||||||
}
|
}
|
||||||
throw new Error('unknown operation: ' + operation.type);
|
throw new Error('unknown operation: ' + operation.type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { injectable } from 'tsyringe';
|
import { injectable } from 'tsyringe';
|
||||||
|
import * as operations from '../../shared/operations';
|
||||||
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,6 +8,7 @@ import SettingRepository from '../repositories/SettingRepository';
|
||||||
import BookmarkRepository from '../repositories/BookmarkRepository';
|
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';
|
||||||
|
import RepeatUseCase from '../usecases/RepeatUseCase';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class CommandIndicator {
|
export default class CommandIndicator {
|
||||||
|
@ -17,21 +19,36 @@ export default class CommandIndicator {
|
||||||
private bookmarkRepository: BookmarkRepository,
|
private bookmarkRepository: BookmarkRepository,
|
||||||
private consoleClient: ConsoleClient,
|
private consoleClient: ConsoleClient,
|
||||||
private contentMessageClient: ContentMessageClient,
|
private contentMessageClient: ContentMessageClient,
|
||||||
|
private repeatUseCase: RepeatUseCase,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async open(keywords: string): Promise<browser.tabs.Tab> {
|
async open(keywords: string): Promise<browser.tabs.Tab> {
|
||||||
let url = await this.urlOrSearch(keywords);
|
let url = await this.urlOrSearch(keywords);
|
||||||
|
this.repeatUseCase.storeLastOperation({
|
||||||
|
type: operations.INTERNAL_OPEN_URL,
|
||||||
|
url,
|
||||||
|
});
|
||||||
return this.tabPresenter.open(url);
|
return this.tabPresenter.open(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
async tabopen(keywords: string): Promise<browser.tabs.Tab> {
|
async tabopen(keywords: string): Promise<browser.tabs.Tab> {
|
||||||
let url = await this.urlOrSearch(keywords);
|
let url = await this.urlOrSearch(keywords);
|
||||||
|
this.repeatUseCase.storeLastOperation({
|
||||||
|
type: operations.INTERNAL_OPEN_URL,
|
||||||
|
url,
|
||||||
|
newTab: true,
|
||||||
|
});
|
||||||
return this.tabPresenter.create(url);
|
return this.tabPresenter.create(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
async winopen(keywords: string): Promise<browser.windows.Window> {
|
async winopen(keywords: string): Promise<browser.windows.Window> {
|
||||||
let url = await this.urlOrSearch(keywords);
|
let url = await this.urlOrSearch(keywords);
|
||||||
|
this.repeatUseCase.storeLastOperation({
|
||||||
|
type: operations.INTERNAL_OPEN_URL,
|
||||||
|
url,
|
||||||
|
newWindow: true,
|
||||||
|
});
|
||||||
return this.windowPresenter.create(url);
|
return this.windowPresenter.create(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ export default class RepeatUseCase {
|
||||||
case operations.ZOOM_IN:
|
case operations.ZOOM_IN:
|
||||||
case operations.ZOOM_OUT:
|
case operations.ZOOM_OUT:
|
||||||
case operations.ZOOM_NEUTRAL:
|
case operations.ZOOM_NEUTRAL:
|
||||||
|
case operations.INTERNAL_OPEN_URL:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { injectable } from 'tsyringe';
|
import { injectable } from 'tsyringe';
|
||||||
import TabPresenter from '../presenters/TabPresenter';
|
import TabPresenter from '../presenters/TabPresenter';
|
||||||
|
import WindowPresenter from '../presenters/WindowPresenter';
|
||||||
import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
|
import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class TabUseCase {
|
export default class TabUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private tabPresenter: TabPresenter,
|
private tabPresenter: TabPresenter,
|
||||||
|
private windowPresenter: WindowPresenter,
|
||||||
private browserSettingRepository: BrowserSettingRepository,
|
private browserSettingRepository: BrowserSettingRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
@ -77,4 +79,17 @@ export default class TabUseCase {
|
||||||
this.tabPresenter.create(url);
|
this.tabPresenter.create(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async openURL(
|
||||||
|
url: string, newTab?: boolean, newWindow?: boolean,
|
||||||
|
): Promise<void> {
|
||||||
|
if (newWindow) {
|
||||||
|
await this.windowPresenter.create(url);
|
||||||
|
} else if (newTab) {
|
||||||
|
await this.tabPresenter.create(url);
|
||||||
|
} else {
|
||||||
|
let tab = await this.tabPresenter.getCurrent();
|
||||||
|
await this.tabPresenter.open(url, tab.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,10 @@ import * as messages from '../../shared/messages';
|
||||||
|
|
||||||
export default interface OperationClient {
|
export default interface OperationClient {
|
||||||
execBackgroundOp(op: operations.Operation): Promise<void>;
|
execBackgroundOp(op: operations.Operation): Promise<void>;
|
||||||
|
|
||||||
|
internalOpenUrl(
|
||||||
|
url: string, newTab?: boolean, background?: boolean,
|
||||||
|
): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OperationClientImpl implements OperationClient {
|
export class OperationClientImpl implements OperationClient {
|
||||||
|
@ -12,4 +16,18 @@ export class OperationClientImpl implements OperationClient {
|
||||||
operation: op,
|
operation: op,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internalOpenUrl(
|
||||||
|
url: string, newTab?: boolean, background?: boolean,
|
||||||
|
): Promise<void> {
|
||||||
|
return browser.runtime.sendMessage({
|
||||||
|
type: messages.BACKGROUND_OPERATION,
|
||||||
|
operation: {
|
||||||
|
type: operations.INTERNAL_OPEN_URL,
|
||||||
|
url,
|
||||||
|
newTab,
|
||||||
|
background,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,16 @@ import { injectable, inject } from 'tsyringe';
|
||||||
import * as urls from '../../shared/urls';
|
import * as urls from '../../shared/urls';
|
||||||
import ClipboardRepository from '../repositories/ClipboardRepository';
|
import ClipboardRepository from '../repositories/ClipboardRepository';
|
||||||
import SettingRepository from '../repositories/SettingRepository';
|
import SettingRepository from '../repositories/SettingRepository';
|
||||||
import TabsClient from '../client/TabsClient';
|
|
||||||
import ConsoleClient from '../client/ConsoleClient';
|
import ConsoleClient from '../client/ConsoleClient';
|
||||||
|
import OperationClient from '../client/OperationClient';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class ClipboardUseCase {
|
export default class ClipboardUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
@inject('ClipboardRepository') private repository: ClipboardRepository,
|
@inject('ClipboardRepository') private repository: ClipboardRepository,
|
||||||
@inject('SettingRepository') private settingRepository: SettingRepository,
|
@inject('SettingRepository') private settingRepository: SettingRepository,
|
||||||
@inject('TabsClient') private client: TabsClient,
|
|
||||||
@inject('ConsoleClient') private consoleClient: ConsoleClient,
|
@inject('ConsoleClient') private consoleClient: ConsoleClient,
|
||||||
|
@inject('OperationClient') private operationClinet: OperationClient,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,10 @@ export default class ClipboardUseCase {
|
||||||
let search = this.settingRepository.get().search;
|
let search = this.settingRepository.get().search;
|
||||||
let text = this.repository.read();
|
let text = this.repository.read();
|
||||||
let url = urls.searchUrl(text, search);
|
let url = urls.searchUrl(text, search);
|
||||||
await this.client.openUrl(url, newTab);
|
|
||||||
|
// TODO: Repeat pasting from clipboard instead of opening a certain url.
|
||||||
|
// 'Repeat last' command is implemented in the background script and cannot
|
||||||
|
// access to clipboard until Firefox 63.
|
||||||
|
await this.operationClinet.internalOpenUrl(url, newTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,9 @@ export const MARK_JUMP_PREFIX = 'mark.jump.prefix';
|
||||||
// Repeat
|
// Repeat
|
||||||
export const REPEAT_LAST = 'repeat.last';
|
export const REPEAT_LAST = 'repeat.last';
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
export const INTERNAL_OPEN_URL = 'internal.open.url';
|
||||||
|
|
||||||
export interface CancelOperation {
|
export interface CancelOperation {
|
||||||
type: typeof CANCEL;
|
type: typeof CANCEL;
|
||||||
}
|
}
|
||||||
|
@ -298,6 +301,14 @@ export interface RepeatLastOperation {
|
||||||
type: typeof REPEAT_LAST;
|
type: typeof REPEAT_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InternalOpenUrl {
|
||||||
|
type: typeof INTERNAL_OPEN_URL;
|
||||||
|
url: string;
|
||||||
|
newTab?: boolean;
|
||||||
|
newWindow?: boolean;
|
||||||
|
background?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type Operation =
|
export type Operation =
|
||||||
CancelOperation |
|
CancelOperation |
|
||||||
AddonEnableOperation |
|
AddonEnableOperation |
|
||||||
|
@ -350,7 +361,8 @@ export type Operation =
|
||||||
FindPrevOperation |
|
FindPrevOperation |
|
||||||
MarkSetPrefixOperation |
|
MarkSetPrefixOperation |
|
||||||
MarkJumpPrefixOperation |
|
MarkJumpPrefixOperation |
|
||||||
RepeatLastOperation;
|
RepeatLastOperation |
|
||||||
|
InternalOpenUrl;
|
||||||
|
|
||||||
const assertOptionalBoolean = (obj: any, name: string) => {
|
const assertOptionalBoolean = (obj: any, name: string) => {
|
||||||
if (Object.prototype.hasOwnProperty.call(obj, name) &&
|
if (Object.prototype.hasOwnProperty.call(obj, name) &&
|
||||||
|
@ -366,6 +378,13 @@ const assertRequiredNumber = (obj: any, name: string) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const assertRequiredString = (obj: any, name: string) => {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(obj, name) ||
|
||||||
|
typeof obj[name] !== 'string') {
|
||||||
|
throw new TypeError(`Missing string parameter '${name}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line complexity, max-lines-per-function
|
// eslint-disable-next-line complexity, max-lines-per-function
|
||||||
export const valueOf = (o: any): Operation => {
|
export const valueOf = (o: any): Operation => {
|
||||||
if (!Object.prototype.hasOwnProperty.call(o, 'type')) {
|
if (!Object.prototype.hasOwnProperty.call(o, 'type')) {
|
||||||
|
@ -409,6 +428,18 @@ export const valueOf = (o: any): Operation => {
|
||||||
type: URLS_PASTE,
|
type: URLS_PASTE,
|
||||||
newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab),
|
newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab),
|
||||||
};
|
};
|
||||||
|
case INTERNAL_OPEN_URL:
|
||||||
|
assertOptionalBoolean(o, 'newTab');
|
||||||
|
assertOptionalBoolean(o, 'newWindow');
|
||||||
|
assertOptionalBoolean(o, 'background');
|
||||||
|
assertRequiredString(o, 'url');
|
||||||
|
return {
|
||||||
|
type: INTERNAL_OPEN_URL,
|
||||||
|
url: o.url,
|
||||||
|
newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab),
|
||||||
|
newWindow: Boolean(typeof o.newWindow === undefined ? false : o.newWindow), // eslint-disable-line max-len
|
||||||
|
background: Boolean(typeof o.background === undefined ? true : o.background), // eslint-disable-line max-len
|
||||||
|
};
|
||||||
case CANCEL:
|
case CANCEL:
|
||||||
case ADDON_ENABLE:
|
case ADDON_ENABLE:
|
||||||
case ADDON_DISABLE:
|
case ADDON_DISABLE:
|
||||||
|
|
Reference in a new issue