Compare commits

...

187 Commits

Author SHA1 Message Date
Eugene Pankov
fc501b5e51 Revert "Bump @typescript-eslint/eslint-plugin from 2.26.0 to 2.28.0"
This reverts commit 9f36258c60.
2020-04-20 11:41:26 +02:00
Eugene
3ddec27b69 Merge pull request #2399 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-2.28.0
Bump @typescript-eslint/eslint-plugin from 2.26.0 to 2.28.0
2020-04-20 11:26:02 +02:00
Eugene
6574cf6b50 Merge pull request #2426 from Eugeny/dependabot/npm_and_yarn/electron-builder-22.5.1
Bump electron-builder from 22.4.1 to 22.5.1
2020-04-20 11:25:53 +02:00
Eugene Pankov
d36ef2e48e lint 2020-04-20 11:25:20 +02:00
Eugene Pankov
f8645df60c fixed zmodem encoding (fixes #2352) 2020-04-20 10:55:38 +02:00
Eugene
f69942a3a3 Merge pull request #2434 from Eugeny/dependabot/npm_and_yarn/app/angular/core-9.1.2
Bump @angular/core from 9.1.0 to 9.1.2 in /app
2020-04-20 08:52:50 +02:00
dependabot-preview[bot]
a36431a08c Bump @angular/core from 9.1.0 to 9.1.2 in /app
Bumps [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) from 9.1.0 to 9.1.2.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.2/packages/core)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-20 04:18:26 +00:00
Eugene Pankov
f570d7e428 Merge branch 'master' of github.com:Eugeny/terminus 2020-04-19 16:49:19 +02:00
Eugene Pankov
fb502bc926 smart copying for Windows line breaks (fixes #1558) 2020-04-19 16:46:16 +02:00
Eugene Pankov
2e12041688 limit max html copy length 2020-04-19 16:22:54 +02:00
Eugene Pankov
ca444bcf65 fixed #2411 2020-04-19 16:22:48 +02:00
Eugene
da1b7b9a80 Merge pull request #2432 from Eugeny/dependabot/npm_and_yarn/app/angular/compiler-9.1.2
Bump @angular/compiler from 9.1.0 to 9.1.2 in /app
2020-04-19 16:17:03 +02:00
Eugene
e02d458109 Merge pull request #2431 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-fit-0.4.0-beta.8
Bump xterm-addon-fit from 0.4.0-beta2 to 0.4.0-beta.8 in /terminus-terminal
2020-04-19 16:14:10 +02:00
dependabot-preview[bot]
51e1a19e3e Bump @angular/compiler from 9.1.0 to 9.1.2 in /app
Bumps [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) from 9.1.0 to 9.1.2.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.2/packages/compiler)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-19 14:14:03 +00:00
dependabot-preview[bot]
68869a52e2 Bump xterm-addon-fit in /terminus-terminal
Bumps [xterm-addon-fit](https://github.com/xtermjs/xterm.js) from 0.4.0-beta2 to 0.4.0-beta.8.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-19 14:13:38 +00:00
Eugene
8527c3f531 Merge pull request #2417 from Eugeny/dependabot/npm_and_yarn/style-loader-1.1.4
Bump style-loader from 1.1.3 to 1.1.4
2020-04-19 16:11:14 +02:00
Eugene
4317094f1f Merge pull request #2418 from Eugeny/dependabot/npm_and_yarn/raw-loader-4.0.1
Bump raw-loader from 4.0.0 to 4.0.1
2020-04-19 16:11:07 +02:00
Eugene
00cf7ef67d Merge pull request #2383 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/types/ssh2-0.5.43
Bump @types/ssh2 from 0.5.42 to 0.5.43 in /terminus-ssh
2020-04-19 16:10:43 +02:00
Eugene Pankov
21e7e762cd bumped xterm 2020-04-19 16:06:59 +02:00
Eugene
ebb35cf9be Merge pull request #2385 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-webgl-0.7.0-beta.4
Bump xterm-addon-webgl from 0.6.0-beta.3 to 0.7.0-beta.4 in /terminus-terminal
2020-04-19 15:51:05 +02:00
Eugene
bd7f9a8030 Merge pull request #2384 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-serialize-0.2.0
Bump xterm-addon-serialize from 0.1.2 to 0.2.0 in /terminus-terminal
2020-04-19 15:50:52 +02:00
Eugene
b1e0ed457e Merge pull request #2387 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-4.5.0
Bump xterm from 4.5.0-beta.13 to 4.5.0 in /terminus-terminal
2020-04-19 15:50:34 +02:00
Eugene
59e40d53a1 Merge pull request #2416 from Eugeny/dependabot/npm_and_yarn/app/node-pty-0.10.0-beta8
Bump node-pty from 0.10.0-beta3 to 0.10.0-beta8 in /app
2020-04-19 15:46:12 +02:00
Eugene
666a180f3f Merge pull request #2414 from Eugeny/dependabot/npm_and_yarn/app/angular/platform-browser-dynamic-9.1.2
Bump @angular/platform-browser-dynamic from 9.1.0 to 9.1.2 in /app
2020-04-19 15:45:26 +02:00
Eugene
ffc767c738 Merge pull request #2415 from Eugeny/dependabot/npm_and_yarn/app/keytar-5.5.0
Bump keytar from 5.4.0 to 5.5.0 in /app
2020-04-19 15:45:18 +02:00
dependabot-preview[bot]
49b252f7cf Bump electron-builder from 22.4.1 to 22.5.1
Bumps [electron-builder](https://github.com/electron-userland/electron-builder) from 22.4.1 to 22.5.1.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/commits/v22.5.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-19 13:44:52 +00:00
Eugene
81e9a0c796 Merge pull request #2425 from Eugeny/dependabot/npm_and_yarn/app/angular/common-9.1.2
Bump @angular/common from 9.1.1 to 9.1.2 in /app
2020-04-19 15:44:17 +02:00
Eugene
f3f5b21910 Merge pull request #2427 from Eugeny/dependabot/npm_and_yarn/electron-8.2.3
Bump electron from 8.2.1 to 8.2.3
2020-04-19 15:42:51 +02:00
Eugene Pankov
b29ab2690f WSL2 support - fixes #271 2020-04-19 14:56:31 +02:00
Eugene Pankov
f58cab0820 fixed window toggling with multiple windows (fixes #619) 2020-04-19 11:47:31 +02:00
dependabot-preview[bot]
b21631acd8 Bump electron from 8.2.1 to 8.2.3
Bumps [electron](https://github.com/electron/electron) from 8.2.1 to 8.2.3.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.2.1...v8.2.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-17 04:20:41 +00:00
dependabot-preview[bot]
52258f9949 Bump @angular/common from 9.1.1 to 9.1.2 in /app
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 9.1.1 to 9.1.2.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.2/packages/common)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-17 04:19:35 +00:00
dependabot-preview[bot]
1308e842ce Bump raw-loader from 4.0.0 to 4.0.1
Bumps [raw-loader](https://github.com/webpack-contrib/raw-loader) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/webpack-contrib/raw-loader/releases)
- [Changelog](https://github.com/webpack-contrib/raw-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/raw-loader/compare/v4.0.0...v4.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-16 04:23:49 +00:00
dependabot-preview[bot]
c4ba51f4ee Bump style-loader from 1.1.3 to 1.1.4
Bumps [style-loader](https://github.com/webpack-contrib/style-loader) from 1.1.3 to 1.1.4.
- [Release notes](https://github.com/webpack-contrib/style-loader/releases)
- [Changelog](https://github.com/webpack-contrib/style-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/style-loader/compare/v1.1.3...v1.1.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-16 04:23:10 +00:00
dependabot-preview[bot]
65d411b00d Bump node-pty from 0.10.0-beta3 to 0.10.0-beta8 in /app
Bumps [node-pty](https://github.com/Tyriar/node-pty) from 0.10.0-beta3 to 0.10.0-beta8.
- [Release notes](https://github.com/Tyriar/node-pty/releases)
- [Commits](https://github.com/Tyriar/node-pty/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-16 04:23:09 +00:00
dependabot-preview[bot]
52d596b01b Bump keytar from 5.4.0 to 5.5.0 in /app
Bumps [keytar](https://github.com/atom/node-keytar) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/atom/node-keytar/releases)
- [Commits](https://github.com/atom/node-keytar/compare/v5.4.0...v5.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-16 04:22:32 +00:00
dependabot-preview[bot]
1607dd90ba Bump @angular/platform-browser-dynamic from 9.1.0 to 9.1.2 in /app
Bumps [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) from 9.1.0 to 9.1.2.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.2/packages/platform-browser-dynamic)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-16 04:22:00 +00:00
Eugene
11767f7d27 Merge pull request #2407 from Eugeny/dependabot/npm_and_yarn/app/angular/platform-browser-9.1.1
Bump @angular/platform-browser from 9.1.0 to 9.1.1 in /app
2020-04-15 08:55:31 +02:00
dependabot-preview[bot]
7cbcf6844d Bump @angular/platform-browser from 9.1.0 to 9.1.1 in /app
Bumps [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) from 9.1.0 to 9.1.1.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.1/packages/platform-browser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-15 04:21:00 +00:00
dependabot-preview[bot]
9f36258c60 Bump @typescript-eslint/eslint-plugin from 2.26.0 to 2.28.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.26.0 to 2.28.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.28.0/packages/eslint-plugin)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-14 04:21:13 +00:00
dependabot-preview[bot]
8f964ffc37 Bump xterm from 4.5.0-beta.13 to 4.5.0 in /terminus-terminal
Bumps [xterm](https://github.com/xtermjs/xterm.js) from 4.5.0-beta.13 to 4.5.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/4.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-13 04:19:30 +00:00
dependabot-preview[bot]
4c137996ff Bump xterm-addon-webgl in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.6.0-beta.3 to 0.7.0-beta.4.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-13 04:18:42 +00:00
dependabot-preview[bot]
966bd5f917 Bump xterm-addon-serialize from 0.1.2 to 0.2.0 in /terminus-terminal
Bumps xterm-addon-serialize from 0.1.2 to 0.2.0.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-13 04:18:15 +00:00
dependabot-preview[bot]
b55011d595 Bump @types/ssh2 from 0.5.42 to 0.5.43 in /terminus-ssh
Bumps [@types/ssh2](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ssh2) from 0.5.42 to 0.5.43.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ssh2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-13 04:16:58 +00:00
Eugene
38bd59641e Merge pull request #2366 from Eugeny/dependabot/npm_and_yarn/app/angular/forms-9.1.1
Bump @angular/forms from 9.1.0 to 9.1.1 in /app
2020-04-11 15:06:11 +02:00
Eugene
c449b60940 Merge pull request #2361 from Eugeny/dependabot/npm_and_yarn/app/angular/common-9.1.1
Bump @angular/common from 9.1.0 to 9.1.1 in /app
2020-04-11 15:06:02 +02:00
Eugene
ee618cdd1f Merge pull request #2378 from Eugeny/dependabot/npm_and_yarn/terminus-plugin-manager/semver-7.2.2
Bump semver from 7.1.1 to 7.2.2 in /terminus-plugin-manager
2020-04-11 15:05:56 +02:00
Eugene
a5bddc21bb Merge pull request #2342 from Eugeny/dependabot/npm_and_yarn/app/rxjs-compat-6.5.5
Bump rxjs-compat from 6.5.4 to 6.5.5 in /app
2020-04-11 15:05:49 +02:00
dependabot-preview[bot]
35bf195f42 Bump rxjs-compat from 6.5.4 to 6.5.5 in /app
Bumps rxjs-compat from 6.5.4 to 6.5.5.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-11 13:05:22 +00:00
Eugene
044c2dda0e Merge pull request #2329 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/types/ssh2-0.5.42
Bump @types/ssh2 from 0.5.41 to 0.5.42 in /terminus-ssh
2020-04-11 15:05:04 +02:00
Eugene
9f2a70fc88 Merge pull request #2336 from Eugeny/dependabot/npm_and_yarn/app/ngx-toastr-12.0.1
Bump ngx-toastr from 12.0.0 to 12.0.1 in /app
2020-04-11 15:04:32 +02:00
dependabot-preview[bot]
409476c729 Bump semver from 7.1.1 to 7.2.2 in /terminus-plugin-manager
Bumps [semver](https://github.com/npm/node-semver) from 7.1.1 to 7.2.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/master/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.1.1...v7.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-11 13:04:30 +00:00
Eugene
91f8f25d26 Merge pull request #2338 from Eugeny/dependabot/npm_and_yarn/terminus-core/electron-updater-4.3.0
Bump electron-updater from 4.2.5 to 4.3.0 in /terminus-core
2020-04-11 15:04:12 +02:00
Eugene
f853839939 Merge pull request #2337 from Eugeny/dependabot/npm_and_yarn/app/electron-updater-4.3.0
Bump electron-updater from 4.2.5 to 4.3.0 in /app
2020-04-11 15:04:06 +02:00
Eugene
6099b44723 Merge pull request #2341 from Eugeny/dependabot/npm_and_yarn/app/rxjs-6.5.5
Bump rxjs from 6.5.4 to 6.5.5 in /app
2020-04-11 15:03:47 +02:00
Eugene
e4e8140145 Merge pull request #2351 from Eugeny/dependabot/npm_and_yarn/typedoc-0.17.4
Bump typedoc from 0.17.3 to 0.17.4
2020-04-11 15:03:01 +02:00
Eugene
8b34ab5102 Merge pull request #2356 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-2.27.0
Bump @typescript-eslint/parser from 2.25.0 to 2.27.0
2020-04-11 15:02:48 +02:00
Eugene
6dc987163d Merge pull request #2372 from Eugeny/dependabot/npm_and_yarn/core-js-3.6.5
Bump core-js from 3.6.4 to 3.6.5
2020-04-11 15:01:31 +02:00
Eugene
a082c71a52 Merge pull request #2373 from Eugeny/dependabot/npm_and_yarn/val-loader-2.1.1
Bump val-loader from 2.1.0 to 2.1.1
2020-04-11 15:01:24 +02:00
Eugene
cc37725014 Merge pull request #2374 from Eugeny/dependabot/npm_and_yarn/terminus-core/core-js-3.6.5
Bump core-js from 3.6.4 to 3.6.5 in /terminus-core
2020-04-11 15:01:16 +02:00
Eugene Pankov
c6fd86dca6 lint 2020-04-11 14:34:32 +02:00
Eugene Pankov
7f55d6f1e2 ssh jump hosts - fixes #737 2020-04-11 14:26:20 +02:00
Eugene Pankov
129a7c1a09 use the new selector for profiles 2020-04-11 12:37:46 +02:00
Eugene Pankov
4969c4e2fc option to hide default profiles - fixes #2078 2020-04-11 11:43:55 +02:00
dependabot-preview[bot]
d290fbe933 Bump core-js from 3.6.4 to 3.6.5 in /terminus-core
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.4 to 3.6.5.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/v3.6.5/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.4...v3.6.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-10 04:32:01 +00:00
dependabot-preview[bot]
358d3d82d6 Bump val-loader from 2.1.0 to 2.1.1
Bumps [val-loader](https://github.com/webpack-contrib/val-loader) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/webpack-contrib/val-loader/releases)
- [Changelog](https://github.com/webpack-contrib/val-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/val-loader/compare/v2.1.0...v2.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-10 04:20:18 +00:00
dependabot-preview[bot]
9b560c79ab Bump core-js from 3.6.4 to 3.6.5
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.4 to 3.6.5.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/v3.6.5/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.4...v3.6.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-10 04:19:45 +00:00
dependabot-preview[bot]
8b58bc420d Bump @angular/forms from 9.1.0 to 9.1.1 in /app
Bumps [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) from 9.1.0 to 9.1.1.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.1/packages/forms)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-09 04:19:28 +00:00
Eugene
78a74ffe1b Merge pull request #2357 from Eugeny/dependabot/npm_and_yarn/electron-8.2.1
Bump electron from 8.2.0 to 8.2.1
2020-04-08 11:39:17 +02:00
Eugene
565c675ce1 Merge pull request #2365 from Eugeny/all-contributors/add-orin220444
docs: add orin220444 as a contributor
2020-04-08 11:36:48 +02:00
Eugene
a25a13188d Merge pull request #2364 from orin220444/master
Add an author and license fields
2020-04-08 11:34:46 +02:00
allcontributors[bot]
2daf85f753 docs: update .all-contributorsrc [skip ci] 2020-04-08 09:34:46 +00:00
allcontributors[bot]
3189258fbb docs: update README.md [skip ci] 2020-04-08 09:34:45 +00:00
Orin Serimon
d678bf68c5 add an author field 2020-04-08 16:23:29 +07:00
dependabot-preview[bot]
9498b17b98 Bump @angular/common from 9.1.0 to 9.1.1 in /app
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 9.1.0 to 9.1.1.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.1/packages/common)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-08 04:22:00 +00:00
orin220444
b48a335aed Add a repository field 2020-04-08 00:17:21 +07:00
dependabot-preview[bot]
71488e749a Bump electron from 8.2.0 to 8.2.1
Bumps [electron](https://github.com/electron/electron) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.2.0...v8.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-07 04:26:08 +00:00
dependabot-preview[bot]
0f1cbfa3ee Bump @typescript-eslint/parser from 2.25.0 to 2.27.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.25.0 to 2.27.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.27.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-07 04:25:32 +00:00
dependabot-preview[bot]
32d33bf85e Bump typedoc from 0.17.3 to 0.17.4
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.17.3 to 0.17.4.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/0.17.3...0.17.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-06 04:19:57 +00:00
dependabot-preview[bot]
c7f1aa895d Bump rxjs from 6.5.4 to 6.5.5 in /app
Bumps [rxjs](https://github.com/reactivex/rxjs) from 6.5.4 to 6.5.5.
- [Release notes](https://github.com/reactivex/rxjs/releases)
- [Changelog](https://github.com/ReactiveX/rxjs/blob/6.5.5/CHANGELOG.md)
- [Commits](https://github.com/reactivex/rxjs/compare/6.5.4...6.5.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-03 04:18:12 +00:00
dependabot-preview[bot]
675bc3d281 Bump electron-updater from 4.2.5 to 4.3.0 in /terminus-core
Bumps [electron-updater](https://github.com/electron-userland/electron-builder) from 4.2.5 to 4.3.0.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-02 04:26:29 +00:00
dependabot-preview[bot]
c63ba8c22b Bump electron-updater from 4.2.5 to 4.3.0 in /app
Bumps [electron-updater](https://github.com/electron-userland/electron-builder) from 4.2.5 to 4.3.0.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-02 04:22:51 +00:00
dependabot-preview[bot]
e9be73226e Bump ngx-toastr from 12.0.0 to 12.0.1 in /app
Bumps [ngx-toastr](https://github.com/scttcper/ngx-toastr) from 12.0.0 to 12.0.1.
- [Release notes](https://github.com/scttcper/ngx-toastr/releases)
- [Commits](https://github.com/scttcper/ngx-toastr/compare/v12.0.0...v12.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-02 04:22:18 +00:00
dependabot-preview[bot]
4a72e554b6 Bump @types/ssh2 from 0.5.41 to 0.5.42 in /terminus-ssh
Bumps [@types/ssh2](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ssh2) from 0.5.41 to 0.5.42.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ssh2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-04-01 04:16:03 +00:00
Eugene
33bb3b0722 Merge pull request #2324 from Eugeny/dependabot/npm_and_yarn/eslint-plugin-import-2.20.2
Bump eslint-plugin-import from 2.20.1 to 2.20.2
2020-03-30 20:19:52 +02:00
dependabot-preview[bot]
46b4288c98 Bump eslint-plugin-import from 2.20.1 to 2.20.2
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.20.1 to 2.20.2.
- [Release notes](https://github.com/benmosher/eslint-plugin-import/releases)
- [Changelog](https://github.com/benmosher/eslint-plugin-import/blob/master/CHANGELOG.md)
- [Commits](https://github.com/benmosher/eslint-plugin-import/compare/v2.20.1...v2.20.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 18:05:18 +00:00
Eugene
9477117236 Merge pull request #2323 from Eugeny/dependabot/npm_and_yarn/sentry/cli-1.52.1
Bump @sentry/cli from 1.51.1 to 1.52.1
2020-03-30 20:04:31 +02:00
Eugene
33e048238e Merge pull request #2302 from Eugeny/dependabot/npm_and_yarn/terminus-core/types/js-yaml-3.12.3
Bump @types/js-yaml from 3.12.2 to 3.12.3 in /terminus-core
2020-03-30 20:04:07 +02:00
Eugene
5895d42444 Merge pull request #2300 from Eugeny/dependabot/npm_and_yarn/types/js-yaml-3.12.3
Bump @types/js-yaml from 3.12.1 to 3.12.3
2020-03-30 20:04:02 +02:00
dependabot-preview[bot]
5d6abca503 Bump @sentry/cli from 1.51.1 to 1.52.1
Bumps [@sentry/cli](https://github.com/getsentry/sentry-cli) from 1.51.1 to 1.52.1.
- [Release notes](https://github.com/getsentry/sentry-cli/releases)
- [Changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-cli/compare/1.51.1...1.52.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 18:03:56 +00:00
Eugene
8ca91af927 Merge pull request #2322 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-2.26.0
Bump @typescript-eslint/eslint-plugin from 2.24.0 to 2.26.0
2020-03-30 20:03:53 +02:00
Eugene
c886fd6915 Merge pull request #2304 from Eugeny/dependabot/npm_and_yarn/app/angular/compiler-9.1.0
Bump @angular/compiler from 9.0.7 to 9.1.0 in /app
2020-03-30 20:03:29 +02:00
dependabot-preview[bot]
e403ca6eff Bump @typescript-eslint/eslint-plugin from 2.24.0 to 2.26.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.24.0 to 2.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.26.0/packages/eslint-plugin)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 18:03:14 +00:00
dependabot-preview[bot]
8f1b401137 Bump @angular/compiler from 9.0.7 to 9.1.0 in /app
Bumps [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) from 9.0.7 to 9.1.0.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.0/packages/compiler)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 18:02:54 +00:00
Eugene
0952899204 Merge pull request #2295 from Eugeny/dependabot/npm_and_yarn/app/ng-bootstrap/ng-bootstrap-6.0.2
Bump @ng-bootstrap/ng-bootstrap from 6.0.0 to 6.0.2 in /app
2020-03-30 20:02:38 +02:00
Eugene
a11c643e41 Merge pull request #2292 from Eugeny/dependabot/npm_and_yarn/yaml-loader-0.6.0
Bump yaml-loader from 0.5.0 to 0.6.0
2020-03-30 20:02:29 +02:00
dependabot-preview[bot]
17fbdeafac Bump @ng-bootstrap/ng-bootstrap from 6.0.0 to 6.0.2 in /app
Bumps [@ng-bootstrap/ng-bootstrap](https://github.com/ng-bootstrap/ng-bootstrap) from 6.0.0 to 6.0.2.
- [Release notes](https://github.com/ng-bootstrap/ng-bootstrap/releases)
- [Changelog](https://github.com/ng-bootstrap/ng-bootstrap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ng-bootstrap/ng-bootstrap/compare/6.0.0...6.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 18:02:07 +00:00
Eugene
06e09f3a45 Merge pull request #2291 from Eugeny/dependabot/npm_and_yarn/typedoc-0.17.3
Bump typedoc from 0.17.0 to 0.17.3
2020-03-30 20:02:02 +02:00
Eugene
4fa63aa939 Merge pull request #2296 from Eugeny/dependabot/npm_and_yarn/fortawesome/fontawesome-free-5.13.0
Bump @fortawesome/fontawesome-free from 5.12.1 to 5.13.0
2020-03-30 20:01:39 +02:00
Eugene
46622cd5d9 Merge pull request #2297 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-2.25.0
Bump @typescript-eslint/parser from 2.24.0 to 2.25.0
2020-03-30 20:01:13 +02:00
Eugene
6d3aace1c9 Merge pull request #2299 from Eugeny/dependabot/npm_and_yarn/electron-8.2.0
Bump electron from 8.1.1 to 8.2.0
2020-03-30 20:01:06 +02:00
Eugene Pankov
e3a569be18 Update package.json 2020-03-30 20:00:27 +02:00
Eugene
2a256ef2bd Merge pull request #2316 from Eugeny/dependabot/npm_and_yarn/app/angular/common-9.1.0
Bump @angular/common from 9.0.7 to 9.1.0 in /app
2020-03-30 19:59:47 +02:00
Eugene
4f3fcc8b22 Merge pull request #2318 from CyrilTaylor/dev/serial.narrow_down_the_margin
narrow down the margin of serial tab
2020-03-30 11:03:05 +02:00
Eugene Pankov
045cc0d243 fixed serial modal crash (#2278) 2020-03-30 11:00:48 +02:00
Cyril Taylor
51e33abbe6 narrow down the margin of serial tab 2020-03-30 16:48:35 +08:00
dependabot-preview[bot]
4900c043ca Bump @angular/common from 9.0.7 to 9.1.0 in /app
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 9.0.7 to 9.1.0.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.1.0/packages/common)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-30 04:18:50 +00:00
Eugene Pankov
09d55979ce made warnOnMultilinePaste optional (fixes #2309) 2020-03-29 01:07:08 +01:00
Eugene Pankov
5d431fa9cf disable progress detection when alt buffer is active 2020-03-25 22:59:44 +01:00
Eugene Pankov
113573b2d2 warn on multi-line paste (fixed #2131) 2020-03-25 22:42:15 +01:00
Eugene Pankov
2c3d93608b hotkey to reopen last tab (fixes #2239) 2020-03-25 22:18:24 +01:00
Eugene Pankov
d38af18582 added selection color customization (fixes #2249) 2020-03-25 22:05:25 +01:00
Eugene Pankov
140f7c51f4 fixed #1930 2020-03-25 21:55:20 +01:00
Eugene Pankov
ffa4350420 search direction buttons (fixes #2251) 2020-03-25 21:51:00 +01:00
dependabot-preview[bot]
99737323de Bump @types/js-yaml from 3.12.2 to 3.12.3 in /terminus-core
Bumps [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) from 3.12.2 to 3.12.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/js-yaml)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-25 04:30:48 +00:00
dependabot-preview[bot]
e9e2429632 Bump @types/js-yaml from 3.12.1 to 3.12.3
Bumps [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) from 3.12.1 to 3.12.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/js-yaml)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-25 04:23:50 +00:00
dependabot-preview[bot]
07597ac79a Bump electron from 8.1.1 to 8.2.0
Bumps [electron](https://github.com/electron/electron) from 8.1.1 to 8.2.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.1.1...v8.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-25 04:23:32 +00:00
dependabot-preview[bot]
248ec60612 Bump @typescript-eslint/parser from 2.24.0 to 2.25.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.24.0 to 2.25.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.25.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-24 04:24:24 +00:00
dependabot-preview[bot]
726847d5df Bump @fortawesome/fontawesome-free from 5.12.1 to 5.13.0
Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 5.12.1 to 5.13.0.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/5.12.1...5.13.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-24 04:23:13 +00:00
Eugene Pankov
6065a95132 fixed #2294 2020-03-23 21:15:36 +01:00
dependabot-preview[bot]
e1259475d2 Bump yaml-loader from 0.5.0 to 0.6.0
Bumps [yaml-loader](https://github.com/eemeli/yaml-loader) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/eemeli/yaml-loader/releases)
- [Commits](https://github.com/eemeli/yaml-loader/compare/v0.5.0...v0.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-23 04:22:22 +00:00
dependabot-preview[bot]
ee018e7c02 Bump typedoc from 0.17.0 to 0.17.3
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.17.0 to 0.17.3.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/0.17.0...0.17.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-23 04:21:49 +00:00
Eugene Pankov
db43381f0d use new selector in serial plugin 2020-03-23 01:12:46 +01:00
Eugene Pankov
28c58d4ec0 new ssh connection selector - fixes #1557 2020-03-23 00:39:31 +01:00
Eugene Pankov
68efe2b3c4 fixed #2285 2020-03-22 23:19:48 +01:00
Eugene Pankov
795979be07 color scheme previews (fixes #2286) 2020-03-22 23:17:25 +01:00
Eugene Pankov
c87a1b92d3 Merge branch 'master' of github.com:Eugeny/terminus 2020-03-22 21:36:33 +01:00
Eugene Pankov
2548ad6605 bumped angular 2020-03-22 21:36:24 +01:00
Eugene
b6519c6626 Merge pull request #2273 from Eugeny/dependabot/npm_and_yarn/app/zone.js-0.10.3
Bump zone.js from 0.10.2 to 0.10.3 in /app
2020-03-22 21:33:07 +01:00
Eugene Pankov
2b8bb47aed lint 2020-03-19 12:47:38 +01:00
dependabot-preview[bot]
bbf332171e Bump zone.js from 0.10.2 to 0.10.3 in /app
Bumps [zone.js](https://github.com/angular/angular/tree/HEAD/packages/zone.js) from 0.10.2 to 0.10.3.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/HEAD/packages/zone.js)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-18 04:19:26 +00:00
Eugene
ef5c9b52a5 Merge pull request #2259 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/types/ssh2-0.5.41
Bump @types/ssh2 from 0.5.40 to 0.5.41 in /terminus-ssh
2020-03-17 09:44:27 +01:00
Eugene
4632523d70 Merge pull request #2266 from Eugeny/dependabot/npm_and_yarn/app/yargs-15.3.1
Bump yargs from 15.1.0 to 15.3.1 in /app
2020-03-17 09:43:13 +01:00
Eugene Pankov
56b996e6e4 word separator setting (fixes #508) 2020-03-16 22:52:50 +01:00
Eugene Pankov
0ca0996493 close forwarded ports when session dies (fixes #2143) 2020-03-16 22:47:26 +01:00
dependabot-preview[bot]
e1a8e72742 Bump yargs from 15.1.0 to 15.3.1 in /app
Bumps [yargs](https://github.com/yargs/yargs) from 15.1.0 to 15.3.1.
- [Release notes](https://github.com/yargs/yargs/releases)
- [Changelog](https://github.com/yargs/yargs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/yargs/compare/v15.1.0...v15.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 21:43:43 +00:00
Eugene Pankov
50959f4490 lint 2020-03-16 22:41:59 +01:00
Eugene Pankov
baaebb402e private service constructors 2020-03-16 22:30:11 +01:00
Eugene Pankov
9e862772eb made welcome page scrollable (fixes #2253) 2020-03-16 21:54:55 +01:00
Eugene Pankov
6cb5505ded better tab recovery (fixes #501, fixes #2214, fixes #2185) 2020-03-16 21:40:22 +01:00
Eugene Pankov
eb0d8615e1 Merge branch 'master' of github.com:Eugeny/terminus 2020-03-16 21:36:37 +01:00
Eugene
f2885c2fce Merge pull request #2269 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/ssh2-0.8.9
Bump ssh2 from 0.8.8 to 0.8.9 in /terminus-ssh
2020-03-16 21:36:16 +01:00
dependabot-preview[bot]
c04018bc70 Bump ssh2 from 0.8.8 to 0.8.9 in /terminus-ssh
Bumps [ssh2](https://github.com/mscdex/ssh2) from 0.8.8 to 0.8.9.
- [Release notes](https://github.com/mscdex/ssh2/releases)
- [Commits](https://github.com/mscdex/ssh2/compare/v0.8.8...v0.8.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 20:29:34 +00:00
Eugene Pankov
3e5032ca8b Update yarn.lock 2020-03-16 21:28:33 +01:00
Eugene
a5014243d9 Merge pull request #2268 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/ssh2-streams-0.4.10
Bump ssh2-streams from 0.4.9 to 0.4.10 in /terminus-ssh
2020-03-16 21:28:20 +01:00
dependabot-preview[bot]
2692eb141c Bump ssh2-streams from 0.4.9 to 0.4.10 in /terminus-ssh
Bumps [ssh2-streams](https://github.com/mscdex/ssh2-streams) from 0.4.9 to 0.4.10.
- [Release notes](https://github.com/mscdex/ssh2-streams/releases)
- [Commits](https://github.com/mscdex/ssh2-streams/compare/v0.4.9...v0.4.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 20:25:46 +00:00
Eugene Pankov
b447f1d52e bumped angular 2020-03-16 21:24:07 +01:00
Eugene
606b9af3f1 Merge pull request #2229 from Eugeny/dependabot/npm_and_yarn/electron-8.1.1
Bump electron from 8.0.2 to 8.1.1
2020-03-16 21:21:24 +01:00
dependabot-preview[bot]
3deab9af24 Bump electron from 8.0.2 to 8.1.1
Bumps [electron](https://github.com/electron/electron) from 8.0.2 to 8.1.1.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.0.2...v8.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 20:20:56 +00:00
Eugene
afab0c5cde Merge pull request #2265 from Eugeny/dependabot/npm_and_yarn/app/angular/core-9.0.6
Bump @angular/core from 9.0.4 to 9.0.6 in /app
2020-03-16 21:20:34 +01:00
dependabot-preview[bot]
e1a03f0dfb Bump @angular/core from 9.0.4 to 9.0.6 in /app
Bumps [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) from 9.0.4 to 9.0.6.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.0.6/packages/core)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 20:20:28 +00:00
Eugene
bfe8dfab02 Merge pull request #2145 from Eugeny/dependabot/npm_and_yarn/app/ngx-toastr-12.0.0
Bump ngx-toastr from 10.2.0 to 12.0.0 in /app
2020-03-16 21:20:27 +01:00
Eugene
a4335edc07 Merge pull request #2221 from Eugeny/dependabot/npm_and_yarn/cross-env-7.0.2
Bump cross-env from 7.0.0 to 7.0.2
2020-03-16 21:20:18 +01:00
Eugene
8613698be9 Merge pull request #2231 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-2.23.0
Bump @typescript-eslint/parser from 2.21.0 to 2.23.0
2020-03-16 21:20:06 +01:00
Eugene
731ddc3e28 Merge pull request #2235 from Eugeny/dependabot/npm_and_yarn/electron-rebuild-1.10.1
Bump electron-rebuild from 1.9.0 to 1.10.1
2020-03-16 21:19:55 +01:00
Eugene
2303e32256 Merge pull request #2244 from Eugeny/dependabot/npm_and_yarn/electron-builder-22.4.1
Bump electron-builder from 22.3.6 to 22.4.1
2020-03-16 21:18:57 +01:00
Eugene
9064f123b3 Merge pull request #2242 from Eugeny/dependabot/npm_and_yarn/app/angular/common-9.0.6
Bump @angular/common from 9.0.4 to 9.0.6 in /app
2020-03-16 21:18:19 +01:00
Eugene
9d3ee4a612 Merge pull request #2243 from Eugeny/dependabot/npm_and_yarn/terminus-core/electron-updater-4.2.5
Bump electron-updater from 4.2.2 to 4.2.5 in /terminus-core
2020-03-16 21:18:10 +01:00
Eugene
20602eed6d Merge pull request #2245 from Eugeny/dependabot/npm_and_yarn/app/electron-updater-4.2.5
Bump electron-updater from 4.2.2 to 4.2.5 in /app
2020-03-16 21:18:02 +01:00
Eugene
f2cd86738c Merge pull request #2260 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-4.5.0-beta.13
Bump xterm from 4.5.0-beta.9 to 4.5.0-beta.13 in /terminus-terminal
2020-03-16 21:17:38 +01:00
Eugene
fc55446342 Merge pull request #2248 from Eugeny/dependabot/npm_and_yarn/app/angular/forms-9.0.6
Bump @angular/forms from 9.0.4 to 9.0.6 in /app
2020-03-16 21:17:13 +01:00
Eugene
dbc12c06cb Merge pull request #2261 from Eugeny/dependabot/npm_and_yarn/app/angular/platform-browser-dynamic-9.0.6
Bump @angular/platform-browser-dynamic from 9.0.4 to 9.0.6 in /app
2020-03-16 21:16:44 +01:00
Eugene
efb551cd94 Merge pull request #2262 from Eugeny/dependabot/npm_and_yarn/typedoc-0.17.0
Bump typedoc from 0.16.10 to 0.17.0
2020-03-16 21:16:16 +01:00
dependabot-preview[bot]
a87c1aa864 Bump typedoc from 0.16.10 to 0.17.0
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.16.10 to 0.17.0.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.16.10...0.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 04:19:54 +00:00
dependabot-preview[bot]
555f55592a Bump @angular/platform-browser-dynamic from 9.0.4 to 9.0.6 in /app
Bumps [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) from 9.0.4 to 9.0.6.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.0.6/packages/platform-browser-dynamic)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 04:19:37 +00:00
dependabot-preview[bot]
ab46739986 Bump xterm from 4.5.0-beta.9 to 4.5.0-beta.13 in /terminus-terminal
Bumps [xterm](https://github.com/xtermjs/xterm.js) from 4.5.0-beta.9 to 4.5.0-beta.13.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 04:18:49 +00:00
dependabot-preview[bot]
7ac7958462 Bump @types/ssh2 from 0.5.40 to 0.5.41 in /terminus-ssh
Bumps [@types/ssh2](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ssh2) from 0.5.40 to 0.5.41.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ssh2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-16 04:18:29 +00:00
dependabot-preview[bot]
46d5dace8f Bump @angular/forms from 9.0.4 to 9.0.6 in /app
Bumps [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) from 9.0.4 to 9.0.6.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.0.6/packages/forms)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-13 04:18:09 +00:00
Eugene Pankov
aace3f42d0 allow disabling ssh dynamic tab title (fixes #2240, fixes #2027) 2020-03-12 18:17:36 +01:00
Eugene
c4297f2b2b Merge pull request #2241 from nstefanou/master
Have multiple recent connections in history instead of just one
2020-03-12 15:00:51 +01:00
Nikolaos Stefanou
3c90e904fc fixed logic bug when deleting from history 2020-03-12 09:12:57 +00:00
dependabot-preview[bot]
f8c8065e4a Bump electron-builder from 22.3.6 to 22.4.1
Bumps [electron-builder](https://github.com/electron-userland/electron-builder) from 22.3.6 to 22.4.1.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-12 04:21:01 +00:00
dependabot-preview[bot]
d45a5a35d8 Bump electron-updater from 4.2.2 to 4.2.5 in /app
Bumps [electron-updater](https://github.com/electron-userland/electron-builder) from 4.2.2 to 4.2.5.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/compare/v4.2.2...v4.2.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-12 04:21:01 +00:00
dependabot-preview[bot]
a9c6b868fb Bump electron-updater from 4.2.2 to 4.2.5 in /terminus-core
Bumps [electron-updater](https://github.com/electron-userland/electron-builder) from 4.2.2 to 4.2.5.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/compare/v4.2.2...v4.2.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-12 04:20:51 +00:00
dependabot-preview[bot]
ffe8168f0f Bump @angular/common from 9.0.4 to 9.0.6 in /app
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 9.0.4 to 9.0.6.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/9.0.6/packages/common)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-12 04:20:09 +00:00
Nikolaos Stefanou
d1f5ebd546 Have multiple recent connections in history instead of just one 2020-03-11 20:37:17 +00:00
Eugene Pankov
2e8b465b3f apply custom css as the last style tag (fixes #2237) 2020-03-11 14:30:01 +01:00
dependabot-preview[bot]
4a535c94a6 Bump electron-rebuild from 1.9.0 to 1.10.1
Bumps [electron-rebuild](https://github.com/electron/electron-rebuild) from 1.9.0 to 1.10.1.
- [Release notes](https://github.com/electron/electron-rebuild/releases)
- [Changelog](https://github.com/electron/electron-rebuild/blob/master/.releaserc.json)
- [Commits](https://github.com/electron/electron-rebuild/compare/v1.9.0...v1.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-11 04:21:59 +00:00
dependabot-preview[bot]
531d47cbd1 Bump @typescript-eslint/parser from 2.21.0 to 2.23.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.21.0 to 2.23.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.23.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-10 04:22:59 +00:00
dependabot-preview[bot]
7a2491fe49 Bump cross-env from 7.0.0 to 7.0.2
Bumps [cross-env](https://github.com/kentcdodds/cross-env) from 7.0.0 to 7.0.2.
- [Release notes](https://github.com/kentcdodds/cross-env/releases)
- [Changelog](https://github.com/kentcdodds/cross-env/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kentcdodds/cross-env/compare/v7.0.0...v7.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-06 04:21:23 +00:00
Eugene
2773c61677 Merge pull request #2211 from Eugeny/dependabot/npm_and_yarn/electron-builder-22.3.6
Bump electron-builder from 22.3.2 to 22.3.6
2020-03-05 12:22:01 +01:00
Eugene
788b063384 Merge pull request #2208 from Eugeny/dependabot/npm_and_yarn/webpack-5.0.0-beta.14
Bump webpack from 5.0.0-beta.13 to 5.0.0-beta.14
2020-03-05 12:14:25 +01:00
dependabot-preview[bot]
0e112899df Bump electron-builder from 22.3.2 to 22.3.6
Bumps [electron-builder](https://github.com/electron-userland/electron-builder) from 22.3.2 to 22.3.6.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/compare/v22.3.2...v22.3.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-04 04:22:12 +00:00
dependabot-preview[bot]
d8c635bc1d Bump webpack from 5.0.0-beta.13 to 5.0.0-beta.14
Bumps [webpack](https://github.com/webpack/webpack) from 5.0.0-beta.13 to 5.0.0-beta.14.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.0.0-beta.13...v5.0.0-beta.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-03 04:23:37 +00:00
Eugene Pankov
dfe55b94ff definitely fixed key permissions 2020-03-02 16:45:47 +01:00
Eugene Pankov
6b4b6b522f reset permissions on key file (fixes #2201) 2020-03-02 16:21:37 +01:00
dependabot-preview[bot]
e0eedca7c9 Bump ngx-toastr from 10.2.0 to 12.0.0 in /app
Bumps [ngx-toastr](https://github.com/scttcper/ngx-toastr) from 10.2.0 to 12.0.0.
- [Release notes](https://github.com/scttcper/ngx-toastr/releases)
- [Commits](https://github.com/scttcper/ngx-toastr/compare/v10.2.0...v12.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-01 12:46:57 +00:00
98 changed files with 1979 additions and 1503 deletions

View File

@@ -253,6 +253,15 @@
"code",
"plugin"
]
},
{
"login": "orin220444",
"name": "orin220444",
"avatar_url": "https://avatars3.githubusercontent.com/u/30747229?v=4",
"profile": "https://github.com/orin220444",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@@ -99,3 +99,8 @@ rules:
'@typescript-eslint/restrict-template-expressions': off
'@typescript-eslint/no-dynamic-delete': off
'@typescript-eslint/prefer-nullish-coalescing': off
'@typescript-eslint/prefer-readonly-parameter-types': off
'@typescript-eslint/no-unsafe-member-access': off
'@typescript-eslint/no-unsafe-call': off
'@typescript-eslint/no-unsafe-return': off
'@typescript-eslint/no-base-to-string': off # broken in typescript-eslint

View File

@@ -107,6 +107,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
</tr>
</table>

View File

@@ -8,17 +8,15 @@ html
window.nodeRequire = require
script(src='./preload.js')
script(src='./bundle.js', defer)
style#custom-css
style.
body { transition: 0.5s background; }
body
style#custom-css
app-root
.preload-logo
div
.terminus-logo
h1.terminus-title Terminus
sup α
sup α
.progress
.bar(style='width: 0%')

View File

@@ -1,4 +1,4 @@
import { app, ipcMain, Menu, Tray, shell } from 'electron'
import { app, ipcMain, Menu, Tray, shell, globalShortcut } from 'electron'
// eslint-disable-next-line no-duplicate-imports
import * as electron from 'electron'
import { loadConfig } from './config'
@@ -9,8 +9,17 @@ export class Application {
private windows: Window[] = []
constructor () {
ipcMain.on('app:config-change', () => {
this.broadcast('host:config-change')
ipcMain.on('app:config-change', (_event, config) => {
this.broadcast('host:config-change', config)
})
ipcMain.on('app:register-global-hotkey', (_event, specs) => {
globalShortcut.unregisterAll()
for (let spec of specs) {
globalShortcut.register(spec, () => {
this.onGlobalHotkey()
})
}
})
const configData = loadConfig()
@@ -45,6 +54,9 @@ export class Application {
this.enableTray()
}
})
window.closed$.subscribe(() => {
this.windows = this.windows.filter(x => x !== window)
})
if (process.platform === 'darwin') {
this.setupMenu()
}
@@ -52,6 +64,24 @@ export class Application {
return window
}
onGlobalHotkey (): void {
if (this.windows.some(x => x.isFocused())) {
for (let window of this.windows) {
window.hide()
}
} else {
for (let window of this.windows) {
window.present()
}
}
}
presentAllWindows (): void {
for (let window of this.windows) {
window.present()
}
}
broadcast (event: string, ...args): void {
for (const window of this.windows) {
window.send(event, ...args)

View File

@@ -34,6 +34,7 @@ process.on('uncaughtException' as any, err => {
})
app.on('second-instance', (_event, argv, cwd) => {
application.presentAllWindows()
application.send('host:second-instance', parseArgs(argv, cwd), cwd)
})

View File

@@ -1,6 +1,6 @@
import { Subject, Observable } from 'rxjs'
import { debounceTime } from 'rxjs/operators'
import { BrowserWindow, app, ipcMain, Rectangle, screen } from 'electron'
import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen } from 'electron'
import ElectronConfig = require('electron-config')
import * as os from 'os'
import * as path from 'path'
@@ -23,17 +23,20 @@ export interface WindowOptions {
export class Window {
ready: Promise<void>
private visible = new Subject<boolean>()
private closed = new Subject<void>()
private window: BrowserWindow
private windowConfig: ElectronConfig
private windowBounds: Rectangle
private closing = false
private lastVibrancy: {enabled: boolean, type?: string} | null = null
private disableVibrancyWhileDragging = false
private configStore: any
get visible$ (): Observable<boolean> { return this.visible }
get closed$ (): Observable<void> { return this.closed }
constructor (options?: WindowOptions) {
let configData = loadConfig()
this.configStore = loadConfig()
options = options || {}
@@ -70,7 +73,7 @@ export class Window {
}
}
if ((configData.appearance || {}).frame === 'native') {
if ((this.configStore.appearance || {}).frame === 'native') {
bwOptions.frame = true
} else {
if (process.platform === 'darwin') {
@@ -86,7 +89,7 @@ export class Window {
this.window.once('ready-to-show', () => {
if (process.platform === 'darwin') {
this.window.setVibrancy('window')
} else if (process.platform === 'win32' && (configData.appearance || {}).vibrancy) {
} else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) {
this.setVibrancy(true)
}
@@ -153,12 +156,49 @@ export class Window {
return
}
this.window.webContents.send(event, ...args)
if (event === 'host:config-change') {
this.configStore = args[0]
}
}
isDestroyed (): boolean {
return !this.window || this.window.isDestroyed()
}
isFocused (): boolean {
return this.window.isFocused()
}
hide (): void {
if (process.platform === 'darwin') {
// Lose focus
Menu.sendActionToFirstResponder('hide:')
}
this.window.blur()
if (process.platform !== 'darwin') {
this.window.hide()
}
}
present (): void {
if (!this.window.isVisible()) {
// unfocused, invisible
this.window.show()
this.window.focus()
} else {
if (!this.configStore.appearance?.dock || this.configStore.appearance?.dock === 'off') {
// not docked, visible
setTimeout(() => {
this.window.show()
this.window.focus()
})
} else {
// docked, visible
this.window.hide()
}
}
}
private setupWindowManagement () {
this.window.on('show', () => {
this.visible.next(true)
@@ -326,6 +366,8 @@ export class Window {
private destroy () {
this.window = null
this.closed.next()
this.visible.complete()
this.closed.complete()
}
}

View File

@@ -13,31 +13,31 @@
"watch": "webpack --progress --color --watch"
},
"dependencies": {
"@angular/animations": "9.0.4",
"@angular/common": "9.0.4",
"@angular/compiler": "9.0.4",
"@angular/core": "9.0.4",
"@angular/forms": "9.0.4",
"@angular/platform-browser": "9.0.4",
"@angular/platform-browser-dynamic": "9.0.4",
"@ng-bootstrap/ng-bootstrap": "^6.0.0",
"@angular/animations": "9.1.0",
"@angular/common": "9.1.2",
"@angular/compiler": "9.1.2",
"@angular/core": "9.1.2",
"@angular/forms": "9.1.1",
"@angular/platform-browser": "9.1.1",
"@angular/platform-browser-dynamic": "9.1.2",
"@ng-bootstrap/ng-bootstrap": "^6.0.2",
"devtron": "1.4.0",
"electron-config": "2.0.0",
"electron-debug": "^3.0.1",
"electron-is-dev": "1.1.0",
"electron-updater": "^4.2.2",
"electron-updater": "^4.3.0",
"fontmanager-redux": "0.4.0",
"js-yaml": "3.13.1",
"keytar": "^5.4.0",
"keytar": "^5.5.0",
"mz": "^2.7.0",
"ngx-toastr": "^10.2.0",
"node-pty": "^0.10.0-beta2",
"ngx-toastr": "^12.0.1",
"node-pty": "^0.10.0-beta8",
"npm": "6.9.0",
"path": "0.12.7",
"rxjs": "^6.5.4",
"rxjs-compat": "^6.5.4",
"yargs": "^15.1.0",
"zone.js": "^0.10.2"
"rxjs": "^6.5.5",
"rxjs-compat": "^6.5.5",
"yargs": "^15.3.1",
"zone.js": "^0.10.3"
},
"optionalDependencies": {
"macos-native-processlist": "^1.0.2",

View File

@@ -2,45 +2,45 @@
# yarn lockfile v1
"@angular/animations@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.0.4.tgz#c95c601dfb8fc4e96aee577c9c0f6cf18b64e5d7"
integrity sha512-zTCgrIAA9FYPMbqqpQnoNltiLR58q0FMfzP2t96q/1tjyVy/Y/IaNgVQ7eL0HeQ0nG6IAzQ1HVx8Xeneg4Yj5Q==
"@angular/animations@9.1.0":
version "9.1.0"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.1.0.tgz#3030e290683c0e2d63fa61060d36f659511d3b2c"
integrity sha512-o7X3HM+eocoryw3VrDUtG6Wci2KwtzyBFo3KBJXjQ16X6fwdkjTG+hLb7pp2CBFBEJW4tPYEy7cSBmEfMRTqag==
"@angular/common@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.0.4.tgz#7d168b22c5c43e72112d0a19242eca22b62bb4f3"
integrity sha512-F3qoYrceEdCd5SlgObcbSIIdKfRXgyTBO2gbbArQHFe4GvewkH3isTn5uqAF6sfJlb7rXWZGrD6C3d9brw/fEw==
"@angular/common@9.1.2":
version "9.1.2"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.1.2.tgz#cec9fbfc572bbcf715e994523b04ac48700c1b2c"
integrity sha512-MAQW0DGq2NhvJSETLTwuImdzwI+wboG+5Uzgc0L8C/hX7SrEE65Hmz4nIjmGi2CPGLpodfWEcCPlV0R0dHun4A==
"@angular/compiler@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.4.tgz#038c9cdbf76f1cce47bd1b355c7d212cc89b18f9"
integrity sha512-+Ku8RUU00yHaKVkVw6YIfM3c5Gmvas5gJcEleiagkLbc1f/jKk1cY4gaUP6xn4TLypFM7NQglneWd+E+8wh0hQ==
"@angular/compiler@9.1.2":
version "9.1.2"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.1.2.tgz#52b22120ca3c7d27dccf4239c849158ad64fb435"
integrity sha512-82DitvlZA5DoE++qiiJdgx6HE71h96sfLHCjjvYJHApoOcnX+zBZFBrflpbXK9W4YdvydU4Lc1Ql1eleQPeT/g==
"@angular/core@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.4.tgz#6baa5ec6c594b47de541e47f4aa37241adec393a"
integrity sha512-6RqQb1GO2uglSlgiGbxhvy8plztZtABCWLRn0X+T1PnrxoqgxqA5WkKJjGxao+1M/ECW1V0fw4Xy7DE6KvAJwQ==
"@angular/core@9.1.2":
version "9.1.2"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.1.2.tgz#30970d49dc3b53c0dc68cd75dbc2c96afc7fee62"
integrity sha512-nAqRl+5drAnZlBT7AgSo2JJubmPNrGCvhZ83dosPEUqJoLr69/lYipnF/iqKzYn5xo4MM1O27WIhSNDtDjBmzQ==
"@angular/forms@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.0.4.tgz#31edac9917e592695a5c12b846e93dbda6afc510"
integrity sha512-WyfZ2u2JzGrwkxQmfxHvZMoYHEGfoUL+JlSXa2Sy3T/FPGNckHzIzggqweJij/qGjabWLabZDla4vak42f+4PA==
"@angular/forms@9.1.1":
version "9.1.1"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.1.1.tgz#3090829dd2989207fd9a4dbc5b44b3ff9b2fe948"
integrity sha512-NX+LuK8JFisiq3uHCOK6YoN/yIb2R9Ye5mwiOPkuZA3lZLKCnUXqCHZbM8VHy/WdjIxxeUaFMJc38yV8RVoabg==
"@angular/platform-browser-dynamic@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.4.tgz#343bd43fe00a279a737e02c16dd8790dc0da93a8"
integrity sha512-9vAn2QH07khuF4n7kyMJzgE6l30Yxg1AGd8GtOfa/4nbna+EZxFVYOkto9bpv4uEwDr9o7QrFLplko9a8xs7kg==
"@angular/platform-browser-dynamic@9.1.2":
version "9.1.2"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.2.tgz#5587d536184e1c92498d9000475dd8998df1b110"
integrity sha512-BWHxy8S71z+NmUQmtR+/Dkohlj3LQIXltOqeVdCSpjV9cultBNN3bE1w0Rjp3BmCRGCIDH7qFlr4U5woHa7ldw==
"@angular/platform-browser@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.0.4.tgz#03853b435c3b964660727ac9d7e15912c920cdb8"
integrity sha512-mbiqmw0rDGPxEgKVgDuK7yZvtgjJmzpMGBYAMwkQ9YIE0SoA5XP0NvZiFkHZqDXwLgCv2IJ/kvkhfCBwnBKCXQ==
"@angular/platform-browser@9.1.1":
version "9.1.1"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.1.1.tgz#bb5a98a3a33a307436684c4c7e2c448c786ae466"
integrity sha512-tjALKhdAWPErj0euIIdvx/31AHEZ7is7ADsMu+nYn2NY2gcPUuiqq3RCUJVxBYJ2Cclq1nlF0i2rEDKh7TrBKg==
"@ng-bootstrap/ng-bootstrap@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-6.0.0.tgz#03b80acd711dd38a653b34339224d5063c50bd62"
integrity sha512-ho0Ssw+kwpGzc+Rvtu2pRSrcbduECMf9+uekhOMB1nzhUfF2vJQnTDpPfHZQgU/ukTMEJWvby5vcXJoPtHgE+w==
"@ng-bootstrap/ng-bootstrap@^6.0.2":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-6.0.2.tgz#ed8d4e04f21885fb18dc2523c4f2111f50ee99b2"
integrity sha512-8+Dz8GN15zneIA4+mQ7b1j5O+oHsFdhTYQVDGk6eAazHeqrFD0+o8N+pLZL2PZlf98WcHFmXIOqKXrBD8iLl1g==
"@serialport/binding-abstract@^8.0.6":
version "8.0.6"
@@ -290,6 +290,11 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
at-least-node@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@@ -375,10 +380,10 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
builder-util-runtime@8.6.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.0.tgz#b7007c30126da9a90e99932128d2922c8c178649"
integrity sha512-WTDhTUVrm7zkFyd6Qn7AXgmWifjpZ/fYnEdV3XCOIDMNNb/KPddBTbQ8bUlxxVeuOYlhGpcLUypG+4USdGL1ww==
builder-util-runtime@8.6.1:
version "8.6.1"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.1.tgz#cf9a268fa51704de24f3c085aa8d1d1b3767d9ea"
integrity sha512-gwIUtMaICmc+e2EC3u3byXcwCyfhtG40LJRNnGfs8AYqacKl4ZLP50ab+uDttn7QAXe0LfMAuKz9v8bCODV0yg==
dependencies:
debug "^4.1.1"
sax "^1.2.4"
@@ -857,18 +862,17 @@ electron-localshortcut@^3.1.0:
keyboardevent-from-electron-accelerator "^1.1.0"
keyboardevents-areequal "^0.2.1"
electron-updater@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.2.tgz#57e106bffad16f71b1ffa3968a52a1b71c8147e6"
integrity sha512-e/OZhr5tLW0GcgmpR5wD0ImxgKMa8pPoNWRcwRyMzTL9pGej7+ORp0t9DtI5ZBHUbObIoEbrk+6EDGUGtJf+aA==
electron-updater@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.0.tgz#f66c253b25431d9aeb04fbd33c79062f33943d44"
integrity sha512-5K3vPgeiBGQaaCcZzQP00QYhGsh0l/q0mwzGWVZq1BHJ5akA+BpsY+EPiI9JzBhNVIdNlUvSKr5azUdbMwZeig==
dependencies:
"@types/semver" "^7.1.0"
builder-util-runtime "8.6.0"
fs-extra "^8.1.0"
builder-util-runtime "8.6.1"
fs-extra "^9.0.0"
js-yaml "^3.13.1"
lazy-val "^1.0.4"
lodash.isequal "^4.5.0"
pako "^1.0.11"
semver "^7.1.3"
emoji-regex@^8.0.0:
@@ -1064,14 +1068,15 @@ fs-constants@^1.0.0:
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
fs-extra@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==
dependencies:
at-least-node "^1.0.0"
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
jsonfile "^6.0.1"
universalify "^1.0.0"
fs-minipass@^1.2.5:
version "1.2.6"
@@ -1517,10 +1522,12 @@ json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
jsonfile@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==
dependencies:
universalify "^1.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
@@ -1549,10 +1556,10 @@ keyboardevents-areequal@^0.2.1:
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
keytar@^5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.4.0.tgz#71d8209e7dd2fe99008c243791350a6bd6ceab67"
integrity sha512-Ta0RtUmkq7un177SPgXKQ7FGfGDV4xvsV0cGNiWVEzash5U0wyOsXpwfrK2+Oq+hHvsvsbzIZUUuJPimm3avFw==
keytar@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.5.0.tgz#971de0fd5f480f9d397f4e4debf96e5ed886f12e"
integrity sha512-1d/F2qAL/qijpm25wNq8eez4mE+/J4eBvqyLfspIYIeCEHn3nttFwplowIZfbdNCjFGWh68MzGZOd2vS61Ffew==
dependencies:
nan "2.14.0"
prebuild-install "5.3.3"
@@ -1982,12 +1989,10 @@ napi-build-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508"
integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==
ngx-toastr@^10.2.0:
version "10.2.0"
resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-10.2.0.tgz#8a79008de0b1c013f90120a53e0355af5762e969"
integrity sha512-6ASr5bcvQmtNKb4D2VEsQjCXyROq6GwberBWO0bVt+xcBYPUea4aRTgX8in9apX9buaTafzG+h3HlnIraspoPg==
dependencies:
tslib "^1.9.0"
ngx-toastr@^12.0.1:
version "12.0.1"
resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-12.0.1.tgz#288c8ef505f1216aa4952cd2a8c6fa7c57a54ccc"
integrity sha512-PABtbn2dyHweVSbo/py1W3veXzcmZO7uVItfTW9AykSSeAUju3gOCgauAw89km0aJ9EBcPOieaoI+9tAR7Pfug==
node-abi@^2.15.0, node-abi@^2.7.0:
version "2.15.0"
@@ -2040,10 +2045,10 @@ node-gyp@^4.0.0:
tar "^4.4.8"
which "1"
node-pty@^0.10.0-beta2:
version "0.10.0-beta3"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta3.tgz#a33c9fc67c9e4d4f124111e1da2a72b0783008e7"
integrity sha512-j7MoJ3K999jrT9gAVs7JvM/skAQXQITrZK/PhL9B4W4GAPkANKwdu9uEtNvYionQ9dV8gRGte7lg9D2cRDdAiA==
node-pty@^0.10.0-beta8:
version "0.10.0-beta8"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta8.tgz#f4aa56c71a794f4580373a3030dfebd25240c6db"
integrity sha512-Ul/hLsadC0SvvShxpne+kq2ebSMcitewlNhrwoXXBvFdCqxJt7Ai1AgMhH7AKBUp06uBeYXThJ2ihTszrkdnYw==
dependencies:
nan "^2.14.0"
@@ -2459,11 +2464,6 @@ pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0:
unique-filename "^1.1.1"
which "^1.3.1"
pako@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
parallel-transform@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
@@ -2865,15 +2865,15 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
rxjs-compat@^6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.4.tgz#03825692af3fe363e04c43f41ff4113d76bbd305"
integrity sha512-rkn+lbOHUQOurdd74J/hjmDsG9nFx0z66fvnbs8M95nrtKvNqCKdk7iZqdY51CGmDemTQk+kUPy4s8HVOHtkfA==
rxjs-compat@^6.5.5:
version "6.5.5"
resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.5.tgz#073c40510f29c45a2a5fc02dde87f8c3ad75f2c2"
integrity sha512-F42sssVbUyWH4vJswEo6m+Eh02xHv3q93n8S7nUJO58R7sbc3CvJIOts605zdaBhWa1xMB9aVSyqPqhQ5q3eXg==
rxjs@^6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
rxjs@^6.5.5:
version "6.5.5"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
dependencies:
tslib "^1.9.0"
@@ -3343,10 +3343,10 @@ unique-string@^1.0.0:
dependencies:
crypto-random-string "^1.0.0"
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
unpipe@~1.0.0:
version "1.0.0"
@@ -3566,10 +3566,10 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
yargs-parser@^16.1.0:
version "16.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1"
integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==
yargs-parser@^18.1.1:
version "18.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.1.tgz#bf7407b915427fc760fcbbccc6c82b4f0ffcbd37"
integrity sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA==
dependencies:
camelcase "^5.0.0"
decamelize "^1.2.0"
@@ -3599,10 +3599,10 @@ yargs@^11.0.0:
y18n "^3.2.1"
yargs-parser "^9.0.2"
yargs@^15.1.0:
version "15.1.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219"
integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==
yargs@^15.3.1:
version "15.3.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==
dependencies:
cliui "^6.0.0"
decamelize "^1.2.0"
@@ -3614,9 +3614,9 @@ yargs@^15.1.0:
string-width "^4.2.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^16.1.0"
yargs-parser "^18.1.1"
zone.js@^0.10.2:
version "0.10.2"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.2.tgz#67ca084b3116fc33fc40435e0d5ea40a207e392e"
integrity sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg==
zone.js@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16"
integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==

View File

@@ -1,28 +1,28 @@
{
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.12.1",
"@sentry/cli": "^1.51.1",
"@fortawesome/fontawesome-free": "^5.13.0",
"@sentry/cli": "^1.52.1",
"@sentry/electron": "^1.2.1",
"@types/electron-config": "^3.2.2",
"@types/electron-debug": "^2.1.0",
"@types/js-yaml": "^3.12.1",
"@types/js-yaml": "^3.12.3",
"@types/node": "12.7.12",
"@types/webpack-env": "1.15.0",
"@typescript-eslint/eslint-plugin": "^2.21.0",
"@typescript-eslint/parser": "^2.21.0",
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.27.0",
"apply-loader": "2.0.0",
"awesome-typescript-loader": "^5.0.0",
"core-js": "^3.6.4",
"cross-env": "7.0.0",
"core-js": "^3.6.5",
"cross-env": "7.0.2",
"css-loader": "3.4.2",
"electron": "^8.0.2",
"electron-builder": "22.3.2",
"electron": "^8.2.3",
"electron-builder": "22.5.1",
"electron-download": "^4.1.1",
"electron-installer-snap": "^5.0.0",
"electron-notarize": "^0.1.1",
"electron-rebuild": "^1.9.0",
"electron-rebuild": "^1.10.1",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-import": "^2.20.2",
"file-loader": "^5.0.2",
"graceful-fs": "^4.2.2",
"html-loader": "0.5.5",
@@ -37,22 +37,22 @@
"pug-lint": "^2.6.0",
"pug-loader": "^2.4.0",
"pug-static-loader": "2.0.0",
"raw-loader": "4.0.0",
"raw-loader": "4.0.1",
"sass-loader": "^8.0.0",
"shelljs": "0.8.3",
"source-code-pro": "^2.30.2",
"source-sans-pro": "3.6.0",
"style-loader": "^1.1.3",
"style-loader": "^1.1.4",
"svg-inline-loader": "^0.8.0",
"to-string-loader": "1.1.6",
"tslib": "^1.11.1",
"typedoc": "^0.16.10",
"typescript": "^3.8.2",
"typedoc": "^0.17.4",
"typescript": "^3.8.3",
"url-loader": "^3.0.0",
"val-loader": "2.1.0",
"webpack": "^5.0.0-beta.13",
"val-loader": "2.1.1",
"webpack": "^5.0.0-beta.14",
"webpack-cli": "^3.3.10",
"yaml-loader": "0.5.0"
"yaml-loader": "0.6.0"
},
"resolutions": {
"*/node-abi": "^2.14.0"
@@ -67,5 +67,7 @@
"lint": "eslint --ext ts */src */lib",
"postinstall": "node ./scripts/install-deps.js"
},
"repository": "eugeny/terminus"
"repository": "eugeny/terminus",
"author": "Eugene Pankov",
"license": "MIT"
}

View File

@@ -1,5 +1,8 @@
export interface SelectorOption<T> {
name: string
description?: string
result: T
result?: T
icon?: string
freeInputPattern?: string
callback?: (string?) => void
}

View File

@@ -114,6 +114,9 @@ export class AppRootComponent {
if (hotkey === 'move-tab-right') {
this.app.moveSelectedTabRight()
}
if (hotkey === 'reopen-tab') {
this.app.reopenLastTab()
}
}
if (hotkey === 'toggle-fullscreen') {
this.hostApp.toggleFullscreen()
@@ -125,17 +128,8 @@ export class AppRootComponent {
this.docking.dock()
})
this.hostApp.secondInstance$.subscribe(() => {
this.presentWindow()
})
this.hotkeys.globalHotkey.subscribe(() => {
this.onGlobalHotkey()
})
this.hostApp.windowCloseRequest$.subscribe(async () => {
if (await this.app.closeAllTabs()) {
this.hostApp.closeWindow()
}
this.app.closeWindow()
})
if (window['safeModeReason']) {
@@ -174,41 +168,6 @@ export class AppRootComponent {
})
}
onGlobalHotkey () {
if (this.hostApp.getWindow().isFocused()) {
this.hideWindow()
} else {
this.presentWindow()
}
}
presentWindow () {
if (!this.hostApp.getWindow().isVisible()) {
// unfocused, invisible
this.hostApp.getWindow().show()
this.hostApp.getWindow().focus()
} else {
if (this.config.store.appearance.dock === 'off') {
// not docked, visible
setTimeout(() => {
this.hostApp.getWindow().show()
this.hostApp.getWindow().focus()
})
} else {
// docked, visible
this.hostApp.getWindow().hide()
}
}
}
hideWindow () {
this.electron.loseFocus()
this.hostApp.getWindow().blur()
if (this.hostApp.platform !== Platform.macOS) {
this.hostApp.getWindow().hide()
}
}
async ngOnInit () {
this.ready = true

View File

@@ -63,7 +63,7 @@ export abstract class BaseTabComponent {
get destroyed$ (): Observable<void> { return this.destroyed }
get recoveryStateChangedHint$ (): Observable<void> { return this.recoveryStateChangedHint }
constructor () {
protected constructor () {
this.focused$.subscribe(() => {
this.hasFocus = true
})

View File

@@ -4,15 +4,23 @@
[(ngModel)]='filter',
autofocus,
[placeholder]='name',
(ngModelChange)='onFilterChange()',
(keyup.enter)='onFilterEnter()',
(keyup.escape)='close()'
(ngModelChange)='onFilterChange()'
)
.list-group.mt-3(*ngIf='filteredOptions.length')
a.list-group-item.list-group-item-action.d-flex.align-items-center(
#item,
(click)='selectOption(option)',
*ngFor='let option of filteredOptions'
[class.active]='selectedIndex == i',
*ngFor='let option of filteredOptions; let i = index'
)
.mr-2 {{option.name}}
i.icon(
class='fa-fw fas fa-{{option.icon}}',
*ngIf='!iconIsSVG(option.icon)'
)
.icon(
[fastHtmlBind]='option.icon',
*ngIf='iconIsSVG(option.icon)'
)
.mr-2.title {{getOptionText(option)}}
.text-muted {{option.description}}

View File

@@ -0,0 +1,13 @@
.list-group {
max-height: 70vh;
overflow: auto;
}
.icon {
width: 1.25rem;
margin-right: 0.25rem;
}
.title {
margin-left: 10px;
}

View File

@@ -1,17 +1,19 @@
import { Component, Input } from '@angular/core'
import { Component, Input, HostListener, ViewChildren, QueryList, ElementRef } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { SelectorOption } from '../api/selector'
/** @hidden */
@Component({
template: require('./selectorModal.component.pug'),
// styles: [require('./selectorModal.component.scss')],
styles: [require('./selectorModal.component.scss')],
})
export class SelectorModalComponent<T> {
@Input() options: SelectorOption<T>[]
@Input() filteredOptions: SelectorOption<T>[]
@Input() filter = ''
@Input() name: string
@Input() selectedIndex = 0
@ViewChildren('item') itemChildren: QueryList<ElementRef>
constructor (
public modalInstance: NgbActiveModal,
@@ -21,27 +23,56 @@ export class SelectorModalComponent<T> {
this.onFilterChange()
}
@HostListener('keyup', ['$event']) onKeyUp (event: KeyboardEvent): void {
if (event.key === 'ArrowUp') {
this.selectedIndex--
}
if (event.key === 'ArrowDown') {
this.selectedIndex++
}
if (event.key === 'Enter') {
this.selectOption(this.filteredOptions[this.selectedIndex])
}
if (event.key === 'Escape') {
this.close()
}
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
})
}
onFilterChange (): void {
const f = this.filter.trim().toLowerCase()
if (!f) {
this.filteredOptions = this.options
this.filteredOptions = this.options.filter(x => !x.freeInputPattern)
} else {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
this.filteredOptions = this.options.filter(x => (x.name + (x.description || '')).toLowerCase().includes(f))
this.filteredOptions = this.options.filter(x => x.freeInputPattern || (x.name + (x.description || '')).toLowerCase().includes(f))
}
this.selectedIndex = Math.max(0, this.selectedIndex)
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
}
onFilterEnter (): void {
if (this.filteredOptions.length === 1) {
this.selectOption(this.filteredOptions[0])
getOptionText (option: SelectorOption<T>): string {
if (option.freeInputPattern) {
return option.freeInputPattern.replace('%s', this.filter)
}
return option.name
}
selectOption (option: SelectorOption<T>): void {
option.callback?.(this.filter)
this.modalInstance.close(option.result)
}
close (): void {
this.modalInstance.dismiss()
}
iconIsSVG (icon: string): boolean {
return icon?.startsWith('<')
}
}

View File

@@ -13,7 +13,7 @@ import { ToolbarButton, ToolbarButtonProvider } from '../api'
export class StartPageComponent {
version: string
constructor (
private constructor (
private config: ConfigService,
private domSanitizer: DomSanitizer,
public homeBase: HomeBaseService,

View File

@@ -1,9 +1,9 @@
.mb-4
.terminus-logo
h1.terminus-title Terminus
sup α
.container.mt-5.mb-5
.mb-4
.terminus-logo
h1.terminus-title Terminus
sup α
.container
.text-center.mb-5 Thank you for downloading Terminus!
.form-line

View File

@@ -2,5 +2,7 @@
display: flex;
flex-direction: column;
margin: auto;
flex: 0 1 500px;
flex: auto;
max-height: 100%;
overflow-y: auto;
}

View File

@@ -10,11 +10,9 @@ import { AppService } from '../services/app.service'
styles: [require('./windowControls.component.scss')],
})
export class WindowControlsComponent {
constructor (public hostApp: HostAppService, public app: AppService) { }
private constructor (public hostApp: HostAppService, public app: AppService) { }
async closeWindow () {
if (await this.app.closeAllTabs()) {
this.hostApp.closeWindow()
}
this.app.closeWindow()
}
}

View File

@@ -7,6 +7,8 @@ hotkeys:
- 'F11'
close-tab:
- 'Ctrl-Shift-W'
reopen-tab:
- 'Ctrl-Shift-T'
toggle-last-tab: []
rename-tab:
- 'Ctrl-Shift-R'

View File

@@ -7,6 +7,8 @@ hotkeys:
- 'Ctrl+⌘+F'
close-tab:
- '⌘-W'
reopen-tab:
- '⌘-Shift-T'
toggle-last-tab: []
rename-tab:
- '⌘-R'

View File

@@ -8,6 +8,8 @@ hotkeys:
- 'Alt-Enter'
close-tab:
- 'Ctrl-Shift-W'
reopen-tab:
- 'Ctrl-Shift-T'
toggle-last-tab: []
rename-tab:
- 'Ctrl-Shift-R'

View File

@@ -25,6 +25,10 @@ export class AppHotkeyProvider extends HotkeyProvider {
id: 'close-tab',
name: 'Close tab',
},
{
id: 'reopen-tab',
name: 'Reopen last tab',
},
{
id: 'toggle-last-tab',
name: 'Toggle last tab',

View File

@@ -8,6 +8,7 @@ import { BaseTabComponent } from '../components/baseTab.component'
import { SplitTabComponent } from '../components/splitTab.component'
import { SelectorModalComponent } from '../components/selectorModal.component'
import { SelectorOption } from '../api/selector'
import { RecoveryToken } from '../api/tabRecovery'
import { ConfigService } from './config.service'
import { HostAppService } from './hostApp.service'
@@ -49,6 +50,7 @@ export class AppService {
private lastTabIndex = 0
private _activeTab: BaseTabComponent
private closedTabsStack: RecoveryToken[] = []
private activeTabChange = new Subject<BaseTabComponent>()
private tabsChanged = new Subject<void>()
@@ -67,39 +69,44 @@ export class AppService {
get ready$ (): Observable<void> { return this.ready }
/** @hidden */
constructor (
private constructor (
private config: ConfigService,
private hostApp: HostAppService,
private tabRecovery: TabRecoveryService,
private tabsService: TabsService,
private ngbModal: NgbModal,
) {
if (hostApp.getWindow().id === 1) {
if (config.store.terminal.recoverTabs) {
this.tabRecovery.recoverTabs().then(tabs => {
for (const tab of tabs) {
this.openNewTabRaw(tab.type, tab.options)
}
this.startTabStorage()
})
} else {
/** Continue to store the tabs even if the setting is currently off */
this.startTabStorage()
}
}
hostApp.windowFocused$.subscribe(() => {
this._activeTab?.emitFocused()
})
}
startTabStorage (): void {
this.tabsChanged$.subscribe(() => {
this.tabRecovery.saveTabs(this.tabs)
})
setInterval(() => {
this.tabRecovery.saveTabs(this.tabs)
}, 30000)
if (hostApp.getWindow().id === 1) {
if (config.store.terminal.recoverTabs) {
this.tabRecovery.recoverTabs().then(tabs => {
for (const tab of tabs) {
this.openNewTabRaw(tab.type, tab.options)
}
this.tabRecovery.enabled = true
})
} else {
/** Continue to store the tabs even if the setting is currently off */
this.tabRecovery.enabled = true
}
}
hostApp.windowFocused$.subscribe(() => {
this._activeTab?.emitFocused()
})
this.tabClosed$.subscribe(async tab => {
const token = await tab.getRecoveryToken()
if (token) {
this.closedTabsStack.push(token)
}
})
}
addTabRaw (tab: BaseTabComponent, index: number|null = null): void {
@@ -163,6 +170,23 @@ export class AppService {
return tab
}
async reopenLastTab (): Promise<BaseTabComponent|null> {
const token = this.closedTabsStack.pop()
if (token) {
const recoveredTab = await this.tabRecovery.recoverTab(token)
if (recoveredTab) {
const tab = this.tabsService.create(recoveredTab.type, recoveredTab.options)
if (this.activeTab) {
this.addTabRaw(tab, this.tabs.indexOf(this.activeTab) + 1)
} else {
this.addTabRaw(tab)
}
return tab
}
}
return null
}
selectTab (tab: BaseTabComponent): void {
if (this._activeTab === tab) {
this._activeTab.emitFocused()
@@ -295,6 +319,16 @@ export class AppService {
return true
}
async closeWindow (): Promise<void> {
this.tabRecovery.enabled = false
await this.tabRecovery.saveTabs(this.tabs)
if (await this.closeAllTabs()) {
this.hostApp.closeWindow()
} else {
this.tabRecovery.enabled = true
}
}
/** @hidden */
emitReady (): void {
this.ready.next()

View File

@@ -102,7 +102,7 @@ export class ConfigService {
get changed$ (): Observable<void> { return this.changed }
/** @hidden */
constructor (
private constructor (
electron: ElectronService,
private hostApp: HostAppService,
@Inject(ConfigProvider) configProviders: ConfigProvider[],
@@ -155,9 +155,11 @@ export class ConfigService {
}
save (): void {
// Scrub undefined values
this._store = JSON.parse(JSON.stringify(this._store))
fs.writeFileSync(this.path, yaml.safeDump(this._store), 'utf8')
this.emitChange()
this.hostApp.broadcastConfigChange()
this.hostApp.broadcastConfigChange(this.store)
}
/**

View File

@@ -6,7 +6,7 @@ import { HostAppService, Bounds } from '../services/hostApp.service'
@Injectable({ providedIn: 'root' })
export class DockingService {
/** @hidden */
constructor (
private constructor (
private electron: ElectronService,
private config: ConfigService,
private hostApp: HostAppService,

View File

@@ -25,7 +25,7 @@ export class ElectronService {
private electron: any
/** @hidden */
constructor () {
private constructor () {
this.electron = require('electron')
this.remote = this.electron.remote
this.app = this.remote.app
@@ -43,15 +43,6 @@ export class ElectronService {
this.MenuItem = this.remote.MenuItem
}
/**
* Removes OS focus from Terminus' window
*/
loseFocus (): void {
if (process.platform === 'darwin') {
this.remote.Menu.sendActionToFirstResponder('hide:')
}
}
async showMessageBox (
browserWindow: Electron.BrowserWindow,
options: Electron.MessageBoxOptions

View File

@@ -11,7 +11,7 @@ export class HomeBaseService {
mixpanel: any
/** @hidden */
constructor (
private constructor (
private electron: ElectronService,
private config: ConfigService,
) {

View File

@@ -166,7 +166,6 @@ export class HostAppService {
this.configChangeBroadcast.next()
}))
if (
isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED) &&
!isWindowsBuild(WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED)
@@ -251,8 +250,8 @@ export class HostAppService {
/**
* Notifies other windows of config file changes
*/
broadcastConfigChange (): void {
this.electron.ipcRenderer.send('app:config-change')
broadcastConfigChange (configStore: {[k: string]: any}): void {
this.electron.ipcRenderer.send('app:config-change', configStore)
}
emitReady (): void {
@@ -267,6 +266,10 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-close')
}
registerGlobalHotkey (specs: string[]): void {
this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
}
relaunch (): void {
if (this.isPortable) {
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })

View File

@@ -2,8 +2,9 @@ import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
import { Observable, Subject } from 'rxjs'
import { HotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
import { stringifyKeySequence } from './hotkeys.util'
import { ConfigService } from '../services/config.service'
import { ElectronService } from '../services/electron.service'
import { ConfigService } from './config.service'
import { ElectronService } from './electron.service'
import { HostAppService } from './hostApp.service'
export interface PartialHotkeyMatch {
id: string
@@ -30,7 +31,6 @@ export class HotkeysService {
*/
get hotkey$ (): Observable<string> { return this._hotkey }
globalHotkey = new EventEmitter<void>()
private _hotkey = new Subject<string>()
private currentKeystrokes: EventBufferEntry[] = []
private disabledLevel = 0
@@ -38,6 +38,7 @@ export class HotkeysService {
private constructor (
private zone: NgZone,
private hostApp: HostAppService,
private electron: ElectronService,
private config: ConfigService,
@Inject(HotkeyProvider) private hotkeyProviders: HotkeyProvider[],
@@ -182,6 +183,7 @@ export class HotkeysService {
if (typeof value === 'string') {
value = [value]
}
const specs: string[] = []
value.forEach((item: string | string[]) => {
item = typeof item === 'string' ? [item] : item
@@ -190,13 +192,13 @@ export class HotkeysService {
electronKeySpec = electronKeySpec.replace('⌘', 'Command')
electronKeySpec = electronKeySpec.replace('⌥', 'Alt')
electronKeySpec = electronKeySpec.replace(/-/g, '+')
this.electron.globalShortcut.register(electronKeySpec, () => {
this.globalHotkey.emit()
})
specs.push(electronKeySpec)
} catch (err) {
console.error('Could not register the global hotkey:', err)
}
})
this.hostApp.registerGlobalHotkey(specs)
}
private getHotkeysConfig () {

View File

@@ -65,7 +65,7 @@ export class LogService {
private log: any
/** @hidden */
constructor (electron: ElectronService) {
private constructor (electron: ElectronService) {
this.log = initializeWinston(electron)
}

View File

@@ -33,7 +33,7 @@ export class ShellIntegrationService {
command: 'paste "%V"',
},
]
constructor (
private constructor (
private electron: ElectronService,
private hostApp: HostAppService,
) {

View File

@@ -8,8 +8,9 @@ import { ConfigService } from '../services/config.service'
@Injectable({ providedIn: 'root' })
export class TabRecoveryService {
logger: Logger
enabled = false
constructor (
private constructor (
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
private config: ConfigService,
log: LogService
@@ -18,6 +19,9 @@ export class TabRecoveryService {
}
async saveTabs (tabs: BaseTabComponent[]): Promise<void> {
if (!this.enabled) {
return
}
window.localStorage.tabsRecovery = JSON.stringify(
await Promise.all(
tabs
@@ -25,8 +29,11 @@ export class TabRecoveryService {
let token = tab.getRecoveryToken()
if (token) {
token = token.then(r => {
if (r && tab.color) {
r.tabColor = tab.color
if (r) {
r.tabTitle = tab.title
if (tab.color) {
r.tabColor = tab.color
}
}
return r
})
@@ -45,6 +52,7 @@ export class TabRecoveryService {
if (tab !== null) {
tab.options = tab.options || {}
tab.options.color = token.tabColor || null
tab.options.title = token.tabTitle || ''
return tab
}
} catch (error) {

View File

@@ -8,7 +8,7 @@ export type TabComponentType = new (...args: any[]) => BaseTabComponent
@Injectable({ providedIn: 'root' })
export class TabsService {
/** @hidden */
constructor (
private constructor (
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private tabRecovery: TabRecoveryService,

View File

@@ -7,7 +7,7 @@ export class ThemesService {
private styleElement: HTMLElement|null = null
/** @hidden */
constructor (
private constructor (
private config: ConfigService,
@Inject(Theme) private themes: Theme[],
) {

View File

@@ -14,7 +14,7 @@ export class TouchbarService {
private tabSegments: SegmentedControlSegment[] = []
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
constructor (
private constructor (
private app: AppService,
private hostApp: HostAppService,
@Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[],

View File

@@ -21,7 +21,7 @@ export class UpdaterService {
private updateURL: string
private autoUpdater: AppUpdater
constructor (
private constructor (
log: LogService,
private electron: ElectronService,
private config: ConfigService,

View File

@@ -20,4 +20,8 @@ app-root {
ssh-tab .content {
margin: 5px !important;
}
serial-tab .content {
margin: 5px !important;
}
}

View File

@@ -246,7 +246,7 @@ ngb-tabset .tab-content {
}
.list-group-item {
transition: 0.25s background;
transition: 0.0625s background;
i + * {
margin-left: 10px;
@@ -262,6 +262,29 @@ ngb-tabset .tab-content {
}
}
.list-group-light {
.list-group-item {
background: transparent;
border: none;
border-top: 1px solid rgba(255, 255, 255, .1);
&:not(.combi) {
padding: $list-group-item-padding-y $list-group-item-padding-x;
}
&:first-child {
border-top: none;
}
&.list-group-item-action {
&:hover, &.active {
background: $list-group-hover-bg;
}
}
}
}
checkbox i.on {
color: $blue;
}
@@ -392,3 +415,7 @@ search-panel {
border-color: $nav-tabs-link-active-border-color;
}
}
hr {
border-color: $list-group-border-color;
}

View File

@@ -3,9 +3,9 @@
"@types/js-yaml@^3.9.0":
version "3.12.2"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.2.tgz#a35a1809c33a68200fb6403d1ad708363c56470a"
integrity sha512-0CFu/g4mDSNkodVwWijdlr8jH7RoplRWNgovjFLEZeT+QEbbZXjBmCe3HwaWheAlCbHwomTwzZoSedeOycABug==
version "3.12.3"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.3.tgz#abf383c5b639d0aa8b8c4a420d6a85f703357d6c"
integrity sha512-otRe77JNNWzoVGLKw8TCspKswRoQToys4tuL6XYVBFxjgeM0RUrx7m3jkaTdxILxeGry3zM8mGYkGXMeQ02guA==
"@types/node@*":
version "13.7.1"
@@ -52,6 +52,11 @@ async@^2.6.1:
dependencies:
lodash "^4.17.11"
at-least-node@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
axios@^0.19.0:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
@@ -64,10 +69,10 @@ bootstrap@^4.1.3:
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
builder-util-runtime@8.6.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.0.tgz#b7007c30126da9a90e99932128d2922c8c178649"
integrity sha512-WTDhTUVrm7zkFyd6Qn7AXgmWifjpZ/fYnEdV3XCOIDMNNb/KPddBTbQ8bUlxxVeuOYlhGpcLUypG+4USdGL1ww==
builder-util-runtime@8.6.1:
version "8.6.1"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.1.tgz#cf9a268fa51704de24f3c085aa8d1d1b3767d9ea"
integrity sha512-gwIUtMaICmc+e2EC3u3byXcwCyfhtG40LJRNnGfs8AYqacKl4ZLP50ab+uDttn7QAXe0LfMAuKz9v8bCODV0yg==
dependencies:
debug "^4.1.1"
sax "^1.2.4"
@@ -124,9 +129,9 @@ colorspace@1.1.x:
text-hex "1.0.x"
core-js@^3.1.2:
version "3.6.4"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647"
integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==
version "3.6.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
core-util-is@~1.0.0:
version "1.0.2"
@@ -169,17 +174,16 @@ diagnostics@^1.1.1:
kuler "1.0.x"
electron-updater@^4.0.6:
version "4.2.2"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.2.tgz#57e106bffad16f71b1ffa3968a52a1b71c8147e6"
integrity sha512-e/OZhr5tLW0GcgmpR5wD0ImxgKMa8pPoNWRcwRyMzTL9pGej7+ORp0t9DtI5ZBHUbObIoEbrk+6EDGUGtJf+aA==
version "4.3.0"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.0.tgz#f66c253b25431d9aeb04fbd33c79062f33943d44"
integrity sha512-5K3vPgeiBGQaaCcZzQP00QYhGsh0l/q0mwzGWVZq1BHJ5akA+BpsY+EPiI9JzBhNVIdNlUvSKr5azUdbMwZeig==
dependencies:
"@types/semver" "^7.1.0"
builder-util-runtime "8.6.0"
fs-extra "^8.1.0"
builder-util-runtime "8.6.1"
fs-extra "^9.0.0"
js-yaml "^3.13.1"
lazy-val "^1.0.4"
lodash.isequal "^4.5.0"
pako "^1.0.11"
semver "^7.1.3"
enabled@1.0.x:
@@ -228,14 +232,15 @@ follow-redirects@1.5.10:
dependencies:
debug "=3.1.0"
fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
fs-extra@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==
dependencies:
at-least-node "^1.0.0"
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
jsonfile "^6.0.1"
universalify "^1.0.0"
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.2"
@@ -278,10 +283,12 @@ js-yaml@^3.13.1, js-yaml@^3.9.0:
argparse "^1.0.7"
esprima "^4.0.0"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
jsonfile@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==
dependencies:
universalify "^1.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
@@ -353,11 +360,6 @@ one-time@0.0.4:
resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e"
integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=
pako@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
perfect-scrollbar@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.4.0.tgz#5d014ef9775e1f43058a1dbae9ed1daf0e7091f1"
@@ -456,10 +458,10 @@ triple-beam@^1.2.0, triple-beam@^1.3.0:
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"

View File

@@ -34,7 +34,7 @@ export class PluginManagerService {
private npmReady: Promise<void>
private npm: any
constructor (
private constructor (
log: LogService,
) {
this.logger = log.create('pluginManager')

View File

@@ -60,9 +60,9 @@ object-assign@^4.0.1:
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
semver@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.1.tgz#29104598a197d6cbe4733eeecbe968f7b43a9667"
integrity sha512-WfuG+fl6eh3eZ2qAf6goB7nhiCd7NPXhmyFxigB/TOkQyeLP8w8GsVehvtGNtnNmyboz4TgeK40B1Kbql/8c5A==
version "7.2.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.2.2.tgz#d01432d74ed3010a20ffaf909d63a691520521cd"
integrity sha512-Zo84u6o2PebMSK3zjJ6Zp5wi8VnQZnEaCP13Ul/lt1ANsLACxnJxq4EEm1PY94/por1Hm9+7xpIswdS5AkieMA==
thenify-all@^1.0.0:
version "1.6.0"

View File

@@ -1,14 +1,13 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Injectable, Injector } from '@angular/core'
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
import { SerialModalComponent } from './components/serialModal.component'
import { SerialService } from './services/serial.service'
/** @hidden */
@Injectable()
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
private ngbModal: NgbModal,
private injector: Injector,
hotkeys: HotkeysService,
) {
super()
@@ -20,7 +19,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
}
activate () {
this.ngbModal.open(SerialModalComponent)
this.injector.get(SerialService).showConnectionSelector()
}
provide (): ToolbarButton[] {

View File

@@ -1,32 +0,0 @@
.modal-body
input.form-control(
type='text',
[(ngModel)]='quickTarget',
autofocus,
placeholder='Quick connect: path@baudrate',
(ngModelChange)='refresh()',
(keyup.enter)='quickConnect()'
)
.list-group.mt-3(*ngIf='lastConnection')
a.list-group-item.list-group-item-action.d-flex.align-items-center((click)='connect(lastConnection)')
i.fas.fa-fw.fa-history
.mr-auto {{lastConnection.name}}
button.btn.btn-outline-danger.btn-sm((click)='clearLastConnection(); $event.stopPropagation()')
i.fas.fa-trash
.list-group.mt-3.connections-list(*ngIf='connections.length')
a.list-group-item.list-group-item-action.d-flex.align-items-center(
*ngFor='let connection of connections',
(click)='connect(connection)'
)
.mr-2 {{connection.name}}
.text-muted {{connection.port}}
.list-group.mt-3(*ngIf='foundPorts.length')
a.list-group-item.list-group-item-action.d-flex.align-items-center(
(click)='connectFoundPort(port)',
*ngFor='let port of foundPorts'
)
.mr-2 {{port.name}}
.text-muted {{port.description}}

View File

@@ -1,5 +0,0 @@
.list-group.connections-list {
display: block;
max-height: 70vh;
overflow-y: auto;
}

View File

@@ -1,102 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, NgZone } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ToastrService } from 'ngx-toastr'
import { ConfigService, AppService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings'
import { SerialService } from '../services/serial.service'
import { SerialConnection, SerialPortInfo, BAUD_RATES } from '../api'
import { SerialTabComponent } from './serialTab.component'
/** @hidden */
@Component({
template: require('./serialModal.component.pug'),
styles: [require('./serialModal.component.scss')],
})
export class SerialModalComponent {
connections: SerialConnection[]
quickTarget: string
lastConnection: SerialConnection|null = null
foundPorts: SerialPortInfo[] = []
constructor (
public modalInstance: NgbActiveModal,
private config: ConfigService,
private serial: SerialService,
private app: AppService,
private zone: NgZone,
private toastr: ToastrService,
) { }
async ngOnInit () {
this.connections = this.config.store.serial.connections
if (window.localStorage.lastSerialConnection) {
this.lastConnection = JSON.parse(window.localStorage.lastSerialConnection)
}
this.foundPorts = await this.serial.listPorts()
}
quickConnect () {
let path = this.quickTarget
let baudrate = 115200
if (this.quickTarget.includes('@')) {
baudrate = parseInt(path.split('@')[1])
path = path.split('@')[0]
}
const connection: SerialConnection = {
name: this.quickTarget,
port: path,
baudrate: baudrate,
databits: 8,
parity: 'none',
rtscts: false,
stopbits: 1,
xany: false,
xoff: false,
xon: false,
}
window.localStorage.lastSerialConnection = JSON.stringify(connection)
this.connect(connection)
}
clearLastConnection () {
window.localStorage.lastSerialConnection = null
this.lastConnection = null
}
async connect (connection: SerialConnection) {
this.close()
try {
const tab = this.zone.run(() => this.app.openNewTab(
SerialTabComponent,
{ connection }
) as SerialTabComponent)
if (connection.color) {
(this.app.getParentTab(tab) || tab).color = connection.color
}
setTimeout(() => {
this.app.activeTab.emitFocused()
})
} catch (error) {
this.toastr.error(`Could not connect: ${error}`)
}
}
manageConnections () {
this.close()
this.app.openNewTab(SettingsTabComponent, { activeTab: 'serial' })
}
close () {
this.modalInstance.close()
}
async connectFoundPort (port: SerialPortInfo) {
const rate = await this.app.showSelector('Baud rate', BAUD_RATES.map(x => ({
name: x.toString(), result: x,
})))
this.quickTarget = `${port.name}@${rate}`
this.quickConnect()
}
}

View File

@@ -21,9 +21,9 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
serialPort: any
private homeEndSubscription: Subscription
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor (
injector: Injector,
private serial: SerialService,
) {
super(injector)
}
@@ -62,7 +62,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
return
}
this.session = this.serial.createSession(this.connection)
this.session = this.injector.get(SerialService).createSession(this.connection)
this.session.serviceMessage$.subscribe(msg => {
this.write('\r\n' + colors.black.bgWhite(' serial ') + ' ' + msg + '\r\n')
this.session.resize(this.size.columns, this.size.rows)
@@ -80,11 +80,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
spinner.start()
try {
this.serialPort = await this.serial.connectSession(this.session, (message: string) => {
spinner.stop(true)
this.write(message + '\r\n')
spinner.start()
})
this.serialPort = await this.injector.get(SerialService).connectSession(this.session)
spinner.stop(true)
} catch (e) {
spinner.stop(true)

View File

@@ -8,7 +8,6 @@ import { SettingsTabProvider } from 'terminus-settings'
import TerminusTerminalModule from 'terminus-terminal'
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
import { SerialModalComponent } from './components/serialModal.component'
import { SerialSettingsTabComponent } from './components/serialSettingsTab.component'
import { SerialTabComponent } from './components/serialTab.component'
@@ -37,13 +36,11 @@ import { SerialHotkeyProvider } from './hotkeys'
],
entryComponents: [
EditConnectionModalComponent,
SerialModalComponent,
SerialSettingsTabComponent,
SerialTabComponent,
],
declarations: [
EditConnectionModalComponent,
SerialModalComponent,
SerialSettingsTabComponent,
SerialTabComponent,
],

View File

@@ -1,8 +1,10 @@
import { Injectable, NgZone } from '@angular/core'
import SerialPort from 'serialport'
import { ToastrService } from 'ngx-toastr'
import { LogService } from 'terminus-core'
import { SerialConnection, SerialSession, SerialPortInfo } from '../api'
import { LogService, AppService, SelectorOption, ConfigService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings'
import { SerialConnection, SerialSession, SerialPortInfo, BAUD_RATES } from '../api'
import { SerialTabComponent } from '../components/serialTab.component'
@Injectable({ providedIn: 'root' })
export class SerialService {
@@ -10,6 +12,8 @@ export class SerialService {
private log: LogService,
private zone: NgZone,
private toastr: ToastrService,
private app: AppService,
private config: ConfigService,
) { }
async listPorts (): Promise<SerialPortInfo[]> {
@@ -25,7 +29,7 @@ export class SerialService {
return session
}
async connectSession (session: SerialSession, _?: (s: any) => void): Promise<SerialPort> {
async connectSession (session: SerialSession): Promise<SerialPort> {
const serial = new SerialPort(session.connection.port, { autoOpen: false, baudRate: session.connection.baudrate,
dataBits: session.connection.databits, stopBits: session.connection.stopbits, parity: session.connection.parity,
rtscts: session.connection.rtscts, xon: session.connection.xon, xoff: session.connection.xoff,
@@ -57,4 +61,109 @@ export class SerialService {
})
return serial
}
async showConnectionSelector (): Promise<void> {
const options: SelectorOption<void>[] = []
const foundPorts = await this.listPorts()
try {
const lastConnection = JSON.parse(window.localStorage.lastSerialConnection)
if (lastConnection) {
options.push({
name: lastConnection.name,
icon: 'history',
callback: () => this.connect(lastConnection),
})
options.push({
name: 'Clear last connection',
icon: 'eraser',
callback: () => {
window.localStorage.lastSerialConnection = null
},
})
}
} catch { }
for (const port of foundPorts) {
options.push({
name: port.name,
description: port.description,
icon: 'arrow-right',
callback: () => this.connectFoundPort(port),
})
}
for (const connection of this.config.store.serial.connections) {
options.push({
name: connection.name,
description: connection.port,
callback: () => this.connect(connection),
})
}
options.push({
name: 'Manage connections',
icon: 'cog',
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'serial' }),
})
options.push({
name: 'Quick connect',
freeInputPattern: 'Open device: %s...',
icon: 'arrow-right',
callback: query => this.quickConnect(query),
})
await this.app.showSelector('Open a serial port', options)
}
async connect (connection: SerialConnection): Promise<SerialTabComponent> {
try {
const tab = this.app.openNewTab(
SerialTabComponent,
{ connection }
) as SerialTabComponent
if (connection.color) {
(this.app.getParentTab(tab) || tab).color = connection.color
}
setTimeout(() => {
this.app.activeTab.emitFocused()
})
return tab
} catch (error) {
this.toastr.error(`Could not connect: ${error}`)
throw error
}
}
quickConnect (query: string): Promise<SerialTabComponent> {
let path = query
let baudrate = 115200
if (query.includes('@')) {
baudrate = parseInt(path.split('@')[1])
path = path.split('@')[0]
}
const connection: SerialConnection = {
name: query,
port: path,
baudrate: baudrate,
databits: 8,
parity: 'none',
rtscts: false,
stopbits: 1,
xany: false,
xoff: false,
xon: false,
}
window.localStorage.lastSerialConnection = JSON.stringify(connection)
return this.connect(connection)
}
async connectFoundPort (port: SerialPortInfo): Promise<SerialTabComponent> {
const rate = await this.app.showSelector('Baud rate', BAUD_RATES.map(x => ({
name: x.toString(), result: x,
})))
return this.quickConnect(`${port.name}@${rate}`)
}
}

View File

@@ -88,7 +88,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
.form-line
.header
.title Transparency
.title Opacity
input(
type='range',
[(ngModel)]='config.store.appearance.opacity',

View File

@@ -34,6 +34,8 @@ export interface SSHConnection {
color?: string
x11?: boolean
skipBanner?: boolean
disableDynamicTitle?: boolean
jumpHost?: string
algorithms?: {[t: string]: string[]}
}
@@ -79,6 +81,7 @@ export class SSHSession extends BaseSession {
ssh: Client
forwardedPorts: ForwardedPort[] = []
logger: Logger
jumpStream: any
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
private serviceMessage = new Subject<string>()
@@ -86,6 +89,13 @@ export class SSHSession extends BaseSession {
constructor (public connection: SSHConnection) {
super()
this.scripts = connection.scripts || []
this.destroyed$.subscribe(() => {
for (const port of this.forwardedPorts) {
if (port.type === PortForwardType.Local) {
port.stopLocalListener()
}
}
})
}
async start (): Promise<void> {
@@ -237,14 +247,16 @@ export class SSHSession extends BaseSession {
socket.destroy()
return
}
stream.pipe(socket)
socket.pipe(stream)
stream.on('close', () => {
socket.destroy()
})
socket.on('close', () => {
stream.close()
})
if (stream) {
stream.pipe(socket)
socket.pipe(stream)
stream.on('close', () => {
socket.destroy()
})
socket.on('close', () => {
stream.close()
})
}
}
)
}).then(() => {
@@ -290,7 +302,7 @@ export class SSHSession extends BaseSession {
write (data: Buffer): void {
if (this.shell) {
this.shell.write(data.toString())
this.shell.write(data)
}
}

View File

@@ -1,15 +1,14 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
import { SSHModalComponent } from './components/sshModal.component'
import { SSHService } from './services/ssh.service'
/** @hidden */
@Injectable()
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
private ngbModal: NgbModal,
hotkeys: HotkeysService,
private ssh: SSHService,
) {
super()
hotkeys.matchedHotkey.subscribe(async (hotkey: string) => {
@@ -20,7 +19,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
}
activate () {
this.ngbModal.open(SSHModalComponent)
this.ssh.showConnectionSelector()
}
provide (): ToolbarButton[] {

View File

@@ -70,6 +70,13 @@
ngb-tab(id='advanced')
ng-template(ngbTabTitle) Advanced
ng-template(ngbTabContent)
.form-line
.header
.title Jump host
select.form-control([(ngModel)]='connection.jumpHost')
option([value]='null') None
option([value]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
.form-line
.header
.title X11 forwarding
@@ -85,9 +92,16 @@
placeholder='#000000'
)
.form-line
.header
.title Disable dynamic tab title
.description Connection name will be used as a title instead
toggle([(ngModel)]='connection.disableDynamicTitle')
.form-line
.header
.title Skip MoTD/banner
.description Will prevent the SSH greeting from showing up
toggle([(ngModel)]='connection.skipBanner')
.form-line

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core'
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ElectronService, HostAppService } from 'terminus-core'
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
import { PasswordStorageService } from '../services/passwordStorage.service'
import { SSHConnection, LoginScript, SSHAlgorithmType } from '../api'
import { PromptModalComponent } from './promptModal.component'
@@ -20,6 +20,7 @@ export class EditConnectionModalComponent {
algorithms: {[id: string]: {[a: string]: boolean}} = {}
constructor (
public config: ConfigService,
private modalInstance: NgbActiveModal,
private electron: ElectronService,
private hostApp: HostAppService,

View File

@@ -1,32 +0,0 @@
.modal-body
input.form-control(
type='text',
[(ngModel)]='quickTarget',
autofocus,
placeholder='Quick connect: [user@]host[:port]',
(ngModelChange)='refresh()',
(keyup.enter)='quickConnect()'
)
.list-group.mt-3(*ngIf='lastConnection')
a.list-group-item.list-group-item-action.d-flex.align-items-center((click)='connect(lastConnection)')
i.fas.fa-fw.fa-history
.mr-auto {{lastConnection.name}}
button.btn.btn-outline-danger.btn-sm((click)='clearLastConnection(); $event.stopPropagation()')
i.fas.fa-trash
.list-group.mt-3.connections-list(*ngIf='childGroups.length')
ng-container(*ngFor='let group of childGroups')
.list-group-item.list-group-item-action.d-flex.align-items-center(
(click)='groupCollapsed[group.name] = !groupCollapsed[group.name]'
)
.fa.fa-fw.fa-chevron-right(*ngIf='groupCollapsed[group.name]')
.fa.fa-fw.fa-chevron-down(*ngIf='!groupCollapsed[group.name]')
.ml-2 {{group.name || "Ungrouped"}}
ng-container(*ngIf='!groupCollapsed[group.name]')
.list-group-item.list-group-item-action.pl-5.d-flex.align-items-center(
*ngFor='let connection of group.connections',
(click)='connect(connection)'
)
.mr-2 {{connection.name}}
.text-muted {{connection.host}}

View File

@@ -1,5 +0,0 @@
.list-group.connections-list {
display: block;
max-height: 70vh;
overflow-y: auto;
}

View File

@@ -1,117 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, NgZone } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ToastrService } from 'ngx-toastr'
import { ConfigService, AppService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings'
import { SSHConnection, SSHConnectionGroup } from '../api'
import { SSHTabComponent } from './sshTab.component'
/** @hidden */
@Component({
template: require('./sshModal.component.pug'),
styles: [require('./sshModal.component.scss')],
})
export class SSHModalComponent {
connections: SSHConnection[]
childFolders: SSHConnectionGroup[]
quickTarget: string
lastConnection: SSHConnection|null = null
childGroups: SSHConnectionGroup[]
groupCollapsed: {[id: string]: boolean} = {}
constructor (
public modalInstance: NgbActiveModal,
private config: ConfigService,
private app: AppService,
private toastr: ToastrService,
private zone: NgZone,
) { }
ngOnInit () {
this.connections = this.config.store.ssh.connections
if (window.localStorage.lastConnection) {
this.lastConnection = JSON.parse(window.localStorage.lastConnection)
}
this.refresh()
}
quickConnect () {
let user = 'root'
let host = this.quickTarget
let port = 22
if (host.includes('@')) {
[user, host] = host.split('@')
}
if (host.includes(':')) {
port = parseInt(host.split(':')[1])
host = host.split(':')[0]
}
const connection: SSHConnection = {
name: this.quickTarget,
group: null,
host,
user,
port,
}
window.localStorage.lastConnection = JSON.stringify(connection)
this.connect(connection)
}
clearLastConnection () {
window.localStorage.lastConnection = null
this.lastConnection = null
}
async connect (connection: SSHConnection) {
this.close()
try {
const tab = this.zone.run(() => this.app.openNewTab(
SSHTabComponent,
{ connection }
) as SSHTabComponent)
if (connection.color) {
(this.app.getParentTab(tab) || tab).color = connection.color
}
setTimeout(() => {
this.app.activeTab?.emitFocused()
})
} catch (error) {
this.toastr.error(`Could not connect: ${error}`)
}
}
manageConnections () {
this.close()
this.app.openNewTab(SettingsTabComponent, { activeTab: 'ssh' })
}
close () {
this.modalInstance.close()
}
refresh () {
this.childGroups = []
let connections = this.connections
if (this.quickTarget) {
connections = connections.filter((connection: SSHConnection) => (connection.name + connection.group!).toLowerCase().includes(this.quickTarget))
}
for (const connection of connections) {
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
group = {
name: connection.group!,
connections: [],
}
this.childGroups.push(group!)
}
group.connections.push(connection)
}
}
}

View File

@@ -96,7 +96,7 @@ export class SSHSettingsTabComponent {
this.hostApp.getWindow(),
{
type: 'warning',
message: `Delete "${group}"?`,
message: `Delete "${group.name}"?`,
buttons: ['Keep', 'Delete'],
defaultId: 1,
}

View File

@@ -10,6 +10,7 @@ import { SSHConnection, SSHSession } from '../api'
import { SSHPortForwardingModalComponent } from './sshPortForwardingModal.component'
import { Subscription } from 'rxjs'
/** @hidden */
@Component({
selector: 'ssh-tab',
@@ -20,6 +21,7 @@ import { Subscription } from 'rxjs'
export class SSHTabComponent extends BaseTerminalTabComponent {
connection: SSHConnection
session: SSHSession
private sessionStack: SSHSession[] = []
private homeEndSubscription: Subscription
constructor (
@@ -33,6 +35,8 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
ngOnInit (): void {
this.logger = this.log.create('terminalTab')
this.enableDynamicTitle = !this.connection.disableDynamicTitle
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
if (!this.hasFocus) {
return
@@ -58,19 +62,40 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
})
}
async initializeSession (): Promise<void> {
if (!this.connection) {
this.logger.error('No SSH connection info supplied')
return
async setupOneSession (session: SSHSession): Promise<void> {
if (session.connection.jumpHost) {
const jumpConnection = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
const jumpSession = this.ssh.createSession(jumpConnection)
await this.setupOneSession(jumpSession)
jumpSession.destroyed$.subscribe(() => session.destroy())
session.jumpStream = await new Promise((resolve, reject) => jumpSession.ssh.forwardOut(
'127.0.0.1', 0, session.connection.host, session.connection.port,
(err, stream) => {
if (err) {
jumpSession.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not set up port forward on ${jumpConnection.name}`)
return reject(err)
}
resolve(stream)
}
))
session.jumpStream.on('close', () => {
jumpSession.destroy()
})
this.sessionStack.push(session)
}
this.session = this.ssh.createSession(this.connection)
this.session.serviceMessage$.subscribe(msg => {
session.serviceMessage$.subscribe(msg => {
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ' ' + msg + '\r\n')
this.session.resize(this.size.columns, this.size.rows)
session.resize(this.size.columns, this.size.rows)
})
this.attachSessionHandlers()
this.write(`Connecting to ${this.connection.host}`)
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
const spinner = new Spinner({
text: 'Connecting',
@@ -82,7 +107,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
spinner.start()
try {
await this.ssh.connectSession(this.session, (message: string) => {
await this.ssh.connectSession(session, (message: string) => {
spinner.stop(true)
this.write(message + '\r\n')
spinner.start()
@@ -93,6 +118,20 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
return
}
}
async initializeSession (): Promise<void> {
if (!this.connection) {
this.logger.error('No SSH connection info supplied')
return
}
this.session = this.ssh.createSession(this.connection)
await this.setupOneSession(this.session)
this.attachSessionHandlers()
await this.session.start()
this.session.resize(this.size.columns, this.size.rows)
}

View File

@@ -5,6 +5,7 @@ export class SSHConfigProvider extends ConfigProvider {
defaults = {
ssh: {
connections: [],
recentConnections: [],
options: {
},
},

View File

@@ -8,7 +8,6 @@ import { SettingsTabProvider } from 'terminus-settings'
import TerminusTerminalModule from 'terminus-terminal'
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
import { SSHModalComponent } from './components/sshModal.component'
import { SSHPortForwardingModalComponent } from './components/sshPortForwardingModal.component'
import { PromptModalComponent } from './components/promptModal.component'
import { SSHSettingsTabComponent } from './components/sshSettingsTab.component'
@@ -40,7 +39,6 @@ import { SSHHotkeyProvider } from './hotkeys'
entryComponents: [
EditConnectionModalComponent,
PromptModalComponent,
SSHModalComponent,
SSHPortForwardingModalComponent,
SSHSettingsTabComponent,
SSHTabComponent,
@@ -48,7 +46,6 @@ import { SSHHotkeyProvider } from './hotkeys'
declarations: [
EditConnectionModalComponent,
PromptModalComponent,
SSHModalComponent,
SSHPortForwardingModalComponent,
SSHSettingsTabComponent,
SSHTabComponent,

View File

@@ -3,16 +3,18 @@ import { open as openTemp } from 'temp'
import { Injectable, NgZone } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Client } from 'ssh2'
import { SSH2Stream } from 'ssh2-streams'
import * as fs from 'mz/fs'
import { execFile } from 'mz/child_process'
import * as path from 'path'
import * as sshpk from 'sshpk'
import { ToastrService } from 'ngx-toastr'
import { HostAppService, Platform, Logger, LogService, ElectronService } from 'terminus-core'
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings'
import { SSHConnection, SSHSession } from '../api'
import { PromptModalComponent } from '../components/promptModal.component'
import { PasswordStorageService } from './passwordStorage.service'
import { SSH2Stream } from 'ssh2-streams'
import { SSHTabComponent } from '../components/sshTab.component'
try {
var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
@@ -30,6 +32,8 @@ export class SSHService {
private hostApp: HostAppService,
private passwordStorage: PasswordStorageService,
private toastr: ToastrService,
private app: AppService,
private config: ConfigService,
) {
this.logger = log.create('ssh')
}
@@ -109,6 +113,8 @@ export class SSHService {
'ssh-keygen',
'ssh-keygen.exe',
)
await execFile('icacls', [temp.path, '/inheritance:r'])
await execFile('icacls', [temp.path, '/grant:r', `${process.env.USERNAME}:(R,W)`])
}
await execFile(sshKeygenPath, [
@@ -145,6 +151,12 @@ export class SSHService {
}
})
})
ssh.on('close', () => {
if (session.open) {
session.destroy()
}
})
ssh.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => this.zone.run(async () => {
log(colors.bgBlackBright(' ') + ` Keyboard-interactive auth requested: ${name}`)
this.logger.info('Keyboard-interactive auth:', name, instructions, instructionsLang)
@@ -205,6 +217,7 @@ export class SSHService {
},
hostHash: 'sha256' as any,
algorithms: session.connection.algorithms,
sock: session.jumpStream,
})
} catch (e) {
this.toastr.error(e.message)
@@ -247,6 +260,124 @@ export class SSHService {
})
})
}
async showConnectionSelector (): Promise<void> {
const options: SelectorOption<void>[] = []
const recentConnections = this.config.store.ssh.recentConnections
for (const connection of recentConnections) {
options.push({
name: connection.name,
description: connection.host,
icon: 'history',
callback: () => this.connect(connection),
})
}
if (recentConnections.length) {
options.push({
name: 'Clear recent connections',
icon: 'eraser',
callback: () => {
this.config.store.ssh.recentConnections = []
this.config.save()
},
})
}
let groups: { name: string, connections: SSHConnection[] }[] = []
let connections = this.config.store.ssh.connections
for (const connection of connections) {
connection.group = connection.group || null
let group = groups.find(x => x.name === connection.group)
if (!group) {
group = {
name: connection.group!,
connections: [],
}
groups.push(group!)
}
group.connections.push(connection)
}
for (const group of groups) {
for (const connection of group.connections) {
options.push({
name: (group.name ? `${group.name} / ` : '') + connection.name,
description: connection.host,
icon: 'desktop',
callback: () => this.connect(connection),
})
}
}
options.push({
name: 'Manage connections',
icon: 'cog',
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'ssh' }),
})
options.push({
name: 'Quick connect',
freeInputPattern: 'Connect to "%s"...',
icon: 'arrow-right',
callback: query => this.quickConnect(query),
})
await this.app.showSelector('Open an SSH connection', options)
}
async connect (connection: SSHConnection): Promise<SSHTabComponent> {
try {
const tab = this.app.openNewTab(
SSHTabComponent,
{ connection }
) as SSHTabComponent
if (connection.color) {
(this.app.getParentTab(tab) || tab).color = connection.color
}
setTimeout(() => {
this.app.activeTab?.emitFocused()
})
return tab
} catch (error) {
this.toastr.error(`Could not connect: ${error}`)
throw error
}
}
quickConnect (query: string): Promise<SSHTabComponent> {
let user = 'root'
let host = query
let port = 22
if (host.includes('@')) {
[user, host] = host.split('@')
}
if (host.includes(':')) {
port = parseInt(host.split(':')[1])
host = host.split(':')[0]
}
const connection: SSHConnection = {
name: query,
group: null,
host,
user,
port,
}
const recentConnections = this.config.store.ssh.recentConnections
recentConnections.unshift(connection)
if (recentConnections.length > 5) {
recentConnections.pop()
}
this.config.store.ssh.recentConnections = recentConnections
this.config.save()
return this.connect(connection)
}
}
/* eslint-disable */

View File

@@ -20,9 +20,9 @@
"@types/node" "*"
"@types/ssh2@^0.5.35":
version "0.5.40"
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.40.tgz#b65465897f40c67e66e630b1f059f13a1ea7f1fa"
integrity sha512-Yrs2vFIirdscR+xY4leiUosHTClRbVBiFLlm5gA0JMZMjbCulHKO3qcgMqATElrquiZal5sSHoXMk4t8DzDawA==
version "0.5.43"
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.43.tgz#a4b8fc0288ef79a0d2d89363644d0b4448fe9532"
integrity sha512-rVEwm6fEmy9RJg1nTK3qhCKoviKtLg+axE1RXzAWuKz3QuZIZDxCKP38/tzhxkQ8I8FDVXgRoWtvltzQKtDaBg==
dependencies:
"@types/node" "*"
"@types/ssh2-streams" "*"
@@ -162,21 +162,21 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
ssh2-streams@^0.4.2, ssh2-streams@~0.4.9:
version "0.4.9"
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.9.tgz#d3d92155410001437d27119d9c023b303cbe2309"
integrity sha512-glMQKeYKuA+rLaH16fJC3nZMV1BWklbxuYCR4C5/LlBSf2yaoNRpPU7Ul702xsi5nvYjIx9XDkKBJwrBjkDynw==
ssh2-streams@^0.4.2, ssh2-streams@~0.4.10:
version "0.4.10"
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.10.tgz#48ef7e8a0e39d8f2921c30521d56dacb31d23a34"
integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==
dependencies:
asn1 "~0.2.0"
bcrypt-pbkdf "^1.0.2"
streamsearch "~0.1.2"
ssh2@^0.8.2:
version "0.8.8"
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.8.tgz#1d9815e287faef623ae2b7db32e674dadbef4664"
integrity sha512-egJVQkf3sbjECTY6rCeg8rgV/fab6S/7E5kpYqHT3Fe/YpfJbLYeA1qTcB2d+LRUUAjqKi7rlbfWkaP66YdpAQ==
version "0.8.9"
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3"
integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==
dependencies:
ssh2-streams "~0.4.9"
ssh2-streams "~0.4.10"
sshpk@^1.16.1:
version "1.16.1"

View File

@@ -28,12 +28,12 @@
"slugify": "^1.4.0",
"uuid": "^7.0.1",
"xterm": "^4.5.0-beta.9",
"xterm-addon-fit": "^0.4.0-beta2",
"xterm-addon-fit": "^0.4.0-beta.8",
"xterm-addon-ligatures": "^0.2.1",
"xterm-addon-search": "^0.5.0",
"xterm-addon-serialize": "^0.1.1",
"xterm-addon-unicode11": "^0.1.1",
"xterm-addon-webgl": "^0.6.0-beta.2",
"xterm-addon-search": "^0.7.0-beta.1",
"xterm-addon-serialize": "^0.3.0-beta.3",
"xterm-addon-unicode11": "^0.2.0-beta.5",
"xterm-addon-webgl": "^0.7.0-beta.5",
"zmodem.js": "^0.1.9"
},
"peerDependencies": {

View File

@@ -63,6 +63,13 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
*/
enablePassthrough = true
/**
* Enables receiving dynamic window/tab title provided by the shell
*/
enableDynamicTitle = true
alternateScreenActive = false
// Deps start
config: ConfigService
element: ElementRef
@@ -205,6 +212,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.session.releaseInitialDataBuffer()
})
this.alternateScreenActive$.subscribe(x => {
this.alternateScreenActive = x
})
if (this.savedState) {
this.frontend.restoreState(this.savedState)
this.frontend.write('\r\n\r\n')
@@ -274,7 +285,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
*/
write (data: string): void {
const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
if (percentageMatch) {
if (!this.alternateScreenActive && percentageMatch) {
const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
if (percentage > 0 && percentage <= 100) {
this.setProgress(percentage)
@@ -286,7 +297,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.frontend.write(data)
}
paste (): void {
async paste (): Promise<void> {
let data = this.electron.clipboard.readText() as string
if (this.config.store.terminal.bracketedPaste) {
data = '\x1b[200~' + data + '\x1b[201~'
@@ -296,6 +307,28 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
} else {
data = data.replace(/\n/g, '\r')
}
if (!this.alternateScreenActive && data.includes('\r') && this.config.store.terminal.warnOnMultilinePaste) {
const canTrim = !data.trim().includes('\r')
const buttons = canTrim ? ['Paste', 'Trim whitespace and paste', 'Cancel'] : ['Paste', 'Cancel']
const result = (await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
detail: data,
message: `Paste multiple lines?`,
buttons,
defaultId: 0,
cancelId: buttons.length - 1,
}
)).response
if (result === buttons.length - 1) {
return
}
if (result === 1) {
data = data.trim()
}
}
this.sendInput(data)
}
@@ -375,7 +408,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
}
this.termContainerSubscriptions = [
this.frontend.title$.subscribe(title => this.zone.run(() => this.setTitle(title))),
this.frontend.title$.subscribe(title => this.zone.run(() => {
if (this.enableDynamicTitle) {
this.setTitle(title)
}
})),
this.focused$.subscribe(() => this.frontend.enableResizing = true),
this.blurred$.subscribe(() => this.frontend.enableResizing = false),

View File

@@ -19,6 +19,7 @@ export interface Profile {
name: string
color?: string
sessionOptions: SessionOptions
shell?: string
isBuiltin?: boolean
icon?: string
}

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import * as fs from 'mz/fs'
import { Injectable } from '@angular/core'
import { ToolbarButtonProvider, ToolbarButton, ElectronService } from 'terminus-core'
import { ToolbarButtonProvider, ToolbarButton, ElectronService, ConfigService, SelectorOption, AppService } from 'terminus-core'
import { TerminalService } from './services/terminal.service'
@@ -10,6 +10,8 @@ import { TerminalService } from './services/terminal.service'
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
electron: ElectronService,
private app: AppService,
private config: ConfigService,
private terminal: TerminalService,
) {
super()
@@ -27,27 +29,35 @@ export class ButtonProvider extends ToolbarButtonProvider {
}
}
async activate () {
const options: SelectorOption<void>[] = []
const profiles = await this.terminal.getProfiles({ skipDefault: !this.config.store.terminal.showDefaultProfiles })
for (const profile of profiles) {
options.push({
icon: profile.icon,
name: profile.name,
callback: () => this.terminal.openTab(profile),
})
}
await this.app.showSelector('Select profile', options)
}
provide (): ToolbarButton[] {
return [
{
icon: require('./icons/plus.svg'),
title: 'New terminal',
touchBarNSImage: 'NSTouchBarAddDetailTemplate',
click: async () => {
click: () => {
this.terminal.openTab()
},
},
{
icon: require('./icons/profiles.svg'),
title: 'New terminal with profile',
submenu: async () => {
const profiles = await this.terminal.getProfiles()
return profiles.map(profile => ({
icon: profile.icon,
title: profile.name,
click: () => this.terminal.openTab(profile),
}))
},
click: () => this.activate(),
},
]
}

View File

@@ -1,6 +1,6 @@
h3.mb-3 Appearance
.d-flex
.mr-5
.mr-5.w-100
.form-line
.header
.title Font
@@ -27,148 +27,7 @@ h3.mb-3 Appearance
(ngModelChange)='config.save()',
)
.form-line(*ngIf='!editingColorScheme')
.header
.title Color scheme
.input-group.w-50
select.form-control(
[compareWith]='equalComparator',
[(ngModel)]='config.store.terminal.colorScheme',
(ngModelChange)='config.save()',
)
option(*ngFor='let scheme of config.store.terminal.customColorSchemes', [ngValue]='scheme') Custom: {{scheme.name}}
option(*ngFor='let scheme of colorSchemes', [ngValue]='scheme') {{scheme.name}}
.input-group-append
button.btn.btn-secondary((click)='editScheme(config.store.terminal.colorScheme)')
i.fas.fa-pen
.input-group-append
button.btn.btn-outline-danger(
(click)='deleteScheme(config.store.terminal.colorScheme)',
*ngIf='isCustomScheme(config.store.terminal.colorScheme)'
)
i.fas.fa-trash
.form-group(*ngIf='editingColorScheme')
label Editing
.input-group
input.form-control(type='text', [(ngModel)]='editingColorScheme.name')
.input-group-append
button.btn.btn-secondary((click)='saveScheme()')
i.fas.fa-check
.input-group-append
button.btn.btn-secondary((click)='cancelEditing()')
i.fas.fa-times
.form-group(*ngIf='editingColorScheme')
color-picker(
[(model)]='editingColorScheme.foreground',
(modelChange)='config.save(); schemeChanged = true',
title='FG',
)
color-picker(
[(model)]='editingColorScheme.background',
(modelChange)='config.save(); schemeChanged = true',
title='BG',
)
color-picker(
[(model)]='editingColorScheme.cursor',
(modelChange)='config.save(); schemeChanged = true',
title='CU',
)
color-picker(
*ngFor='let _ of editingColorScheme.colors; let idx = index; trackBy: colorsTrackBy',
[(model)]='editingColorScheme.colors[idx]',
(modelChange)='config.save(); schemeChanged = true',
[title]='idx',
)
div
.form-group
.appearance-preview(
[style.font-family]='getPreviewFontFamily()',
[style.font-size]='config.store.terminal.fontSize + "px"',
[style.background-color]='(config.store.terminal.background == "theme") ? null : config.store.terminal.colorScheme.background',
[style.color]='config.store.terminal.colorScheme.foreground',
[style.font-feature-settings]='\'"liga" \' + config.store.terminal.ligatures ? 1 : 0',
[style.font-variant-ligatures]='config.store.terminal.ligatures ? "initial" : "none"',
)
div
span([style.background-color]='config.store.terminal.colorScheme.colors[0]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[1]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[2]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[3]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[4]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[5]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[6]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[7]') &nbsp;
span &nbsp;&nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[0]') B
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[1]') R
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[2]') G
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[3]') Y
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[4]') B
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[5]') M
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[6]') T
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[7]') W
div
span([style.background-color]='config.store.terminal.colorScheme.colors[8]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[9]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[10]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[11]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[12]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[13]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[14]') &nbsp;
span([style.background-color]='config.store.terminal.colorScheme.colors[15]') &nbsp;
span &nbsp;&nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[8]') B
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[9]') R
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[10]') G
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[11]') Y
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[12]') B
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[13]') M
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[14]') T
span &nbsp;
span([style.color]='config.store.terminal.colorScheme.colors[15]') W
div
span &nbsp;
div
span john@doe-pc
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
span ls -l
div
span drwxr-xr-x 1 root
span([style.color]='config.store.terminal.colorScheme.colors[4]') directory 📁
div
span -rw-r--r-- 1 root файл
div
span -rwxr-xr-x 1 root
span([style.color]='config.store.terminal.colorScheme.colors[2]') 実行可能ファイル
div
span -rwxr-xr-x 1 root
span([style.color]='config.store.terminal.colorScheme.colors[6]') sym
span ->
span([style.color]='config.store.terminal.colorScheme.colors[1]') link
div
span &nbsp;
div
span john@doe-pc
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
span rm -rf /
span([style.background-color]='config.store.terminal.colorScheme.cursor') &nbsp;
color-scheme-preview([scheme]='config.store.terminal.colorScheme', [fontPreview]='true')
.form-line
.header

View File

@@ -1,12 +1,4 @@
.appearance-preview {
padding: 10px 0;
margin-left: 20px;
padding: 10px;
overflow: hidden;
max-width: 400px;
max-height: 400px;
span {
white-space: pre;
}
color-scheme-preview {
flex-shrink: 0;
margin-bottom: 20px;
}

View File

@@ -2,13 +2,10 @@
import { Observable } from 'rxjs'
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
import { exec } from 'mz/child_process'
import deepEqual from 'deep-equal'
const fontManager = require('fontmanager-redux') // eslint-disable-line
import { Component, Inject } from '@angular/core'
import { ConfigService, HostAppService, Platform, ElectronService, getCSSFontFamily } from 'terminus-core'
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
import { TerminalColorScheme } from '../api/interfaces'
import { Component } from '@angular/core'
import { ConfigService, HostAppService, Platform, getCSSFontFamily } from 'terminus-core'
/** @hidden */
@Component({
@@ -17,15 +14,9 @@ import { TerminalColorScheme } from '../api/interfaces'
})
export class AppearanceSettingsTabComponent {
fonts: string[] = []
colorSchemes: TerminalColorScheme[] = []
equalComparator = deepEqual
editingColorScheme: TerminalColorScheme|null = null
schemeChanged = false
constructor (
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
private hostApp: HostAppService,
private electron: ElectronService,
public config: ConfigService,
) { }
@@ -49,7 +40,6 @@ export class AppearanceSettingsTabComponent {
this.fonts.sort()
})
}
this.colorSchemes = (await Promise.all(this.config.enabledServices(this.colorSchemeProviders).map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
}
fontAutocomplete = (text$: Observable<string>) => {
@@ -61,49 +51,6 @@ export class AppearanceSettingsTabComponent {
)
}
editScheme (scheme: TerminalColorScheme) {
this.editingColorScheme = scheme
this.schemeChanged = false
}
saveScheme () {
let schemes = this.config.store.terminal.customColorSchemes
schemes = schemes.filter(x => x !== this.editingColorScheme && x.name !== this.editingColorScheme!.name)
schemes.push(this.editingColorScheme)
this.config.store.terminal.customColorSchemes = schemes
this.config.save()
this.cancelEditing()
}
cancelEditing () {
this.editingColorScheme = null
}
async deleteScheme (scheme: TerminalColorScheme) {
if ((await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
message: `Delete "${scheme.name}"?`,
buttons: ['Keep', 'Delete'],
defaultId: 1,
}
)).response === 1) {
let schemes = this.config.store.terminal.customColorSchemes
schemes = schemes.filter(x => x !== scheme)
this.config.store.terminal.customColorSchemes = schemes
this.config.save()
}
}
isCustomScheme (scheme: TerminalColorScheme) {
return this.config.store.terminal.customColorSchemes.some(x => deepEqual(x, scheme))
}
colorsTrackBy (index) {
return index
}
getPreviewFontFamily () {
return getCSSFontFamily(this.config.store)
}

View File

@@ -9,6 +9,7 @@ div(
[ngbPopover]='content',
[style.background]='model',
(click)='open()',
autoClose='outside',
container='body',
#popover='ngbPopover',
) {{ title }}

View File

@@ -1,4 +1,4 @@
import { Component, Input, Output, EventEmitter, HostListener, ViewChild } from '@angular/core'
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
/** @hidden */
@@ -12,34 +12,14 @@ export class ColorPickerComponent {
@Input() title: string
@Output() modelChange = new EventEmitter<string>()
@ViewChild('popover') popover: NgbPopover
@ViewChild('input') input
isOpen: boolean
open (): void {
setImmediate(() => {
this.popover.open()
setImmediate(() => {
this.input.nativeElement.focus()
this.isOpen = true
})
this.popover['_windowRef'].location.nativeElement.querySelector('input').focus()
})
}
@HostListener('document:click', ['$event']) onOutsideClick ($event: MouseEvent): void {
if (!this.isOpen) {
return
}
const windowRef = (this.popover as any)._windowRef
if (!windowRef) {
return
}
if ($event.target !== windowRef.location.nativeElement &&
!windowRef.location.nativeElement.contains($event.target)) {
this.popover.close()
this.isOpen = false
}
}
onChange (): void {
this.modelChange.emit(this.model)
}

View File

@@ -0,0 +1,35 @@
.preview(
[style.font-family]='getPreviewFontFamily()',
[style.font-size]='(fontPreview ? config.store.terminal.fontSize : 11) + "px"',
[style.background-color]='scheme.background',
[style.color]='scheme.foreground',
[style.font-feature-settings]='\'"liga" \' + config.store.terminal.ligatures ? 1 : 0',
[style.font-variant-ligatures]='config.store.terminal.ligatures ? "initial" : "none"',
)
div
span([style.color]='scheme.colors[2]') john
span([style.color]='scheme.colors[6]') @
span([style.color]='scheme.colors[4]') doe-pc
strong([style.color]='scheme.colors[1]') $
span ls
span([style.background-color]='scheme.cursor') &nbsp;
div
span -rwxr-xr-x 1 root
strong([style.color]='scheme.colors[3]') Documents
div
span -rwxr-xr-x 1 root
strong([style.color]='scheme.colors[5]') Downloads
div
span -rwxr-xr-x 1 root
strong([style.color]='scheme.colors[13]') Pictures
div
span -rwxr-xr-x 1 root
strong([style.color]='scheme.colors[12]') Music
div(*ngIf='fontPreview')
span -rwxr-xr-x 1 root
span([style.color]='scheme.colors[2]') 実行可能ファイル
div(*ngIf='fontPreview')
span -rwxr-xr-x 1 root
span([style.color]='scheme.colors[6]') sym
span ->
span([style.color]='scheme.colors[1]') link

View File

@@ -0,0 +1,15 @@
:host {
display: block;
}
.preview {
margin-top: 10px;
margin-left: 10px;
padding: 5px 10px;
border-radius: 4px;
overflow: hidden;
span {
white-space: pre;
}
}

View File

@@ -0,0 +1,21 @@
import { Component, Input, ChangeDetectionStrategy } from '@angular/core'
import { ConfigService, getCSSFontFamily } from 'terminus-core'
import { TerminalColorScheme } from '../api/interfaces'
/** @hidden */
@Component({
selector: 'color-scheme-preview',
template: require('./colorSchemePreview.component.pug'),
styles: [require('./colorSchemePreview.component.scss')],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ColorSchemePreviewComponent {
@Input() scheme: TerminalColorScheme
@Input() fontPreview = false
constructor (public config: ConfigService) {}
getPreviewFontFamily (): string {
return getCSSFontFamily(this.config.store)
}
}

View File

@@ -0,0 +1,96 @@
.head
h3.mb-3 Current color scheme
.d-flex.align-items-center(*ngIf='!editing')
span {{getCurrentSchemeName()}}
.mr-auto
.btn-toolbar
button.btn.btn-secondary((click)='editScheme()')
i.fas.fa-pen
span Edit
.mr-1
button.btn.btn-danger(
(click)='deleteScheme(config.store.terminal.colorScheme)',
*ngIf='currentCustomScheme'
)
i.fas.fa-trash
span Delete
div(*ngIf='editing')
.form-group
label Name
input.form-control(type='text', [(ngModel)]='config.store.terminal.colorScheme.name')
.form-group
color-picker(
[(model)]='config.store.terminal.colorScheme.foreground',
(modelChange)='config.save()',
title='FG',
)
color-picker(
[(model)]='config.store.terminal.colorScheme.background',
(modelChange)='config.save()',
title='BG',
)
color-picker(
[(model)]='config.store.terminal.colorScheme.cursor',
(modelChange)='config.save()',
title='CU',
)
color-picker(
*ngFor='let _ of config.store.terminal.colorScheme.colors; let idx = index; trackBy: colorsTrackBy',
[(model)]='config.store.terminal.colorScheme.colors[idx]',
(modelChange)='config.save()',
[title]='idx',
)
color-scheme-preview([scheme]='config.store.terminal.colorScheme')
.btn-toolbar.d-flex.mt-2(*ngIf='editing')
.mr-auto
button.btn.btn-primary((click)='saveScheme()')
i.fas.fa-check
span Save
.mr-1
button.btn.btn-secondary((click)='cancelEditing()')
i.fas.fa-times
span Cancel
hr.mt-3.mb-4
.input-group.mb-3
.input-group-prepend
.input-group-text
i.fas.fa-fw.fa-search
input.form-control(type='search', placeholder='Search color schemes', [(ngModel)]='filter')
.body
.list-group-light.mb-3
ng-container(*ngFor='let scheme of allColorSchemes')
.list-group-item.list-group-item-action(
[hidden]='filter && !scheme.name.toLowerCase().includes(filter.toLowerCase())',
(click)='selectScheme(scheme)',
[class.active]='(currentCustomScheme || currentStockScheme) === scheme'
)
.d-flex.w-100.align-items-center
i.fas.fa-fw([class.fa-check]='(currentCustomScheme || currentStockScheme) === scheme')
.ml-2
.mr-auto
span {{scheme.name}}
.badge.badge-info.ml-2(*ngIf='customColorSchemes.includes(scheme)') Custom
div
.d-flex
.swatch(
*ngFor='let index of colorIndexes.slice(0, 8)',
[style.background-color]='scheme.colors[index]'
)
.d-flex
.swatch(
*ngFor='let index of colorIndexes.slice(8, 16)',
[style.background-color]='scheme.colors[index]'
)
color-scheme-preview([scheme]='scheme')

View File

@@ -0,0 +1,22 @@
.head {
flex: none;
}
.body {
overflow: auto;
flex: auto;
min-height: 0;
}
.swatch {
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 3px;
margin-bottom: 3px;
box-shadow: 0 1px 1px rgba(0, 0, 0, .5);
}
.list-group-item color-scheme-preview {
margin-left: 14px;
}

View File

@@ -0,0 +1,106 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import deepEqual from 'deep-equal'
import { Component, Inject, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'
import { ConfigService, HostAppService, ElectronService } from 'terminus-core'
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
import { TerminalColorScheme } from '../api/interfaces'
/** @hidden */
@Component({
template: require('./colorSchemeSettingsTab.component.pug'),
styles: [require('./colorSchemeSettingsTab.component.scss')],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ColorSchemeSettingsTabComponent {
@Input() stockColorSchemes: TerminalColorScheme[] = []
@Input() customColorSchemes: TerminalColorScheme[] = []
@Input() allColorSchemes: TerminalColorScheme[] = []
@Input() filter = ''
@Input() editing = false
colorIndexes = [...new Array(16).keys()]
currentStockScheme: TerminalColorScheme|null = null
currentCustomScheme: TerminalColorScheme|null = null
constructor (
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
private changeDetector: ChangeDetectorRef,
private hostApp: HostAppService,
private electron: ElectronService,
public config: ConfigService,
) { }
async ngOnInit () {
this.stockColorSchemes = (await Promise.all(this.config.enabledServices(this.colorSchemeProviders).map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
this.stockColorSchemes.sort((a, b) => a.name.localeCompare(b.name))
this.customColorSchemes = this.config.store.terminal.customColorSchemes
this.changeDetector.markForCheck()
this.update()
}
ngOnChanges () {
this.update()
}
selectScheme (scheme: TerminalColorScheme) {
this.config.store.terminal.colorScheme = { ...scheme }
this.config.save()
this.cancelEditing()
this.update()
}
update () {
this.currentCustomScheme = this.findMatchingScheme(this.config.store.terminal.colorScheme, this.customColorSchemes)
this.currentStockScheme = this.findMatchingScheme(this.config.store.terminal.colorScheme, this.stockColorSchemes)
this.allColorSchemes = this.customColorSchemes.concat(this.stockColorSchemes)
this.changeDetector.markForCheck()
}
editScheme () {
this.editing = true
}
saveScheme () {
this.customColorSchemes = this.customColorSchemes.filter(x => x.name !== this.config.store.terminal.colorScheme.name)
this.customColorSchemes.push(this.config.store.terminal.colorScheme)
this.config.store.terminal.customColorSchemes = this.customColorSchemes
this.config.save()
this.cancelEditing()
this.update()
}
cancelEditing () {
this.editing = false
}
async deleteScheme (scheme: TerminalColorScheme) {
if ((await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
message: `Delete "${scheme.name}"?`,
buttons: ['Keep', 'Delete'],
defaultId: 1,
}
)).response === 1) {
this.customColorSchemes = this.customColorSchemes.filter(x => x.name !== scheme.name)
this.config.store.terminal.customColorSchemes = this.customColorSchemes
this.config.save()
this.update()
}
}
getCurrentSchemeName () {
return (this.currentCustomScheme || this.currentStockScheme)?.name || 'Custom'
}
findMatchingScheme (scheme: TerminalColorScheme, schemes: TerminalColorScheme[]) {
return schemes.find(x => deepEqual(x, scheme)) || null
}
colorsTrackBy (index) {
return index
}
}

View File

@@ -1,36 +1,51 @@
.input-group.w-100
input.search-input.form-control(
type='search',
[(ngModel)]='query',
(ngModelChange)='onQueryChange()',
[class.text-danger]='notFound',
(click)='$event.stopPropagation()',
(keyup.enter)='findNext()',
(keyup.esc)='close.emit()',
placeholder='Search...'
)
.input-group-append
.input-group-text
a(
(click)='options.caseSensitive = !options.caseSensitive',
[class.text-info]='options.caseSensitive',
ngbTooltip='Case sensitivity',
placement='bottom'
)
i.fa.fa-fw.fa-font
a(
(click)='options.regex = !options.regex',
[class.text-info]='options.regex',
ngbTooltip='Regular expression',
placement='bottom'
)
i.fa.fa-fw.fa-asterisk
a(
(click)='options.wholeWord = !options.wholeWord',
[class.text-info]='options.wholeWord',
ngbTooltip='Whole word',
placement='bottom'
)
i.fa.fa-fw.fa-text-width
input.search-input.form-control(
type='search',
[(ngModel)]='query',
(ngModelChange)='onQueryChange()',
[class.text-danger]='notFound',
(click)='$event.stopPropagation()',
(keyup.enter)='findPrevious()',
(keyup.esc)='close.emit()',
placeholder='Search...'
)
button.btn.btn-link(
(click)='findPrevious()',
ngbTooltip='Next',
placement='bottom'
)
i.fa.fa-fw.fa-arrow-up
button.btn.btn-link(
(click)='findNext()',
ngbTooltip='Next',
placement='bottom'
)
i.fa.fa-fw.fa-arrow-down
.mr-2
button.btn.btn-link(
(click)='options.caseSensitive = !options.caseSensitive',
[class.active]='options.caseSensitive',
ngbTooltip='Case sensitivity',
placement='bottom'
)
i.fa.fa-fw.fa-font
button.btn.btn-link(
(click)='options.regex = !options.regex',
[class.active]='options.regex',
ngbTooltip='Regular expression',
placement='bottom'
)
i.fa.fa-fw.fa-asterisk
button.btn.btn-link(
(click)='options.wholeWord = !options.wholeWord',
[class.active]='options.wholeWord',
ngbTooltip='Whole word',
placement='bottom'
)
i.fa.fa-fw.fa-text-width
button.close.text-light.pl-3.pr-2((click)='close.emit()') &times;

View File

@@ -5,16 +5,13 @@
z-index: 5;
padding: 10px;
border-radius: 0 0 3px 3px;
background: rgba(0, 0, 0, .75);
background: rgba(0, 0, 0, .95);
border: 1px solid rgba(0, 0, 0, .5);
border-top: 0;
display: flex;
a {
padding-left: 10px;
&:first-child {
padding-left: 0;
}
button {
padding: 0 6px;
flex-shrink: 0;
}
}

View File

@@ -23,18 +23,24 @@ export class SearchPanelComponent {
onQueryChange (): void {
this.notFound = false
this.findNext(true)
this.findPrevious(true)
}
findNext (incremental = false): void {
if (!this.query) {
return
}
if (!this.frontend.findNext(this.query, { ...this.options, incremental: incremental || undefined })) {
this.notFound = true
this.toastr.error('Not found')
}
}
findPrevious (): void {
if (!this.frontend.findPrevious(this.query, this.options)) {
findPrevious (incremental = false): void {
if (!this.query) {
return
}
if (!this.frontend.findPrevious(this.query, { ...this.options, incremental: incremental || undefined })) {
this.notFound = true
this.toastr.error('Not found')
}

View File

@@ -11,7 +11,7 @@ h3.mb-3 Shell
)
option(
*ngFor='let profile of profiles',
[ngValue]='slugify(profile.name).toLowerCase()'
[ngValue]='terminal.getProfileID(profile)'
) {{profile.name}}
@@ -74,6 +74,16 @@ h3.mb-3 Shell
environment-editor([(model)]='this.config.store.terminal.environment')
.form-line(*ngIf='config.store.terminal.profiles.length > 0')
.header
.title Show default profiles in the selector
.description If disabled, only custom profiles will show up in the profile selector
toggle(
[(ngModel)]='config.store.terminal.showDefaultProfiles',
(ngModelChange)='config.save()'
)
h3.mt-3 Saved Profiles
.list-group.list-group-flush.mt-3.mb-3

View File

@@ -1,4 +1,3 @@
import slugify from 'slugify'
import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Subscription } from 'rxjs'
@@ -17,14 +16,13 @@ export class ShellSettingsTabComponent {
Platform = Platform
isConPTYAvailable: boolean
isConPTYStable: boolean
slugify = slugify
private configSubscription: Subscription
constructor (
public config: ConfigService,
public hostApp: HostAppService,
public terminal: TerminalService,
private electron: ElectronService,
private terminalService: TerminalService,
private ngbModal: NgbModal,
) {
config.store.terminal.environment = config.store.terminal.environment || {}
@@ -38,7 +36,7 @@ export class ShellSettingsTabComponent {
}
async ngOnInit (): Promise<void> {
this.shells = await this.terminalService.shells$.toPromise()
this.shells = await this.terminal.shells$.toPromise()
}
ngOnDestroy (): void {
@@ -46,21 +44,22 @@ export class ShellSettingsTabComponent {
}
async reload (): Promise<void> {
this.profiles = await this.terminalService.getProfiles(true)
this.profiles = await this.terminal.getProfiles({ includeHidden: true })
}
pickWorkingDirectory (): void {
const shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
async pickWorkingDirectory (): Promise<void> {
const profile = await this.terminal.getProfileByID(this.config.store.terminal.profile)
const shell = this.shells.find(x => x.id === profile?.shell)
if (!shell) {
return
}
const paths = this.electron.dialog.showOpenDialog(
const paths = (await this.electron.dialog.showOpenDialog(
this.hostApp.getWindow(),
{
defaultPath: shell.fsBase,
properties: ['openDirectory', 'showHiddenFiles'],
}
)
)).filePaths
if (paths) {
this.config.store.terminal.workingDirectory = paths[0]
}
@@ -69,7 +68,8 @@ export class ShellSettingsTabComponent {
newProfile (shell: Shell): void {
const profile: Profile = {
name: shell.name || '',
sessionOptions: this.terminalService.optionsFromShell(shell),
shell: shell.id,
sessionOptions: this.terminal.optionsFromShell(shell),
}
this.config.store.terminal.profiles = [profile, ...this.config.store.terminal.profiles]
this.config.save()

View File

@@ -29,11 +29,11 @@ h3.mb-3 Terminal
[value]='"audible"'
)
| Audible
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.bell != "audible" && config.store.terminal.shell.startsWith("wsl")')
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.bell != "audible" && config.store.terminal.profile.startsWith("wsl")')
.mr-auto WSL terminal bell can only be muted via Volume Mixer
button.btn.btn-secondary((click)='openWSLVolumeMixer()') Show Mixer
.form-line
.header
.title Right click
@@ -63,11 +63,11 @@ h3.mb-3 Terminal
value='paste'
)
| Paste
.form-line
.header
.title Paste on middle-click
toggle(
[(ngModel)]='config.store.terminal.pasteOnMiddleClick',
(ngModelChange)='config.save()',
@@ -76,7 +76,7 @@ h3.mb-3 Terminal
.form-line
.header
.title Auto-open a terminal on app start
toggle(
[(ngModel)]='config.store.terminal.autoOpen',
(ngModelChange)='config.save()',
@@ -85,7 +85,7 @@ h3.mb-3 Terminal
.form-line
.header
.title Restore terminal tabs on app start
toggle(
[(ngModel)]='config.store.terminal.recoverTabs',
(ngModelChange)='config.save()',
@@ -116,7 +116,7 @@ h3.mb-3 Terminal
[(ngModel)]='config.store.terminal.scrollOnInput',
(ngModelChange)='config.save()',
)
.form-line
.header
.title Use Alt key as the Meta key
@@ -125,3 +125,23 @@ h3.mb-3 Terminal
[(ngModel)]='config.store.terminal.altIsMeta',
(ngModelChange)='config.save()',
)
.form-line
.header
.title Word separators
.description Double-click selection will stop at these characters
input.form-control(
type='text',
placeholder=' ()[]{}\'"',
[(ngModel)]='config.store.terminal.wordSeparator',
(ngModelChange)='config.save()',
)
.form-line
.header
.title Warn on multi-line paste
.description Show a confirmation box when pasting multiple lines
toggle(
[(ngModel)]='config.store.terminal.warnOnMultilinePaste',
(ngModelChange)='config.save()',
)

View File

@@ -31,11 +31,13 @@ export class TerminalConfigProvider extends ConfigProvider {
workingDirectory: '',
alwaysUseWorkingDirectory: false,
altIsMeta: false,
wordSeparator: ' ()[]{}\'"',
colorScheme: {
__nonStructural: true,
name: 'Material',
foreground: '#eceff1',
background: 'rgba(38, 50, 56, 1)',
selection: null,
cursor: '#FFCC00',
colors: [
'#000000',
@@ -61,6 +63,8 @@ export class TerminalConfigProvider extends ConfigProvider {
profiles: [],
useConPTY: true,
recoverTabs: true,
warnOnMultilinePaste: true,
showDefaultProfiles: true,
},
}

View File

@@ -121,6 +121,11 @@ export class XTermFrontend extends Frontend {
this.xtermCore.updateCursorStyle(e)
keyboardEventHandler('keyup', e)
}
this.xterm.buffer.onBufferChange(() => {
const altBufferActive = this.xterm.buffer.active === this.xterm.buffer.alternate
this.alternateScreenActive.next(altBufferActive)
})
}
attach (host: HTMLElement): void {
@@ -162,10 +167,30 @@ export class XTermFrontend extends Frontend {
}
copySelection (): void {
require('electron').remote.clipboard.write({
text: this.getSelection(),
html: this.getSelectionAsHTML(),
})
let text = this.getSelection()
let lines = text.split('\n')
if (lines.some(x => x.length === this.xterm.cols)) {
text = ''
let lastLineWraps = false
for (let line of lines) {
if (!lastLineWraps) {
text += '\n'
}
text += line
lastLineWraps = line.length === this.xterm.cols
}
}
if (text.length < 1024 * 32) {
require('electron').remote.clipboard.write({
text: text,
html: this.getSelectionAsHTML(),
})
} else {
require('electron').remote.clipboard.write({
text: text,
})
}
}
clearSelection (): void {
@@ -215,6 +240,7 @@ export class XTermFrontend extends Frontend {
this.xterm.setOption('cursorBlink', config.terminal.cursorBlink)
this.xterm.setOption('macOptionIsMeta', config.terminal.altIsMeta)
this.xterm.setOption('scrollback', 100000)
this.xterm.setOption('wordSeparator', config.terminal.wordSeparator)
this.configuredFontSize = config.terminal.fontSize
this.configuredLinePadding = config.terminal.linePadding
this.setFontSize()
@@ -223,6 +249,7 @@ export class XTermFrontend extends Frontend {
const theme: ITheme = {
foreground: config.terminal.colorScheme.foreground,
selection: config.terminal.colorScheme.selection || '#88888888',
background: config.terminal.background === 'colorScheme' ? config.terminal.colorScheme.background : '#00000000',
cursor: config.terminal.colorScheme.cursor,
}
@@ -304,7 +331,7 @@ export class XTermFrontend extends Frontend {
private getLineAsHTML (y: number, start: number, end: number): string {
let html = '<div>'
let lastStyle: string|null = null
const line = (this.xterm.buffer.getLine(y) as any)._line
const line = (this.xterm.buffer.active.getLine(y) as any)._line
const cell = new CellData()
for (let i = start; i < end; i++) {
line.loadCell(i, cell)

View File

@@ -1,4 +1,3 @@
import slugify from 'slugify'
import { Injectable } from '@angular/core'
import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
import { TerminalService } from './services/terminal.service'
@@ -78,7 +77,7 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
return [
...this.hotkeys,
...profiles.map(profile => ({
id: `profile.${slugify(profile.name).toLowerCase()}`,
id: `profile.${this.terminal.getProfileID(profile)}`,
name: `New tab: ${profile.name}`,
})),
]

View File

@@ -1,5 +1,4 @@
import * as fs from 'mz/fs'
import slugify from 'slugify'
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
@@ -11,10 +10,12 @@ import TerminusCorePlugin, { HostAppService, ToolbarButtonProvider, TabRecoveryP
import { SettingsTabProvider } from 'terminus-settings'
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
import { ColorSchemeSettingsTabComponent } from './components/colorSchemeSettingsTab.component'
import { TerminalTabComponent } from './components/terminalTab.component'
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
import { ColorPickerComponent } from './components/colorPicker.component'
import { ColorSchemePreviewComponent } from './components/colorSchemePreview.component'
import { EditProfileModalComponent } from './components/editProfileModal.component'
import { EnvironmentEditorComponent } from './components/environmentEditor.component'
import { SearchPanelComponent } from './components/searchPanel.component'
@@ -30,7 +31,7 @@ import { TerminalDecorator } from './api/decorator'
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
import { ShellProvider } from './api/shellProvider'
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ShellSettingsTabProvider } from './settings'
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ColorSchemeSettingsTabProvider, ShellSettingsTabProvider } from './settings'
import { DebugDecorator } from './features/debug'
import { PathDropDecorator } from './features/pathDrop'
import { ZModemDecorator } from './features/zmodem'
@@ -68,6 +69,7 @@ import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
],
providers: [
{ provide: SettingsTabProvider, useClass: AppearanceSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: ColorSchemeSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: ShellSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: TerminalSettingsTabProvider, multi: true },
@@ -106,14 +108,17 @@ import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
entryComponents: [
TerminalTabComponent,
AppearanceSettingsTabComponent,
ColorSchemeSettingsTabComponent,
ShellSettingsTabComponent,
TerminalSettingsTabComponent,
EditProfileModalComponent,
] as any[],
declarations: [
ColorPickerComponent,
ColorSchemePreviewComponent,
TerminalTabComponent,
AppearanceSettingsTabComponent,
ColorSchemeSettingsTabComponent,
ShellSettingsTabComponent,
TerminalSettingsTabComponent,
EditProfileModalComponent,
@@ -127,7 +132,7 @@ import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
],
})
export default class TerminalModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
constructor (
private constructor (
app: AppService,
config: ConfigService,
hotkeys: HotkeysService,
@@ -181,8 +186,7 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
hostApp.newWindow()
}
if (hotkey.startsWith('profile.')) {
const profiles = await terminal.getProfiles()
const profile = profiles.find(x => slugify(x.name).toLowerCase() === hotkey.split('.')[1])
const profile = await terminal.getProfileByID(hotkey.split('.')[1])
if (profile) {
terminal.openTabWithOptions(profile.sessionOptions)
}

View File

@@ -332,7 +332,7 @@ export class SessionsService {
logger: Logger
private lastID = 0
constructor (
private constructor (
log: LogService,
) {
require('../bufferizedPTY')(nodePTY) // eslint-disable-line @typescript-eslint/no-var-requires

View File

@@ -19,7 +19,7 @@ export class TerminalService {
get shells$ (): Observable<Shell[]> { return this.shells }
/** @hidden */
constructor (
private constructor (
private app: AppService,
private config: ConfigService,
private uac: UACService,
@@ -34,12 +34,13 @@ export class TerminalService {
})
}
async getProfiles (includeHidden?: boolean): Promise<Profile[]> {
async getProfiles ({ includeHidden, skipDefault }: { includeHidden?: boolean, skipDefault?: boolean } = {}): Promise<Profile[]> {
const shells = await this.shells$.toPromise()
return [
...this.config.store.terminal.profiles,
...shells.filter(x => includeHidden || !x.hidden).map(shell => ({
...skipDefault ? [] : shells.filter(x => includeHidden || !x.hidden).map(shell => ({
name: shell.name,
shell: shell.id,
icon: shell.icon,
sessionOptions: this.optionsFromShell(shell),
isBuiltin: true,
@@ -47,14 +48,25 @@ export class TerminalService {
]
}
getProfileID (profile: Profile): string {
return slugify(profile.name).toLowerCase()
}
async getProfileByID (id: string): Promise<Profile> {
const profiles = await this.getProfiles({ includeHidden: true })
return profiles.find(x => this.getProfileID(x) === id) || profiles[0]
}
/**
* Launches a new terminal with a specific shell and CWD
* @param pause Wait for a keypress when the shell exits
*/
async openTab (profile?: Profile, cwd?: string|null, pause?: boolean): Promise<TerminalTabComponent> {
if (!profile) {
const profiles = await this.getProfiles(true)
profile = profiles.find(x => slugify(x.name).toLowerCase() === this.config.store.terminal.profile) || profiles[0]
profile = await this.getProfileByID(this.config.store.terminal.profile)
if (!profile) {
profile = (await this.getProfiles({ includeHidden: true }))[0]
}
}
cwd = cwd || profile.sessionOptions.cwd

View File

@@ -10,7 +10,7 @@ export class TerminalFrontendService {
private containers = new WeakMap<BaseSession, Frontend>()
/** @hidden */
constructor (
private constructor (
private config: ConfigService,
private themes: ThemesService,
private hotkeys: HotkeysService,

View File

@@ -8,7 +8,7 @@ import { SessionOptions } from '../api/interfaces'
export class UACService {
isAvailable = false
constructor (
private constructor (
private electron: ElectronService,
) {
this.isAvailable = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED)

View File

@@ -4,12 +4,13 @@ import { SettingsTabProvider } from 'terminus-settings'
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
import { ColorSchemeSettingsTabComponent } from './components/colorSchemeSettingsTab.component'
/** @hidden */
@Injectable()
export class AppearanceSettingsTabProvider extends SettingsTabProvider {
id = 'terminal-appearance'
icon = 'palette'
icon = 'swatchbook'
title = 'Appearance'
getComponentType (): any {
@@ -17,6 +18,18 @@ export class AppearanceSettingsTabProvider extends SettingsTabProvider {
}
}
/** @hidden */
@Injectable()
export class ColorSchemeSettingsTabProvider extends SettingsTabProvider {
id = 'terminal-color-scheme'
icon = 'palette'
title = 'Color Scheme'
getComponentType (): any {
return ColorSchemeSettingsTabComponent
}
}
/** @hidden */
@Injectable()
export class ShellSettingsTabProvider extends SettingsTabProvider {

View File

@@ -88,13 +88,15 @@ export class WSLShellProvider extends ShellProvider {
if (!childKey.DistributionName) {
continue
}
const wslVersion = childKey.Flags.value & 8 ? 2 : 1
const name = childKey.DistributionName.value
const fsBase = wslVersion === 2 ? `\\\\wsl$\\${name}` : childKey.BasePath.value as string + '\\rootfs'
const shell: Shell = {
id: `wsl-${slugify(name)}`,
name: `WSL / ${name}`,
command: wslPath,
args: ['-d', name],
fsBase: childKey.BasePath.value as string + '\\rootfs',
fsBase,
env: {
TERM: 'xterm-color',
COLORTERM: 'truecolor',

View File

@@ -120,7 +120,7 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
/** @hidden */
@Injectable()
export class CopyPasteContextMenu extends TabContextMenuItemProvider {
weight = 1
weight = -10
constructor (
private zone: NgZone,

View File

@@ -224,10 +224,10 @@ uuid@^7.0.1:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.1.tgz#95ed6ff3d8c881cbf85f0f05cc3915ef994818ef"
integrity sha512-yqjRXZzSJm9Dbl84H2VDHpM3zMjzSJQ+hn6C4zqd5ilW+7P4ZmLEEqwho9LjP+tGuZlF4xrHQXT0h9QZUS/pWA==
xterm-addon-fit@^0.4.0-beta2:
version "0.4.0-beta2"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.4.0-beta2.tgz#c638ea7d41c55b535825f41b1cdb7358a94dfca4"
integrity sha512-7EHWk8SPCmKuw9ux1mFek2SfBw1QjJ/ObYA87tubOtJi7mAZ0eIb9IE5ditcma9Nyz/cR/ROQQxoRn4UbDvyfA==
xterm-addon-fit@^0.4.0-beta.8:
version "0.4.0-beta.8"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.4.0-beta.8.tgz#3d38b16335a3f54d254bb446e554699319563a6f"
integrity sha512-gFfMQ9TeCELggiANB+z3y3rpleOK0Fc59rwJDbBRRVaMNGJW3Xedl5Ne6xJ+vqkqugYq66vl4CwrMRYylyq5IQ==
xterm-addon-ligatures@^0.2.1:
version "0.2.1"
@@ -237,30 +237,30 @@ xterm-addon-ligatures@^0.2.1:
font-finder "^1.0.4"
font-ligatures "^1.3.2"
xterm-addon-search@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.5.0.tgz#cd3a2f8056084c28e236d4e732da37682010bcc2"
integrity sha512-zLVqVTrg5w2nk9fRj3UuVKCPo/dmFe/cLf3EM9Is5Dm6cgOoXmeo9eq2KgD8A0gquAflTFTf0ya2NaFmShHwyg==
xterm-addon-search@^0.7.0-beta.1:
version "0.7.0-beta.1"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.7.0-beta.1.tgz#9178c14ae13062cc42a620e02ecbf511940ddc32"
integrity sha512-D/CnYl6s3bGTdqvB+AFO5DbPQiM+loZ2rQas1LVWCk0qkbu5aef4rkK0OpIGQJUrGh9Y2mnrZk7p4SDeTSurzA==
xterm-addon-serialize@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.1.2.tgz#339a38520bf90cf51f447cb74f3ae0e530d5ee39"
integrity sha512-etSTiN+I3lqWefMixiiVo1V4lPjmfInFmwtjbYDYWyUwPU5tveEZZSu15b52Q26IPaJdl8RxBgNTYu6Q3YauLQ==
xterm-addon-serialize@^0.3.0-beta.3:
version "0.3.0-beta.3"
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.3.0-beta.3.tgz#43e069fdb0e7e84cb1da79bf596099ff02885904"
integrity sha512-avgc1LcuIZrLQm96USogysIsOmcrmT1Kb4jAu5GHFM8Y8Z35AHFuIYRg7b2RQQFJb7PKQ3y5Ki6UE0PuFZMMDg==
xterm-addon-unicode11@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.1.1.tgz#b209ef137db38096f68636af4ef4d0c0acba85ad"
integrity sha512-z6vJTL+dpNljwAYzYoyDjJP8A2XjZuEosl0sRa+FGRf3jEyEVWquDM53MfUd1ztVdAPQ839qR6eYK1BXV04Bhw==
xterm-addon-unicode11@^0.2.0-beta.5:
version "0.2.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
xterm-addon-webgl@^0.6.0-beta.2:
version "0.6.0-beta.3"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.6.0-beta.3.tgz#48abe4607659caaec3175c0105298bba5e34be27"
integrity sha512-2mhW/4Qv4i4KhEbtOAL4bc9FPGXON8XuM3vfKXT0EauXy/7ygtPu8IqrYNvNo0uJUoW6gOf0d5+/6kUMak2YYg==
xterm-addon-webgl@^0.7.0-beta.5:
version "0.7.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.5.tgz#20fbafcf2fb2c2438977c40fd41945d297ea0c25"
integrity sha512-Mf0PYiWe4GL8mcS4KnjVsosbvD2xSxUCappbTRNZ+5hQgmrayrr6UciKw7CasSLOsji8AHkoZJEl0MxMsTTEeg==
xterm@^4.5.0-beta.9:
version "4.5.0-beta.9"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.5.0-beta.9.tgz#8e3610031d0114a3b112bfd1aaeebd181e1230fa"
integrity sha512-GfsHrQIMjIHVqDdTZoZl/fsMB/73Cltw2aR/gMYz2gZq8fzzxTrgSseiQD1rnIRrcbfmVEF4cFQARQwZj6hGlg==
version "4.5.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.5.0.tgz#c7fd145c6cf91c9f2ef07011a9b35026cf4bfecc"
integrity sha512-4t12tsvtYnv13FBJwewddxdI/j4kSonmbQQv50j34R/rPIFbUNGtptbprmuUlTDAKvHLMDZ/Np2XcpNimga/HQ==
yallist@^2.1.2:
version "2.1.2"

1030
yarn.lock

File diff suppressed because it is too large Load Diff