Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Commit b7173a4

Browse files
committed
feat(): config file option for custom url open key on click
1 parent 8a42595 commit b7173a4

File tree

7 files changed

+102
-35
lines changed

7 files changed

+102
-35
lines changed

e2e/app.e2e.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,4 +587,16 @@ it('should copy and paste the text', () => {
587587
.then(() => expect(textOut.endsWith(text)).to.be.true)
588588
});
589589

590+
it('should copy a link on click', () => {
591+
let testString: string = 'http://bleenco.com/';
592+
return this.app.client.waitUntilWindowLoaded()
593+
.then(() => this.app.client.keys(testString + '\r\n'))
594+
.then(() => wait(2000))
595+
.then(() => this.app.client.pause(2000))
596+
.then(() => this.app.client.click('.terminal-instance a'))
597+
.then(() => wait(1000))
598+
.then(() => console.log(this.app.electron.clipboard.getText()))
599+
.then(() => expect(this.app.electron.clipboard.getText()).to.contain(testString));
600+
});
601+
590602
});

src/app/components/window-sidebar/window-sidebar.component.html

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="menu-open" (click)="openSidebar()" *ngIf="!opened">
33
<svg width="124px" height="112px" viewBox="0 0 124 112" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
44
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5-
<g fill-rule="nonzero" fill="#FFFFFF">
5+
<g fill-rule="nonzero" class="theme-fg-fill">
66
<path d="M112,0 L12,0 C5.4,0 0,5.4 0,12 C0,18.6 5.4,24 12,24 L112,24 C118.6,24 124,18.6 124,12 C124,5.4 118.6,0 112,0 Z" id="Shape"></path>
77
<path d="M112,44 L12,44 C5.4,44 0,49.4 0,56 C0,62.6 5.4,68 12,68 L112,68 C118.6,68 124,62.6 124,56 C124,49.4 118.6,44 112,44 Z" id="Shape"></path>
88
<path d="M112,88 L12,88 C5.4,88 0,93.4 0,100 C0,106.6 5.4,112 12,112 L112,112 C118.6,112 124,106.6 124,100 C124,93.4 118.6,88 112,88 Z" id="Shape"></path>
@@ -20,7 +20,7 @@
2020
<span class="sidebar-icon themes" (click)="setMenu($event, 'themes')">
2121
<svg width="240px" height="222px" viewBox="0 0 240 222" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
2222
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
23-
<g id="coding" fill-rule="nonzero" fill="#FFFFFF">
23+
<g id="coding" fill-rule="nonzero" class="theme-fg-fill">
2424
<path d="M218.855,0.257 L20.555,0.257 C9.221,0.257 0,9.474 0,20.803 L0,39.557 L0,152.65 L0,171.403 C0,182.735 9.221,191.955 20.555,191.955 L85.627,191.955 L85.627,206.145 L60.369,206.145 C56.226,206.145 52.869,209.503 52.869,213.645 C52.869,217.788 56.226,221.145 60.369,221.145 L93.127,221.145 L146.273,221.145 L179.033,221.145 C183.176,221.145 186.533,217.788 186.533,213.645 C186.533,209.503 183.176,206.145 179.033,206.145 L153.773,206.145 L153.773,191.955 L218.855,191.955 C230.185,191.955 239.402,182.735 239.402,171.403 L239.402,152.65 L239.402,39.557 L239.402,20.803 C239.402,9.474 230.186,0.257 218.855,0.257 Z M20.555,15.257 L218.856,15.257 C221.915,15.257 224.403,17.745 224.403,20.803 L224.403,32.057 L15,32.057 L15,20.803 C15,17.745 17.492,15.257 20.555,15.257 Z M224.402,145.15 L15,145.15 L15,47.057 L224.402,47.057 L224.402,145.15 Z M138.773,206.145 L100.627,206.145 L100.627,191.955 L138.773,191.955 L138.773,206.145 Z M218.855,176.955 L146.273,176.955 L93.127,176.955 L20.555,176.955 C17.492,176.955 15,174.465 15,171.403 L15,160.15 L224.402,160.15 L224.402,171.403 C224.402,174.465 221.914,176.955 218.855,176.955 Z" id="Shape"></path>
2525
<path d="M98.492,124.769 C100.411,124.769 102.331,124.037 103.795,122.573 L146.133,80.241 C149.063,77.312 149.063,72.563 146.134,69.634 C143.205,66.704 138.456,66.705 135.528,69.633 L93.19,111.965 C90.26,114.894 90.26,119.643 93.189,122.571 C94.653,124.036 96.572,124.769 98.492,124.769 Z" id="Shape"></path>
2626
<path d="M72.261,122.571 C73.726,124.036 75.645,124.768 77.565,124.768 C79.484,124.768 81.404,124.036 82.868,122.572 C85.798,119.643 85.798,114.894 82.869,111.966 L67.334,96.429 L82.959,80.805 C85.888,77.875 85.888,73.127 82.959,70.198 C80.029,67.27 75.281,67.27 72.352,70.198 L51.424,91.126 C48.495,94.056 48.495,98.804 51.424,101.732 L72.261,122.571 Z" id="Shape"></path>
@@ -32,7 +32,7 @@
3232
<span class="sidebar-icon shell" (click)="setMenu($event, 'shell')">
3333
<svg width="20px" height="16px" viewBox="0 0 20 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3434
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
35-
<g id="shell-icon" transform="translate(-2.000000, 0.000000)" fill-rule="nonzero" fill="#FFFFFF">
35+
<g id="shell-icon" transform="translate(-2.000000, 0.000000)" fill-rule="nonzero" class="theme-fg-fill">
3636
<g id="Group" transform="translate(2.000000, 0.000000)">
3737
<path d="M2,0 C0.892,0 0,0.892 0,2 L0,14 C0,15.108 0.892,16 2,16 L18,16 C19.108,16 20,15.108 20,14 L20,2 C20,0.892 19.108,0 18,0 L2,0 Z M2,2 L18,2 L18,14 L2,14 L2,2 Z M5.4140625,4 L4,5.4140625 L6.1210938,7.535156 L4,9.65625 L5.4140625,11.070312 L8.949219,7.535156 L5.4140625,4 Z M11,9.070312 L11,11.070312 L16,11.070312 L16,9.070312 L11,9.070312 Z" id="Shape"></path>
3838
</g>
@@ -43,12 +43,22 @@
4343
<span class="sidebar-icon font" (click)="setMenu($event, 'font')">
4444
<svg width="8px" height="8px" viewBox="0 0 8 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
4545
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
46-
<g id="font-icon" fill-rule="nonzero" fill="#FFFFFF">
46+
<g id="font-icon" fill-rule="nonzero" class="theme-fg-fill">
4747
<path d="M7.499,7 L7.375,7 C7.165,7 6.987,6.869 6.912,6.688 L4.466,0.32 C4.464,0.316 4.461,0.313 4.459,0.309 C4.445,0.274 4.421,0.246 4.399,0.215 C4.383,0.192 4.371,0.166 4.351,0.146 C4.334,0.129 4.311,0.119 4.292,0.104 C4.258,0.08 4.226,0.054 4.188,0.039 C4.184,0.037 4.182,0.034 4.179,0.033 C4.158,0.025 4.137,0.027 4.116,0.022 C4.077,0.013 4.04,0.002 4,0.002 C3.959,0.002 3.921,0.013 3.882,0.023 C3.862,0.028 3.841,0.025 3.821,0.033 C3.82,0.033 3.818,0.037 3.817,0.037 C3.691,0.087 3.585,0.184 3.533,0.32 L1.087,6.688 C1.013,6.869 0.835,7 0.625,7 L0.501,7 C0.224,7 0.001,7.224 0.001,7.5 C0.001,7.774 0.224,8 0.501,8 L1.321,8 C1.324,8 1.328,8 1.332,8 L2.5,8 C2.776,8 3,7.774 3,7.5 C3,7.224 2.776,7 2.5,7 L2.406,7 C2.267,7 2.156,6.887 2.156,6.75 C2.156,6.718 2.161,6.688 2.172,6.659 C2.173,6.657 2.168,6.662 2.168,6.66 L2.422,5.998 L5.091,5.998 L5.375,6.757 C5.376,6.758 5.375,6.758 5.375,6.759 C5.416,6.874 5.368,7 5.268,7.059 C5.268,7.059 5.272,7.062 5.272,7.063 C5.111,7.146 5,7.308 5,7.5 C5,7.774 5.223,8 5.5,8 L6.58,8 C6.594,8 6.606,8 6.619,8 L7.499,8 C7.775,8 7.999,7.774 7.999,7.5 C7.999,7.224 7.775,7 7.499,7 Z M2.807,4.998 L3.502,3.187 C3.503,3.185 3.504,3.193 3.506,3.187 C3.558,3.041 3.719,2.963 3.866,3.015 C3.945,3.043 4.006,3.106 4.034,3.18 C4.034,3.18 4.034,3.179 4.034,3.179 L4.716,4.999 L2.807,4.999 L2.807,4.998 Z" id="Shape"></path>
4848
</g>
4949
</g>
5050
</svg>
5151
</span>
52+
<span class="sidebar-icon font" (click)="setMenu($event, 'key')">
53+
<svg width="86px" height="86px" viewBox="0 0 86 86" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
54+
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
55+
<g id="enter-key" fill-rule="nonzero" class="theme-fg-fill">
56+
<path d="M85.5,83 L85.5,3 C85.5,1.619 84.381,0.5 83,0.5 L33,0.5 C31.619,0.5 30.5,1.619 30.5,3 L30.5,45.5 L3,45.5 C1.619,45.5 0.5,46.619 0.5,48 L0.5,83 C0.5,84.381 1.619,85.5 3,85.5 L83,85.5 C84.381,85.5 85.5,84.381 85.5,83 Z M80.5,80.5 L5.5,80.5 L5.5,50.5 L33,50.5 C34.381,50.5 35.5,49.381 35.5,48 L35.5,5.5 L80.5,5.5 L80.5,80.5 Z" id="Shape"></path>
57+
<path d="M31.232,67.268 L38.732,74.768 C39.221,75.256 39.86,75.5 40.5,75.5 C41.14,75.5 41.779,75.256 42.268,74.768 C43.245,73.792 43.245,72.209 42.268,71.233 L39.035,68 L58,68 C59.381,68 60.5,66.881 60.5,65.5 L60.5,58 C60.5,56.619 59.381,55.5 58,55.5 C56.619,55.5 55.5,56.619 55.5,58 L55.5,63 L39.035,63 L42.267,59.768 C43.244,58.792 43.244,57.209 42.267,56.233 C41.29,55.256 39.708,55.256 38.732,56.233 L31.232,63.733 C30.256,64.708 30.256,66.292 31.232,67.268 Z" id="Shape"></path>
58+
</g>
59+
</g>
60+
</svg>
61+
</span>
5262
</div>
5363

5464
<div *ngIf="menu === 'themes'">
@@ -72,5 +82,12 @@ <h1>Font</h1>
7282
</div>
7383
</div>
7484

85+
<div *ngIf="menu === 'key'">
86+
<h1>URL Open Key</h1>
87+
<div class="theme-browser" slimScroll [options]="scrollOptions">
88+
<span *ngFor="let key of availableUrlKeys" (click)="setUrlKey(key)">{{ key }}</span>
89+
</div>
90+
</div>
91+
7592
</div>
7693
</div>

src/app/components/window-sidebar/window-sidebar.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
22
import { ConfigService, IShellDef } from '../../services/config.service';
33
import { SlimScrollOptions } from 'ng2-slimscroll';
44
import { themes } from '../../themes';
5-
import { IFonts, SystemService } from '../../services/system.service';
5+
import { IFonts, IUrlKeys, SystemService } from '../../services/system.service';
66

77
@Component({
88
selector: 'window-sidebar',
@@ -16,10 +16,12 @@ export class WindowSidebarComponent implements OnInit {
1616
selectedTheme: string;
1717
availableFonts: IFonts[];
1818
availableShells: IShellDef[];
19+
availableUrlKeys: IUrlKeys[];
1920

2021
constructor(private config: ConfigService, private _system: SystemService) {
2122
this.availableFonts = [];
2223
this.availableShells = [];
24+
this.availableUrlKeys = this._system.getUrlKeys();
2325

2426
this.menu = 'themes';
2527
this.scrollOptions = new SlimScrollOptions({
@@ -40,6 +42,7 @@ export class WindowSidebarComponent implements OnInit {
4042

4143
setFont(font: string) { this.config.setFont(font); }
4244
setShell(shell: IShellDef) { this.config.setShell(shell); }
45+
setUrlKey(key: IUrlKeys) { this.config.setUrlKey(key); }
4346

4447
previewTheme(theme: string): void {
4548
let styles = { style: themes[theme] };

src/app/components/window-terminal/window-terminal.component.ts

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,18 @@ import { writeFile } from 'fs';
1414
export class WindowTerminalComponent implements OnInit {
1515
@HostBinding('class') class = 'window-terminal';
1616
ctxMenu: Electron.Menu;
17+
ctrlKey: boolean;
18+
selectionTimeout: any;
1719

1820
constructor(
1921
@Inject(XtermService) private xterm: XtermService,
2022
@Inject(ConfigService) private config: ConfigService
21-
) { }
23+
) {}
2224

2325
ngOnInit() {
2426
this.xterm.create();
2527
setTimeout(() => this.config.setConfig());
28+
this.ctrlKey = false;
2629

2730
ipcRenderer.on('newTab', () => this.xterm.create());
2831
ipcRenderer.on('closeTab', () => this.xterm.deleteTab());
@@ -39,30 +42,17 @@ export class WindowTerminalComponent implements OnInit {
3942
});
4043
this.initMenu();
4144

42-
// auto-copy on selection
43-
let selectionTimeout;
44-
document.addEventListener('selectionchange', (e: Event) => {
45-
if (selectionTimeout) {
46-
clearTimeout(selectionTimeout);
45+
ipcRenderer.on('url-clicked', (ev, url) => {
46+
if (this.ctrlKey) {
47+
this.ctrlKey = false;
48+
remote.shell.openExternal(url);
49+
return;
4750
}
4851

49-
selectionTimeout = setTimeout(() => {
50-
this.copy();
51-
}, 800);
52-
}, false);
53-
}
52+
clipboard.writeText(url);
53+
});
54+
5455

55-
@HostListener('click', ['$event']) handleURLClick(event: any) {
56-
if (event.target.tagName === 'A') {
57-
event.preventDefault();
58-
clipboard.writeText(event.target.href);
59-
let isMac = process.platform === 'darwin';
60-
if (isMac && event.metaKey) {
61-
electron.shell.openExternal(event.target.href)
62-
} else if (!isMac && event.ctrlKey) {
63-
electron.shell.openExternal(event.target.href)
64-
}
65-
}
6656
}
6757

6858
initMenu() {
@@ -115,4 +105,22 @@ export class WindowTerminalComponent implements OnInit {
115105
@HostListener('window:resize', ['$event'])
116106
windowResized(ev: any) { this.xterm.fitTerminal(); }
117107

108+
@HostListener('document:click', ['$event'])
109+
clickListener(ev: any) {
110+
if (ev.ctrlKey && this.config.config.settings.urlKey === 'ctrl') { this.ctrlKey = true; return; }
111+
if (ev.metaKey && this.config.config.settings.urlKey === 'meta') { this.ctrlKey = true; return; }
112+
if (ev.shiftKey && this.config.config.settings.urlKey === 'shift') { this.ctrlKey = true; return; }
113+
this.ctrlKey = false;
114+
}
115+
116+
117+
@HostListener('document:selectionchange', ['$event'])
118+
autoCopy(ev: any) {
119+
if (this.selectionTimeout) {
120+
clearTimeout(this.selectionTimeout);
121+
}
122+
this.selectionTimeout = setTimeout(() => { this.copy(); }, 1000);
123+
return false;
124+
}
125+
118126
}

src/app/services/config.service.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Terminal } from './xterm.service';
33
import * as os from 'os';
44
import * as fs from 'fs';
55
import { CssBuilder } from '../../utils';
6+
import { IUrlKeys } from './system.service';
67

78
export interface IShellDef {
89
shell: string;
@@ -88,6 +89,8 @@ export class ConfigService {
8889
this.css.add(`.xterm-color-${index + 1}`, `color: ${color};`);
8990
});
9091

92+
if (!this.config.settings.urlKey) { this.config.settings['urlKey'] = 'shift'; }
93+
9194
this.css.add('html', 'background: ${this.config.style.background} !important;');
9295
this.css.add('.terminal-cursor', `background: ${this.config.style.cursor} !important; color: ${this.config.style.cursor} !important;`);
9396
this.css.add('.terminal-instance .active', `font-size: ${this.config.settings.font_size}px !important;`);
@@ -138,20 +141,26 @@ export class ConfigService {
138141
this.decorateTerminals();
139142
}
140143

144+
updateConfig() {
145+
this.writeConfig();
146+
this.setConfig();
147+
}
148+
141149
setFont(font: string) {
142150
if (this.config && this.config.settings) {
143-
this.config.settings['font'] = font;
151+
this.config.settings['font'] = { family: font, size: this.config.settings.font.size || '13' };
144152
}
145-
146-
this.writeConfig();
147-
this.setConfig();
153+
this.updateConfig();
148154
}
149155

150156
setShell(shell: IShellDef) {
151157
if (this.config && this.config.settings) { this.config.settings['shell'] = shell; }
158+
this.updateConfig();
159+
}
152160

153-
this.writeConfig();
154-
this.setConfig();
161+
setUrlKey(urlkey: IUrlKeys) {
162+
if (this.config && this.config.settings) { this.config.settings['urlKey'] = urlkey.key; }
163+
this.updateConfig();
155164
}
156165

157166
setSidebarConfig(): void {
@@ -206,7 +215,7 @@ export class ConfigService {
206215
}
207216

208217
readConfig(): void {
209-
this.config = JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
218+
this.config = Object.assign({}, this.getDefaultConfig(), JSON.parse(fs.readFileSync(this.configPath, 'utf8')));
210219
}
211220

212221
getDefaultConfig(): any {
@@ -222,7 +231,8 @@ export class ConfigService {
222231
'clipboard_notice': false,
223232
'theme_name': 'AtelierSulphurpool',
224233
'scrollBufferSave': false,
225-
'shells': [ 'bash', 'zsh', 'sh', 'powershell', 'cmd', 'login', 'tcsh', 'csh', 'ash' ]
234+
'shells': [ 'bash', 'zsh', 'sh', 'powershell', 'cmd', 'login', 'tcsh', 'csh', 'ash' ],
235+
'urlKey': 'shift'
226236
},
227237
'style': {
228238
'background': '#090300',

src/app/services/system.service.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export interface IFonts {
1010
toString?: () => string;
1111
};
1212

13+
export interface IUrlKeys {
14+
key: string;
15+
toString?: () => string;
16+
}
1317

1418
@Injectable()
1519
export class SystemService {
@@ -55,6 +59,14 @@ export class SystemService {
5559
});
5660
}
5761

62+
getUrlKeys(): IUrlKeys[] {
63+
return [
64+
{ key: 'ctrl', toString: function() { return this.key.toUpperCase(); } },
65+
{ key: 'shift', toString: function() { return this.key.toUpperCase(); } },
66+
{ key: 'meta', toString: function() { return this.key.toUpperCase(); } }
67+
];
68+
}
69+
5870
}
5971

6072
export let SystemServiceProvider: Provider = {

src/electron.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ app.on('browser-window-created', (e: Event, win: Electron.BrowserWindow) => {
8383
ev.preventDefault();
8484
current.webContents.send('navigate', url);
8585
});
86+
87+
current.webContents.on('new-window', (ev: Electron.Event, url: string) => {
88+
ev.preventDefault();
89+
current.webContents.send('url-clicked', url);
90+
});
8691
});
8792

8893
app.on('browser-window-focus', (e: Event, win: Electron.BrowserWindow) => {

0 commit comments

Comments
 (0)