Compare commits

...

276 Commits

Author SHA1 Message Date
Eugene Pankov
bc7a537c4c lint 2020-12-27 21:03:12 +01:00
Eugene Pankov
10ae6ffd99 build fix 2020-12-27 20:58:25 +01:00
Eugene Pankov
847628fbff Merge branch 'master' of github.com:Eugeny/terminus 2020-12-27 18:51:14 +01:00
Eugene Pankov
b502c3e84d fixed notification size 2020-12-27 18:51:12 +01:00
Eugene Pankov
85e99ff0a8 build fix 2020-12-27 13:15:04 +01:00
Eugene Pankov
02de15a6d2 re-added missing dep 2020-12-27 13:03:46 +01:00
Eugene Pankov
38a6e7fe67 work around win32 fluent background bugs - #949 2020-12-27 13:03:38 +01:00
Eugene Pankov
e98c12d409 lint typescript-eslint/prefer-enum-initializers 2020-12-24 18:59:33 +01:00
Eugene Pankov
aacc603309 lint typescript-eslint/consistent-indexed-object-style 2020-12-24 18:56:59 +01:00
Eugene
2ef3a81dd8 Merge pull request #3218 from Eugeny/dependabot/npm_and_yarn/electron-11.1.1
Bump electron from 8.5.2 to 11.1.1
2020-12-24 18:51:14 +01:00
Eugene
22ef1bbb87 Merge pull request #3238 from Eugeny/dependabot/npm_and_yarn/extend-3.0.2
[Security] Bump extend from 3.0.1 to 3.0.2
2020-12-24 18:50:42 +01:00
Eugene
7ff9f268c9 Merge pull request #3236 from Eugeny/dependabot/npm_and_yarn/debug-2.6.9
[Security] Bump debug from 2.6.8 to 2.6.9
2020-12-24 18:50:25 +01:00
Eugene
7866bcd9a4 Merge pull request #3227 from Eugeny/dependabot/npm_and_yarn/highlight.js-10.5.0
[Security] Bump highlight.js from 10.0.1 to 10.5.0
2020-12-24 18:50:11 +01:00
Eugene
5a20ac19d9 Merge pull request #3198 from Eugeny/dependabot/npm_and_yarn/app/ini-1.3.7
[Security] Bump ini from 1.3.5 to 1.3.7 in /app
2020-12-24 18:50:02 +01:00
Eugene
915f6acf22 Merge pull request #3199 from Eugeny/dependabot/npm_and_yarn/ini-1.3.7
[Security] Bump ini from 1.3.5 to 1.3.7
2020-12-24 18:49:51 +01:00
Eugene
59b73fcdc1 Merge pull request #2999 from Eugeny/dependabot/npm_and_yarn/bl-1.2.3
[Security] Bump bl from 1.2.2 to 1.2.3
2020-12-24 18:49:44 +01:00
Eugene
8699634492 Merge pull request #3237 from Eugeny/all-contributors/add-pinpins 2020-12-24 18:49:06 +01:00
dependabot-preview[bot]
d625e90464 [Security] Bump extend from 3.0.1 to 3.0.2
Bumps [extend](https://github.com/justmoon/node-extend) from 3.0.1 to 3.0.2. **This update includes a security fix.**
- [Release notes](https://github.com/justmoon/node-extend/releases)
- [Changelog](https://github.com/justmoon/node-extend/blob/main/CHANGELOG.md)
- [Commits](https://github.com/justmoon/node-extend/compare/v3.0.1...v3.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:47:34 +00:00
allcontributors[bot]
bc31c775e9 docs: update .all-contributorsrc [skip ci] 2020-12-24 17:46:47 +00:00
allcontributors[bot]
49424e8da5 docs: update README.md [skip ci] 2020-12-24 17:46:46 +00:00
dependabot-preview[bot]
2526c4e458 [Security] Bump debug from 2.6.8 to 2.6.9
Bumps [debug](https://github.com/visionmedia/debug) from 2.6.8 to 2.6.9. **This update includes a security fix.**
- [Release notes](https://github.com/visionmedia/debug/releases)
- [Changelog](https://github.com/visionmedia/debug/blob/2.6.9/CHANGELOG.md)
- [Commits](https://github.com/visionmedia/debug/compare/2.6.8...2.6.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:46:38 +00:00
dependabot-preview[bot]
24de3ba77c Bump electron from 8.5.2 to 11.1.1
Bumps [electron](https://github.com/electron/electron) from 8.5.2 to 11.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.5.2...v11.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:46:21 +00:00
dependabot-preview[bot]
157ed82000 [Security] Bump highlight.js from 10.0.1 to 10.5.0
Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 10.0.1 to 10.5.0. **This update includes security fixes.**
- [Release notes](https://github.com/highlightjs/highlight.js/releases)
- [Changelog](https://github.com/highlightjs/highlight.js/blob/master/CHANGES.md)
- [Commits](https://github.com/highlightjs/highlight.js/compare/10.0.1...10.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:45:34 +00:00
dependabot-preview[bot]
8275a9449a [Security] Bump ini from 1.3.5 to 1.3.7 in /app
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7. **This update includes a security fix.**
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:45:23 +00:00
dependabot-preview[bot]
6ed6b90840 [Security] Bump ini from 1.3.5 to 1.3.7
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7. **This update includes a security fix.**
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:45:16 +00:00
dependabot-preview[bot]
de827ef61a [Security] Bump bl from 1.2.2 to 1.2.3
Bumps [bl](https://github.com/rvagg/bl) from 1.2.2 to 1.2.3. **This update includes a security fix.**
- [Release notes](https://github.com/rvagg/bl/releases)
- [Commits](https://github.com/rvagg/bl/compare/v1.2.2...v1.2.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-24 17:44:58 +00:00
Eugene
bcdbab43de Merge pull request #3226 from pinpins/terminus_pinpin 2020-12-24 18:43:18 +01:00
Eugene Pankov
a24f52c58a more build fixes 2020-12-24 18:18:07 +01:00
Eugene Pankov
0e745ea607 Update package.json 2020-12-24 16:49:48 +01:00
Eugene Pankov
8fe9232d9b Update lint.yml 2020-12-24 16:30:00 +01:00
Eugene Pankov
e6004fa980 build on big sur 2020-12-24 16:21:38 +01:00
Eugene Pankov
987b89b914 build fixes 2020-12-24 16:16:13 +01:00
Eugene Pankov
9fddfa6fc2 removed temp files 2020-12-24 16:10:31 +01:00
Eugene Pankov
6d765bb1b8 build fixes 2020-12-24 16:04:15 +01:00
Eugene Pankov
0ca971a289 electron 11 cleanup 2020-12-24 14:03:14 +01:00
pinpins
e87f6e7af0 Support for Apple Silicon via node 15, electron 11.1 update 2020-12-23 22:45:47 +02:00
pinpins
56be0a1085 Merge branch 'master' into terminus_pinpin 2020-12-18 15:56:18 +02:00
pinpins
41f464d21d Merge branch 'master' into terminus_pinpin
update from master
2020-12-18 14:17:40 +02:00
pinpins
c8dde73158 remove DS_Store 2020-12-18 13:46:50 +02:00
Eugene Pankov
0971a85db4 ssh: added dynamic port forwarding (fixes #2077) 2020-12-13 13:36:37 +01:00
Eugene Pankov
51d54a8477 fixed compact theme icon size (fixes #3196, fixes #3197) 2020-12-13 13:36:09 +01:00
Eugene Pankov
b75775283f use run-script-os for xcopy 2020-12-13 12:21:28 +01:00
Eugene Pankov
66558290a0 fixed missing tabs at the bottom 2020-12-09 09:30:20 +01:00
Eugene
a1980afd9d Merge pull request #3158 from Eugeny/dependabot/npm_and_yarn/sentry/electron-2.0.4
Bump @sentry/electron from 1.5.1 to 2.0.4
2020-12-06 19:26:27 +01:00
Eugene
2b28802ce7 Merge pull request #3049 from Eugeny/dependabot/npm_and_yarn/electron-8.5.2
Bump electron from 8.2.5 to 8.5.2
2020-12-06 19:25:58 +01:00
Eugene
0514a7c229 Merge pull request #3178 from Eugeny/all-contributors/add-TakuroOnoda 2020-12-06 19:21:10 +01:00
allcontributors[bot]
326901b7e8 docs: update .all-contributorsrc [skip ci] 2020-12-06 18:20:37 +00:00
allcontributors[bot]
bbe6b61d63 docs: update README.md [skip ci] 2020-12-06 18:20:36 +00:00
Eugene
204c1057db Merge pull request #3084 from TakuroOnoda/feature/sidetab 2020-12-06 19:20:17 +01:00
Eugene Pankov
dff6a2470c refined vertical tabs 2020-12-06 19:12:15 +01:00
Eugene
cbebc09504 Merge branch 'master' into feature/sidetab 2020-12-06 18:21:03 +01:00
Eugene Pankov
f56dd71f43 Merge branch 'master' of github.com:Eugeny/terminus 2020-12-06 18:14:36 +01:00
Eugene Pankov
17f52a257e PS ctrl-left, ctrl-right and ctrl-del bindings (#507, #2739) 2020-12-06 18:11:15 +01:00
Eugene
8d09ddb686 Merge pull request #3177 from Eugeny/all-contributors/add-pinpins 2020-12-06 17:43:21 +01:00
Eugene Pankov
e6fd31e0b0 don't try to load the private key if not selected - fixes #2968 2020-12-06 17:43:00 +01:00
allcontributors[bot]
c6188a49f5 docs: update .all-contributorsrc [skip ci] 2020-12-06 16:28:09 +00:00
allcontributors[bot]
9a60b4d102 docs: update README.md [skip ci] 2020-12-06 16:28:08 +00:00
Eugene Pankov
7977c1d644 cleanup 2020-12-06 17:27:45 +01:00
Eugene
ac85a1d7d3 Merge pull request #3142 from pinpins/master 2020-12-06 17:25:19 +01:00
Eugene Pankov
86b503093c only send args to the most recent window 2020-12-06 17:03:07 +01:00
Eugene Pankov
dd3e7a0f89 fixed #2558 2020-12-06 15:39:49 +01:00
Eugene
8905106b48 Merge pull request #3174 from opensorceror/opensorceror-patch-1
Fix typos
2020-12-04 09:03:00 +01:00
Harsh Gadgil
225760a9a5 Update api.ts
Fix typos
2020-12-03 19:09:26 -05:00
dependabot-preview[bot]
4aa79a76ea Bump @sentry/electron from 1.5.1 to 2.0.4
Bumps [@sentry/electron](https://github.com/getsentry/sentry-electron) from 1.5.1 to 2.0.4.
- [Release notes](https://github.com/getsentry/sentry-electron/releases)
- [Changelog](https://github.com/getsentry/sentry-electron/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-electron/compare/v1.5.1...2.0.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-24 04:23:53 +00:00
pinpins
1e2d6c7e75 script for local macos release 2020-11-21 20:53:17 +02:00
pinpin
f1e79e9ada Fixes based on PR reviews 2020-11-17 09:32:02 +02:00
pinpin
37cc37650e Fixes based on PR reviews 2020-11-17 09:14:05 +02:00
pinpin
d607b7423a fix 2020-11-16 22:33:16 +02:00
pinpin
a2e843ec84 fix 2020-11-16 22:33:13 +02:00
pinpin
17cafbfa52 add restart prompt 2020-11-16 22:19:44 +02:00
pinpin
91333abc4f add restart prompt 2020-11-16 22:17:19 +02:00
pinpin
05b2b11af5 add restart prompt 2020-11-16 22:16:37 +02:00
pinpin
3931e8088e revert version of node 2020-11-16 21:44:20 +02:00
pinpin
299ede2eb1 Add Hide Tab Index and Hide Tab Close Button 2020-11-16 21:41:11 +02:00
pinpin
4fed323a2a Revert "remove workwlows temporary"
This reverts commit b4bf8ec250.
2020-11-16 20:56:18 +02:00
pinpin
b4bf8ec250 remove workwlows temporary 2020-11-16 20:37:51 +02:00
pinpin
780657ce1d remove workflows for now 2020-11-16 20:35:24 +02:00
pinpin
2d558563e4 Add Hide Tab Index and Hide Tab Close Button 2020-11-16 20:27:39 +02:00
Eugene
bc5e6e9535 Merge pull request #3098 from Eugeny/all-contributors/add-matishadow 2020-10-23 09:04:39 +02:00
allcontributors[bot]
0c15fc2657 docs: update .all-contributorsrc [skip ci] 2020-10-23 07:03:53 +00:00
allcontributors[bot]
5e115c63f1 docs: update README.md [skip ci] 2020-10-23 07:03:52 +00:00
Eugene
2bcf23cff1 Merge pull request #3055 from matishadow/feature/regex-search-configuration 2020-10-23 09:03:35 +02:00
matishadow
2c59022b78 Fix lint 2020-10-23 07:53:43 +02:00
matishadow
358d9f30d2 Make search options be remembered 2020-10-22 23:35:23 +02:00
matishadow
afd6ce4346 Remove RegexAlwaysEnabled from settings component 2020-10-22 19:48:28 +02:00
TakuroOnoda
5c7256ffe5 Adding Tab Location "left" 2020-10-18 18:48:10 +09:00
Eugene Pankov
a15e79ad5a PEM related patches (potentially fixes #2053) 2020-10-16 15:53:41 +02:00
Eugene
f1ecbd1a93 handle windows usernames with spaces - fixed #2944 2020-10-16 12:47:03 +02:00
Eugene
7da941d038 Merge pull request #3073 from Eugeny/all-contributors/add-zend 2020-10-14 13:10:22 +02:00
allcontributors[bot]
3efc142630 docs: update .all-contributorsrc [skip ci] 2020-10-14 11:09:21 +00:00
allcontributors[bot]
d592469237 docs: update README.md [skip ci] 2020-10-14 11:09:20 +00:00
Eugene
b3e63620b3 Merge pull request #3072 from zend/master 2020-10-14 13:09:19 +02:00
Zenghai Liang
22b79510ea lint: add the parameter type 2020-10-14 17:31:45 +08:00
Zenghai Liang
70cf63f8fa lint: using a template literal 2020-10-14 17:17:07 +08:00
Zenghai Liang
c9067cf8b8 Fix the linting issue 2020-10-14 16:57:09 +08:00
Zenghai Liang
4ccc406768 Using Object.assign to copy connection 2020-10-14 16:40:14 +08:00
Zenghai Liang
1c25747de0 feat: Add copy button to ssh connection 2020-10-14 15:43:12 +08:00
matishadow
8e4c36ec24 Fix lint problems 2020-10-08 19:53:13 +02:00
matishadow
444d92d393 Add possibility to configure always enabled regex 2020-10-08 19:30:57 +02:00
dependabot[bot]
2597702676 Bump electron from 8.2.5 to 8.5.2
Bumps [electron](https://github.com/electron/electron) from 8.2.5 to 8.5.2.
- [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.5...v8.5.2)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-06 17:56:11 +00:00
Eugene
c9d75d81e4 Merge pull request #2965 from Eugeny/dependabot/npm_and_yarn/app/bl-3.0.1
Bump bl from 3.0.0 to 3.0.1 in /app
2020-09-02 17:57:12 +02:00
dependabot[bot]
98eb68c845 Bump bl from 3.0.0 to 3.0.1 in /app
Bumps [bl](https://github.com/rvagg/bl) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/rvagg/bl/releases)
- [Commits](https://github.com/rvagg/bl/compare/v3.0.0...v3.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-02 15:55:20 +00:00
Eugene
5185e1fe1d Update ssh.service.ts 2020-08-27 23:03:54 +02:00
Eugene Pankov
5bde116a4e Merge branch 'master' of github.com:Eugeny/terminus 2020-08-26 10:54:52 +02:00
Eugene Pankov
179acc1382 only use pageant as agent if it's runing - fixes #2935, fixes #2936 2020-08-26 10:54:49 +02:00
Eugene Pankov
c6d918e401 build fix 2020-08-23 16:02:56 +02:00
Eugene Pankov
62b53575ac WinSCP integration 2020-08-23 14:59:06 +02:00
Eugene Pankov
32b29a91e9 fixed random conpty freezes - fixes #2805, fixes #1583, fixes #2686, fixes #2293 2020-08-23 14:06:49 +02:00
Eugene Pankov
4346030459 lint 2020-08-16 18:52:45 +02:00
Eugene Pankov
9e8c0ccb14 restore all split tab children at once 2020-08-16 18:30:42 +02:00
Eugene Pankov
6c8d00eb16 don't mention legacy API in README 2020-08-16 18:24:55 +02:00
Eugene Pankov
b3fcfd0c8b added hotkey to focus all panes (fixes #722) 2020-08-16 18:24:47 +02:00
Eugene Pankov
4eefab5655 made warning when closing SSH tabs optional - fixes #2801 2020-08-15 21:07:35 +02:00
Eugene Pankov
2745896ec3 lint 2020-08-15 20:49:18 +02:00
Eugene Pankov
cdfaaabb70 bumped native deps 2020-08-15 20:46:50 +02:00
Eugene Pankov
60ab6ece62 fixed tab context menu for custom tab colors 2020-08-15 20:46:40 +02:00
Eugene Pankov
436318b534 Merge branch 'master' of github.com:Eugeny/terminus 2020-08-15 20:46:21 +02:00
Eugene
248f431437 Merge pull request #2648 from Eugeny/dependabot/npm_and_yarn/node-abi-2.18.0
Bump node-abi from 2.16.0 to 2.18.0
2020-08-15 20:45:56 +02:00
Eugene
7794280115 Merge pull request #2879 from Eugeny/dependabot/npm_and_yarn/typedoc-0.18.0
Bump typedoc from 0.17.7 to 0.18.0
2020-08-15 20:45:32 +02:00
Eugene Pankov
c2cc4c977f Update shellSettingsTab.component.pug 2020-08-15 19:21:12 +02:00
Eugene Pankov
f9b7f97863 handle cwd detection errors on linux 2020-08-14 12:39:14 +02:00
Eugene Pankov
59ce7eeee6 prioritize pubkey auth over password (fixes #2894) 2020-08-13 15:05:05 +02:00
Eugene Pankov
0e012a90ea Update xtermFrontend.ts 2020-08-12 21:04:42 +02:00
Eugene Pankov
6773d260cf Merge branch 'master' of github.com:Eugeny/terminus 2020-08-12 21:02:29 +02:00
Eugene
7379f6cd59 Merge pull request #2859 from 695137400/patch-1
Update xtermFrontend.ts
2020-08-12 21:02:25 +02:00
Jonathan Beverley
3aee24bdbd Re-added an option for Agent Forwarding 2020-08-12 21:00:55 +02:00
dependabot-preview[bot]
84dbfa5d6c Bump typedoc from 0.17.7 to 0.18.0
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.17.7 to 0.18.0.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.17.7...v0.18.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-10 04:19:24 +00:00
Eugene Pankov
43958d88b8 Merge branch 'master' of github.com:Eugeny/terminus 2020-08-07 12:25:05 +02:00
Eugene Pankov
f4b0e4cb52 Update package.json 2020-08-07 12:25:02 +02:00
Eugene
d91c898f6d Merge pull request #2830 from Eugeny/dependabot/npm_and_yarn/app/yargs-15.4.1
Bump yargs from 15.3.1 to 15.4.1 in /app
2020-08-07 09:22:38 +02:00
Eugene
f16989a45d Merge pull request #2724 from Eugeny/dependabot/npm_and_yarn/electron-notarize-1.0.0
Bump electron-notarize from 0.1.1 to 1.0.0
2020-08-07 09:20:54 +02:00
Eugene
1ef524e832 Merge pull request #2852 from Eugeny/dependabot/npm_and_yarn/eslint-7.6.0
Bump eslint from 7.2.0 to 7.6.0
2020-08-07 09:19:33 +02:00
Eugene
65fcdd2745 Merge pull request #2856 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-3.8.0
Bump @typescript-eslint/parser from 3.3.0 to 3.8.0
2020-08-07 09:18:56 +02:00
695137400
7030f562e8 Update xtermFrontend.ts
console error
2020-08-04 18:21:26 +08:00
dependabot-preview[bot]
047b31dd67 Bump @typescript-eslint/parser from 3.3.0 to 3.8.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 3.3.0 to 3.8.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/v3.8.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-04 04:24:06 +00:00
Eugene Pankov
ae0d33f026 use update.electronjs.org for updates (fixes #2393, fixes #2087, fixes #2835, fixes #2436, fixes #2635, fixes #1495, fixes #2158) 2020-08-03 23:14:05 +02:00
dependabot-preview[bot]
039a0b7eb5 Bump eslint from 7.2.0 to 7.6.0
Bumps [eslint](https://github.com/eslint/eslint) from 7.2.0 to 7.6.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.2.0...v7.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-03 04:25:33 +00:00
Eugene Pankov
3d3fcc41b8 lint 2020-07-29 19:27:23 +02:00
Eugene Pankov
3e3e8f3132 added fontawesome regular style 2020-07-29 19:19:05 +02:00
Eugene Pankov
da21895e40 more explicit SSH auth options and agent forwarding - fixes #2284, fixes #2511, fixes #2717, fixes #2184 2020-07-29 19:18:57 +02:00
Eugene Pankov
34752ed69e Merge branch 'master' of https://github.com/Eugeny/terminus 2020-07-29 18:50:16 +02:00
Eugene
008eb98f50 Merge pull request #2767 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/types/ssh2-0.5.44 2020-07-29 18:50:10 +02:00
Eugene
e521cd4648 Merge pull request #2844 from Eugeny/all-contributors/add-JonathanBeverley 2020-07-29 18:31:10 +02:00
Eugene Pankov
cb97a784da support windows openssh agent 2020-07-29 18:11:10 +02:00
allcontributors[bot]
96d9d81be2 docs: update .all-contributorsrc [skip ci] 2020-07-29 15:45:53 +00:00
allcontributors[bot]
71797eb93f docs: update README.md [skip ci] 2020-07-29 15:45:52 +00:00
Eugene
ae3870e297 Merge pull request #2601 from JonathanBeverley/jmb/features 2020-07-29 17:45:05 +02:00
Eugene Pankov
055de5013c updated uac.exe 2020-07-29 09:50:08 +02:00
dependabot-preview[bot]
ad1ea01976 Bump yargs from 15.3.1 to 15.4.1 in /app
Bumps [yargs](https://github.com/yargs/yargs) from 15.3.1 to 15.4.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.3.1...v15.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-28 04:20:35 +00:00
Eugene
064fbfac67 Merge pull request #2736 from Eugeny/dependabot/npm_and_yarn/terminus-core/winston-3.3.3 2020-07-27 22:33:53 +02:00
Eugene
a31c83476d Merge pull request #2759 from Eugeny/dependabot/npm_and_yarn/app/rxjs-compat-6.6.0 2020-07-27 22:33:21 +02:00
Eugene
bc9f4c267e Merge pull request #2723 from Eugeny/dependabot/npm_and_yarn/webpack-cli-3.3.12
Bump webpack-cli from 3.3.10 to 3.3.12
2020-07-27 22:33:03 +02:00
Eugene
3e92ae278e Merge pull request #2823 from Eugeny/dependabot/npm_and_yarn/sentry/electron-1.5.1
Bump @sentry/electron from 1.2.1 to 1.5.1
2020-07-27 22:22:31 +02:00
Eugene
6adc3543a8 Merge pull request #2826 from Eugeny/all-contributors/add-dimitory 2020-07-27 22:21:01 +02:00
allcontributors[bot]
af5293948c docs: update .all-contributorsrc [skip ci] 2020-07-27 20:15:14 +00:00
allcontributors[bot]
34620db925 docs: update README.md [skip ci] 2020-07-27 20:15:13 +00:00
Eugene
4a5a96ea16 Merge pull request #2824 from Dimitory/patch-1 2020-07-27 22:15:09 +02:00
Dmitry Pronin
fcc9d7cf7d Update ssh.service.ts 2020-07-27 19:26:02 +03:00
Dmitry Pronin
9cae50bfc5 Fixed SSH Keys Permission Denied 2020-07-27 19:19:21 +03:00
Eugene Pankov
3cff5909bd rebuild uac.exe in release mode (fixes #2800) 2020-07-27 17:38:26 +02:00
Eugene Pankov
0130cd9d54 handle global hotkeys with win key - fixes #2524 2020-07-27 16:36:11 +02:00
Eugene Pankov
926d4f51b3 use more performant sourcemap mode - fixes #2617 2020-07-27 16:12:16 +02:00
Eugene Pankov
efe390f68d allow searching for hotkey values - #1509 2020-07-27 16:04:31 +02:00
Eugene Pankov
6d0b2608a2 added an option to disable the global hotkey to the welcome tab (fixes #1509, fixes #2809) 2020-07-27 15:56:09 +02:00
Eugene Pankov
ddd306dbf6 bumped xterm 2020-07-27 15:55:24 +02:00
Eugene Pankov
30c632a5cc Merge branch 'master' of github.com:Eugeny/terminus 2020-07-27 15:39:27 +02:00
Eugene
65b3254b77 Merge pull request #2699 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-webgl-0.8.0
Bump xterm-addon-webgl from 0.7.0 to 0.8.0 in /terminus-terminal
2020-07-27 15:38:31 +02:00
Eugene
f776a30c9f Merge pull request #2787 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-ligatures-0.4.0-beta.5
Bump xterm-addon-ligatures from 0.3.0 to 0.4.0-beta.5 in /terminus-terminal
2020-07-27 15:38:20 +02:00
dependabot-preview[bot]
c02525440c Bump @sentry/electron from 1.2.1 to 1.5.1
Bumps [@sentry/electron](https://github.com/getsentry/sentry-electron) from 1.2.1 to 1.5.1.
- [Release notes](https://github.com/getsentry/sentry-electron/releases)
- [Changelog](https://github.com/getsentry/sentry-electron/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-electron/compare/v1.2.1...v1.5.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 04:22:58 +00:00
Eugene Pankov
dbda8dad34 lint 2020-07-17 20:45:18 +02:00
dependabot-preview[bot]
bc44f55989 Bump xterm-addon-ligatures in /terminus-terminal
Bumps [xterm-addon-ligatures](https://github.com/xtermjs/xterm.js) from 0.3.0 to 0.4.0-beta.5.
- [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-07-14 04:20:15 +00:00
dependabot-preview[bot]
a3c998adab Bump @types/ssh2 from 0.5.43 to 0.5.44 in /terminus-ssh
Bumps [@types/ssh2](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ssh2) from 0.5.43 to 0.5.44.
- [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-07-07 04:20:14 +00:00
dependabot-preview[bot]
b62b59f9b8 Bump winston from 3.2.1 to 3.3.3 in /terminus-core
Bumps [winston](https://github.com/winstonjs/winston) from 3.2.1 to 3.3.3.
- [Release notes](https://github.com/winstonjs/winston/releases)
- [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md)
- [Commits](https://github.com/winstonjs/winston/compare/3.2.1...v3.3.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-05 10:54:28 +00:00
Eugene Pankov
bb1557b0a4 avoid ResizeObserver feedback loop 2020-07-05 12:47:40 +02:00
Eugene Pankov
d0fe64355b ssh reconnection logic improvements - fixes #2705, fixes #761, fixes #2662 2020-07-05 12:47:32 +02:00
Eugene Pankov
7b4e6e8f3a build fix 2020-07-05 12:19:08 +02:00
dependabot-preview[bot]
bd11c90846 Bump rxjs-compat from 6.5.5 to 6.6.0 in /app
Bumps rxjs-compat from 6.5.5 to 6.6.0.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-02 04:22:04 +00:00
Eugene Pankov
21f33618d4 stop ssh session after connection errors 2020-06-30 15:35:07 +02:00
Eugene Pankov
11c8ca6582 don't crash on missing wsl distro flags - fixes #2744 2020-06-30 15:34:55 +02:00
Eugene Pankov
6e9ac1b59a added entitlements and usage descriptions - fixed #2746 2020-06-28 15:11:52 +02:00
dependabot-preview[bot]
91591a81ff Bump electron-notarize from 0.1.1 to 1.0.0
Bumps [electron-notarize](https://github.com/electron/electron-notarize) from 0.1.1 to 1.0.0.
- [Release notes](https://github.com/electron/electron-notarize/releases)
- [Changelog](https://github.com/electron/electron-notarize/blob/master/.releaserc.json)
- [Commits](https://github.com/electron/electron-notarize/compare/v0.1.1...v1.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-22 04:19:42 +00:00
dependabot-preview[bot]
1ce0ff2e00 Bump webpack-cli from 3.3.10 to 3.3.12
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 3.3.10 to 3.3.12.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/v3.3.12/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/v3.3.10...v3.3.12)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-22 04:19:12 +00:00
Eugene
92cef766f6 Merge pull request #2682 from Eugeny/dependabot/npm_and_yarn/eslint-7.2.0
Bump eslint from 7.1.0 to 7.2.0
2020-06-19 20:00:36 +02:00
Eugene
d1d55d39b1 Merge pull request #2716 from Eugeny/dependabot/npm_and_yarn/app/angular/forms-9.1.11
Bump @angular/forms from 9.1.9 to 9.1.11 in /app
2020-06-19 20:00:24 +02:00
Eugene
4ad55bff6e Merge pull request #2714 from Eugeny/dependabot/npm_and_yarn/webpack-5.0.0-beta.18
Bump webpack from 5.0.0-beta.16 to 5.0.0-beta.18
2020-06-19 20:00:13 +02:00
Eugene
f73c41a709 Merge pull request #2710 from Eugeny/dependabot/npm_and_yarn/app/angular/common-9.1.11
Bump @angular/common from 9.1.9 to 9.1.11 in /app
2020-06-19 19:59:45 +02:00
Eugene
3ca55d972a Merge pull request #2707 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-3.3.0
Bump @typescript-eslint/parser from 3.1.0 to 3.3.0
2020-06-19 19:59:05 +02:00
dependabot-preview[bot]
2b25c25337 Bump @angular/forms from 9.1.9 to 9.1.11 in /app
Bumps [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) from 9.1.9 to 9.1.11.
- [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.11/packages/forms)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-19 04:17:10 +00:00
dependabot-preview[bot]
3621877f32 Bump webpack from 5.0.0-beta.16 to 5.0.0-beta.18
Bumps [webpack](https://github.com/webpack/webpack) from 5.0.0-beta.16 to 5.0.0-beta.18.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.0.0-beta.16...v5.0.0-beta.18)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-18 04:20:19 +00:00
dependabot-preview[bot]
cf2a8ddc96 Bump @angular/common from 9.1.9 to 9.1.11 in /app
Bumps [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) from 9.1.9 to 9.1.11.
- [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.11/packages/common)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-17 04:19:49 +00:00
dependabot-preview[bot]
d461515881 Bump @typescript-eslint/parser from 3.1.0 to 3.3.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 3.1.0 to 3.3.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/v3.3.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-16 04:21:28 +00:00
Eugene Pankov
5828571a95 fixed uac.exe encoding (fixes #654) 2020-06-14 18:46:22 +02:00
Eugene Pankov
3aba7c9b93 lint 2020-06-14 17:26:57 +02:00
Eugene Pankov
d371bf2f41 fixed arrow keys in admin shells (fixes #691) 2020-06-14 17:25:32 +02:00
Eugene Pankov
51934dccbd use glasstron on win32 2020-06-14 16:16:00 +02:00
Eugene Pankov
b6caf47ce6 Update theme.scss 2020-06-14 16:13:01 +02:00
dependabot-preview[bot]
e8362268bb Bump xterm-addon-webgl from 0.7.0 to 0.8.0 in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.7...0.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-12 04:17:36 +00:00
dependabot-preview[bot]
88c57a6794 Bump eslint from 7.1.0 to 7.2.0
Bumps [eslint](https://github.com/eslint/eslint) from 7.1.0 to 7.2.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.1.0...v7.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-09 04:18:03 +00:00
Eugene Pankov
69a0b46a20 auto-trim single-line clipboard contents (fixes #2677) 2020-06-08 10:04:29 +02:00
dependabot-preview[bot]
a5a662c05d Bump node-abi from 2.16.0 to 2.18.0
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.16.0 to 2.18.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.16.0...v2.18.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-08 07:15:31 +00:00
Eugene
4ab0b51d87 Merge pull request #2647 from Eugeny/dependabot/npm_and_yarn/app/node-abi-2.18.0
Bump node-abi from 2.16.0 to 2.18.0 in /app
2020-06-08 09:13:38 +02:00
dependabot-preview[bot]
c3285b24d9 Bump node-abi from 2.16.0 to 2.18.0 in /app
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.16.0 to 2.18.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.16.0...v2.18.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-08 07:13:06 +00:00
Eugene
313345da3d Merge pull request #2666 from Eugeny/dependabot/npm_and_yarn/node-gyp-7.0.0
Bump node-gyp from 6.1.0 to 7.0.0
2020-06-08 09:12:12 +02:00
Eugene
7173be8c22 Merge pull request #2628 from Eugeny/dependabot/npm_and_yarn/app/keytar-6.0.1
Bump keytar from 5.6.0 to 6.0.1 in /app
2020-06-08 09:11:27 +02:00
Eugene
b97ef8c643 Merge pull request #2678 from Eugeny/dependabot/npm_and_yarn/eslint-plugin-import-2.21.1
Bump eslint-plugin-import from 2.20.2 to 2.21.1
2020-06-08 09:11:12 +02:00
Eugene Pankov
d221f8e561 properly clear jump host from settings (fixes #2675) 2020-06-08 09:11:00 +02:00
dependabot-preview[bot]
95ed0a58b9 Bump eslint-plugin-import from 2.20.2 to 2.21.1
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.20.2 to 2.21.1.
- [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.2...v2.21.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-08 04:18:27 +00:00
dependabot-preview[bot]
77d4176b55 Bump keytar from 5.6.0 to 6.0.1 in /app
Bumps [keytar](https://github.com/atom/node-keytar) from 5.6.0 to 6.0.1.
- [Release notes](https://github.com/atom/node-keytar/releases)
- [Commits](https://github.com/atom/node-keytar/compare/v5.6.0...v6.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-05 08:32:24 +00:00
Eugene Pankov
48013e2102 moved glasstron outside of webpack realm 2020-06-05 10:08:20 +02:00
dependabot-preview[bot]
31dcb2b514 Bump node-gyp from 6.1.0 to 7.0.0
Bumps [node-gyp](https://github.com/nodejs/node-gyp) from 6.1.0 to 7.0.0.
- [Release notes](https://github.com/nodejs/node-gyp/releases)
- [Changelog](https://github.com/nodejs/node-gyp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodejs/node-gyp/compare/v6.1.0...v7.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-05 04:21:13 +00:00
Eugene
43a9a7cb19 Merge pull request #2629 from Eugeny/dependabot/npm_and_yarn/app/serialport-9.0.0
Bump serialport from 8.0.7 to 9.0.0 in /app
2020-06-04 13:52:00 +02:00
Eugene
88cecba2b6 Merge pull request #2619 from Eugeny/dependabot/npm_and_yarn/eslint-7.1.0
Bump eslint from 6.8.0 to 7.1.0
2020-06-04 13:51:37 +02:00
Eugene
91e1870f91 Merge pull request #2631 from Eugeny/dependabot/npm_and_yarn/typedoc-0.17.7
Bump typedoc from 0.17.6 to 0.17.7
2020-06-04 13:51:11 +02:00
Eugene
705050a96a Merge pull request #2655 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-3.1.0
Bump @typescript-eslint/parser from 2.34.0 to 3.1.0
2020-06-04 13:49:53 +02:00
Eugene
8d2550fb99 Merge pull request #2660 from Eugeny/all-contributors/add-3l0w 2020-06-04 13:49:14 +02:00
dependabot-preview[bot]
c4a89d4ee3 Bump eslint from 6.8.0 to 7.1.0
Bumps [eslint](https://github.com/eslint/eslint) from 6.8.0 to 7.1.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.8.0...v7.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-04 11:43:04 +00:00
allcontributors[bot]
6140cdfabc docs: update .all-contributorsrc [skip ci] 2020-06-04 11:41:01 +00:00
allcontributors[bot]
5786d61620 docs: update README.md [skip ci] 2020-06-04 11:41:00 +00:00
Eugene
32f6e16275 Merge pull request #2657 from 3l0w/master 2020-06-04 13:40:58 +02:00
Gwilherm Folliot
668986fc08 fixed lint 2020-06-04 13:34:33 +02:00
Gwilherm Folliot
9190893ccf Added acrylic background for linux 2020-06-03 18:41:23 +02:00
dependabot-preview[bot]
546837ab55 Bump @typescript-eslint/parser from 2.34.0 to 3.1.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.34.0 to 3.1.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/v3.1.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-03 04:20:59 +00:00
dependabot-preview[bot]
3825feae08 Bump typedoc from 0.17.6 to 0.17.7
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.17.6 to 0.17.7.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/0.17.6...v0.17.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-27 04:21:13 +00:00
dependabot-preview[bot]
fdeabae061 Bump serialport from 8.0.7 to 9.0.0 in /app
Bumps [serialport](https://github.com/serialport/node-serialport) from 8.0.7 to 9.0.0.
- [Release notes](https://github.com/serialport/node-serialport/releases)
- [Changelog](https://github.com/serialport/node-serialport/blob/master/CHANGELOG.md)
- [Commits](https://github.com/serialport/node-serialport/compare/@serialport/bindings@8.0.7...@serialport/bindings@9.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-27 04:19:14 +00:00
Eugene Pankov
8b307be92d Merge branch 'master' of github.com:Eugeny/terminus 2020-05-26 18:52:26 +02:00
Eugene
45516c4013 Merge pull request #2622 from Eugeny/dependabot/npm_and_yarn/app/js-yaml-3.14.0 2020-05-26 17:32:06 +02:00
Eugene
5d8f7a4e34 Merge pull request #2623 from Eugeny/dependabot/npm_and_yarn/terminus-core/js-yaml-3.14.0 2020-05-26 17:31:47 +02:00
Eugene
792c9279e2 Merge pull request #2592 from Eugeny/dependabot/npm_and_yarn/terminus-core/types/js-yaml-3.12.4 2020-05-26 17:31:34 +02:00
Eugene
8825a8163e Merge pull request #2591 from Eugeny/dependabot/npm_and_yarn/types/js-yaml-3.12.4 2020-05-26 17:31:28 +02:00
Eugene Pankov
7e42328c6f bumped node-pty 2020-05-26 17:31:09 +02:00
Eugene
2dd99d43ed Merge pull request #2597 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-2.34.0 2020-05-26 17:31:04 +02:00
Eugene Pankov
991b4fc965 Merge branch 'master' of github.com:Eugeny/terminus 2020-05-26 17:30:42 +02:00
Eugene
e9d7af5320 Merge pull request #2552 from Eugeny/dependabot/npm_and_yarn/app/serialport-9.0.0 2020-05-26 17:29:30 +02:00
Eugene
bff23fe825 Merge pull request #2573 from Eugeny/dependabot/npm_and_yarn/tslib-2.0.0 2020-05-26 17:29:10 +02:00
Eugene
79bd94ee6f Merge pull request #2604 from Eugeny/dependabot/npm_and_yarn/typescript-3.9.3 2020-05-26 17:28:57 +02:00
Eugene
fdd833ef7c Merge pull request #2603 from Eugeny/dependabot/npm_and_yarn/app/node-abi-2.17.0 2020-05-26 17:28:47 +02:00
Eugene Pankov
c386504296 fixed #2624 - fixed analytics initialization 2020-05-26 17:28:02 +02:00
Eugene
9cc8649422 Merge pull request #2610 from Eugeny/dependabot/npm_and_yarn/terminus-core/uuid-8.1.0 2020-05-26 17:27:00 +02:00
Eugene Pankov
625a9179c5 dropped uuid dependency 2020-05-26 17:26:39 +02:00
Eugene Pankov
66ed73f7c9 bumped angular 2020-05-26 17:19:45 +02:00
Eugene Pankov
95bd48d6c6 warn when closing ssh tabs - fixes #2512 2020-05-26 17:12:48 +02:00
Eugene Pankov
328490a85e move "close" menu items to the bottom - fixes #2599 2020-05-26 17:10:02 +02:00
Eugene Pankov
d08413aeab fixed focus loss on new windows 2020-05-26 17:04:39 +02:00
Eugene Pankov
922f1fbade fixed #1870 - new window hotkey on mac 2020-05-26 17:04:10 +02:00
Eugene
cb96c8d470 Merge pull request #2578 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-unicode11-0.2.0
Bump xterm-addon-unicode11 from 0.2.0-beta.5 to 0.2.0 in /terminus-terminal
2020-05-26 16:53:19 +02:00
Eugene
f3ebc43667 Merge pull request #2572 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-webgl-0.7.0 2020-05-26 16:53:06 +02:00
dependabot-preview[bot]
e7696dcdf3 Bump js-yaml from 3.13.1 to 3.14.0 in /app
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.13.1 to 3.14.0.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.13.1...3.14.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-26 14:52:51 +00:00
Eugene
4abf7d7738 Merge pull request #2574 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-4.6.0 2020-05-26 16:52:46 +02:00
dependabot-preview[bot]
be206161d6 Bump uuid from 8.0.0 to 8.1.0 in /terminus-core
Bumps [uuid](https://github.com/uuidjs/uuid) from 8.0.0 to 8.1.0.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v8.0.0...v8.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-26 14:52:11 +00:00
dependabot-preview[bot]
dcd17f886e Bump xterm-addon-unicode11 in /terminus-terminal
Bumps [xterm-addon-unicode11](https://github.com/xtermjs/xterm.js) from 0.2.0-beta.5 to 0.2.0.
- [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-05-26 14:52:08 +00:00
dependabot-preview[bot]
2c94dea941 Bump xterm from 4.6.0-beta.41 to 4.6.0 in /terminus-terminal
Bumps [xterm](https://github.com/xtermjs/xterm.js) from 4.6.0-beta.41 to 4.6.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/4.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-26 14:51:57 +00:00
dependabot-preview[bot]
7a2291f7db Bump js-yaml from 3.13.1 to 3.14.0 in /terminus-core
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.13.1 to 3.14.0.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.13.1...3.14.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-26 14:51:15 +00:00
Eugene
af0d9142ed Merge pull request #2579 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-serialize-0.3.0 2020-05-26 16:50:59 +02:00
Eugene
6ba7d5b78f Merge pull request #2577 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-search-0.7.0 2020-05-26 16:50:45 +02:00
Eugene
bbf035d5fd Merge pull request #2576 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-ligatures-0.3.0
Bump xterm-addon-ligatures from 0.3.0-beta.1 to 0.3.0 in /terminus-terminal
2020-05-26 16:50:25 +02:00
Eugene
84bc4369cb Merge pull request #2575 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-fit-0.4.0 2020-05-26 16:50:15 +02:00
Eugene
e01f77998c Merge pull request #2595 from Eugeny/dependabot/npm_and_yarn/electron-builder-22.6.1 2020-05-26 16:49:30 +02:00
Eugene Pankov
08acd4df46 depend on gnome-keyring (fixes #2203, fixes #2568) 2020-05-22 11:30:05 +02:00
dependabot-preview[bot]
2c9d968aa8 Bump typescript from 3.8.3 to 3.9.3
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.8.3 to 3.9.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.8.3...v3.9.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-20 04:24:04 +00:00
dependabot-preview[bot]
19a3996861 Bump node-abi from 2.16.0 to 2.17.0 in /app
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.16.0 to 2.17.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.16.0...v2.17.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-20 04:22:02 +00:00
Jonathan Beverley
6d187e8117 Add an option for Agent Forwarding
I don't understand why this is on by default, let alone not
configurable. Agent forwarding is a significant security concern, and
buggy agent forwarding is the cause of a couple existing bugs.
2020-05-19 12:09:07 -04:00
Jonathan Beverley
a7687a6fc2 Include pagent.exe in installer, Remove check for pageant (fixed Eugeny#350) 2020-05-19 12:08:55 -04:00
dependabot-preview[bot]
7cbec63039 Bump @typescript-eslint/parser from 2.31.0 to 2.34.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.31.0 to 2.34.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.34.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-19 04:23:17 +00:00
dependabot-preview[bot]
91320f1cd7 Bump electron-builder from 22.5.1 to 22.6.1
Bumps [electron-builder](https://github.com/electron-userland/electron-builder) from 22.5.1 to 22.6.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/compare/v22.5.1...v22.6.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-19 04:22:40 +00:00
dependabot-preview[bot]
5518ce5e0c Bump @types/js-yaml from 3.12.3 to 3.12.4 in /terminus-core
Bumps [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) from 3.12.3 to 3.12.4.
- [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-05-18 04:30:04 +00:00
dependabot-preview[bot]
d59c52d7a5 Bump @types/js-yaml from 3.12.3 to 3.12.4
Bumps [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) from 3.12.3 to 3.12.4.
- [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-05-18 04:22:03 +00:00
dependabot-preview[bot]
dd3a4cb289 Bump xterm-addon-serialize in /terminus-terminal
Bumps xterm-addon-serialize from 0.3.0-beta.4 to 0.3.0.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 04:25:51 +00:00
dependabot-preview[bot]
fc6ded4b1a Bump xterm-addon-search from 0.7.0-beta.2 to 0.7.0 in /terminus-terminal
Bumps [xterm-addon-search](https://github.com/xtermjs/xterm.js) from 0.7.0-beta.2 to 0.7.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 04:25:00 +00:00
dependabot-preview[bot]
d4f61b3846 Bump xterm-addon-ligatures in /terminus-terminal
Bumps [xterm-addon-ligatures](https://github.com/xtermjs/xterm.js) from 0.3.0-beta.1 to 0.3.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.3)

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

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 04:24:10 +00:00
dependabot-preview[bot]
499f541328 Bump tslib from 1.11.1 to 2.0.0
Bumps [tslib](https://github.com/Microsoft/tslib) from 1.11.1 to 2.0.0.
- [Release notes](https://github.com/Microsoft/tslib/releases)
- [Commits](https://github.com/Microsoft/tslib/compare/1.11.1...2.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 04:23:36 +00:00
dependabot-preview[bot]
7c893a3c4b Bump xterm-addon-webgl from 0.7.0-beta.10 to 0.7.0 in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.7.0-beta.10 to 0.7.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 04:23:24 +00:00
dependabot-preview[bot]
1f5c55826b Bump serialport from 8.0.7 to 9.0.0 in /app
Bumps [serialport](https://github.com/serialport/node-serialport) from 8.0.7 to 9.0.0.
- [Release notes](https://github.com/serialport/node-serialport/releases)
- [Changelog](https://github.com/serialport/node-serialport/blob/master/CHANGELOG.md)
- [Commits](https://github.com/serialport/node-serialport/compare/@serialport/bindings@8.0.7...@serialport/bindings@9.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-11 04:22:52 +00:00
Eugene Pankov
197824004e notarize pkg 2020-05-07 17:37:39 +02:00
Eugene Pankov
ee1d465bf6 Revert "separate mac builds"
This reverts commit 90cc06c3fd.
2020-05-07 13:00:42 +02:00
Eugene Pankov
12bb070def Revert "separate pkg/zip builds for macos"
This reverts commit 8cf0445b6d.
2020-05-07 12:59:26 +02:00
123 changed files with 7090 additions and 7381 deletions

View File

@@ -271,6 +271,69 @@
"contributions": [ "contributions": [
"code" "code"
] ]
},
{
"login": "3l0w",
"name": "Gwilherm Folliot",
"avatar_url": "https://avatars2.githubusercontent.com/u/37798980?v=4",
"profile": "https://github.com/3l0w",
"contributions": [
"code"
]
},
{
"login": "dimitory",
"name": "Dmitry Pronin",
"avatar_url": "https://avatars0.githubusercontent.com/u/475955?v=4",
"profile": "https://github.com/Dimitory",
"contributions": [
"code"
]
},
{
"login": "JonathanBeverley",
"name": "Jonathan Beverley",
"avatar_url": "https://avatars1.githubusercontent.com/u/20328966?v=4",
"profile": "https://github.com/JonathanBeverley",
"contributions": [
"code"
]
},
{
"login": "zend",
"name": "Zenghai Liang",
"avatar_url": "https://avatars1.githubusercontent.com/u/25160?v=4",
"profile": "https://github.com/zend",
"contributions": [
"code"
]
},
{
"login": "matishadow",
"name": "Mateusz Tracz",
"avatar_url": "https://avatars0.githubusercontent.com/u/9083085?v=4",
"profile": "https://about.me/matishadow",
"contributions": [
"code"
]
},
{
"login": "pinpins",
"name": "pinpin",
"avatar_url": "https://avatars3.githubusercontent.com/u/36234677?v=4",
"profile": "https://zergpool.com",
"contributions": [
"code"
]
},
{
"login": "TakuroOnoda",
"name": "Takuro Onoda",
"avatar_url": "https://avatars0.githubusercontent.com/u/1407926?v=4",
"profile": "https://github.com/TakuroOnoda",
"contributions": [
"code"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -37,6 +37,7 @@ rules:
'@typescript-eslint/strict-boolean-expressions': off '@typescript-eslint/strict-boolean-expressions': off
'@typescript-eslint/no-misused-promises': off '@typescript-eslint/no-misused-promises': off
'@typescript-eslint/typedef': off '@typescript-eslint/typedef': off
'@typescript-eslint/consistent-type-imports': off
'@typescript-eslint/no-use-before-define': '@typescript-eslint/no-use-before-define':
- error - error
- classes: false - classes: false
@@ -53,7 +54,8 @@ rules:
computed-property-spacing: computed-property-spacing:
- error - error
- never - never
comma-dangle: comma-dangle: off
'@typescript-eslint/comma-dangle':
- error - error
- always-multiline - always-multiline
curly: error curly: error
@@ -104,3 +106,14 @@ rules:
'@typescript-eslint/no-unsafe-call': off '@typescript-eslint/no-unsafe-call': off
'@typescript-eslint/no-unsafe-return': off '@typescript-eslint/no-unsafe-return': off
'@typescript-eslint/no-base-to-string': off # broken in typescript-eslint '@typescript-eslint/no-base-to-string': off # broken in typescript-eslint
'@typescript-eslint/no-unsafe-assignment': off
'@typescript-eslint/naming-convention': off
'@typescript-eslint/lines-between-class-members':
- error
- exceptAfterSingleLine: true
'@typescript-eslint/dot-notation': off
'@typescript-eslint/no-confusing-void-expression': off
'@typescript-eslint/no-implicit-any-catch': off
'@typescript-eslint/member-ordering': off
'@typescript-eslint/no-var-requires': off
'@typescript-eslint/no-shadow': off

View File

@@ -11,7 +11,7 @@ jobs:
- name: Installing Node - name: Installing Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 10 node-version: 15
- name: Install deps - name: Install deps
run: | run: |
@@ -22,5 +22,8 @@ jobs:
rm app/node_modules/.yarn-integrity rm app/node_modules/.yarn-integrity
yarn yarn
- name: Build typings
run: yarn run build:typings
- name: Lint - name: Lint
run: yarn run lint run: yarn run lint

View File

@@ -11,7 +11,7 @@ jobs:
- name: Install Node - name: Install Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 10 node-version: 15
- name: Install deps - name: Install deps
run: | run: |

View File

@@ -1,64 +0,0 @@
name: macOS Build (ZIP)
on: [push, pull_request]
jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Installing Node
uses: actions/setup-node@v1
with:
node-version: 10
- name: Install deps
run: |
sudo npm i -g yarn@1.19.1
cd app
yarn
cd ..
rm app/node_modules/.yarn-integrity
yarn
- name: Build native deps
run: scripts/build-native.js
- name: Webpack
run: yarn run build
- name: Prepackage plugins
run: scripts/prepackage-plugins.js
# Prevent permission corruption caused by electron-builder
# This is the reason there's a separate workflow for the ZIP build
- run: sed -i '' 's/updateInfo = await/\/\/updateInfo = await/g' node_modules/app-builder-lib/out/targets/ArchiveTarget.js
- name: Build and sign packages
run: scripts/build-macos-zip.js
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
env:
#DEBUG: electron-builder,electron-builder:*
GH_TOKEN: ${{ secrets.GH_TOKEN }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
- name: Build packages without signing
run: scripts/build-macos.js
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
env:
DEBUG: electron-builder,electron-builder:*
- name: Package artifacts
run: |
mkdir artifact-zip
mv dist/*.zip artifact-zip/
- uses: actions/upload-artifact@master
name: Upload ZIP
with:
name: macOS .zip
path: artifact-zip

View File

@@ -2,7 +2,12 @@ name: macOS Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
runs-on: macos-latest runs-on: macos-11.0
strategy:
matrix:
include:
- arch: x86_64
- arch: arm64
steps: steps:
- name: Checkout - name: Checkout
@@ -11,11 +16,11 @@ jobs:
- name: Installing Node - name: Installing Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 10 node-version: 15
- name: Install deps - name: Install deps
run: | run: |
sudo npm i -g yarn@1.19.1 sudo npm i -g yarn@1.22.1
cd app cd app
yarn yarn
cd .. cd ..
@@ -24,37 +29,53 @@ jobs:
- name: Build native deps - name: Build native deps
run: scripts/build-native.js run: scripts/build-native.js
env:
ARCH: ${{matrix.arch}}
- name: Webpack - name: Webpack
run: yarn run build run: yarn run build
- name: Prepackage plugins - name: Prepackage plugins
run: scripts/prepackage-plugins.js run: scripts/prepackage-plugins.js
env:
ARCH: ${{matrix.arch}}
- run: sed -i '' 's/updateInfo = await/\/\/updateInfo = await/g' node_modules/app-builder-lib/out/targets/ArchiveTarget.js
- name: Build and sign packages - name: Build and sign packages
run: scripts/build-macos.js run: scripts/build-macos.js
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push' if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
env: env:
#DEBUG: electron-builder,electron-builder:* ARCH: ${{matrix.arch}}
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }}
CSC_LINK: ${{ secrets.CSC_LINK }} CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }} APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }} APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
# DEBUG: electron-builder,electron-builder:*
- name: Build packages without signing - name: Build packages without signing
run: scripts/build-macos.js run: scripts/build-macos.js
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push' if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
env: env:
DEBUG: electron-builder,electron-builder:* ARCH: ${{matrix.arch}}
# DEBUG: electron-builder,electron-builder:*
- name: Package artifacts - name: Package artifacts
run: | run: |
mkdir artifact-pkg mkdir artifact-pkg
mv dist/*.pkg artifact-pkg/ mv dist/*.pkg artifact-pkg/
mkdir artifact-zip
mv dist/*.zip artifact-zip/
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@master
name: Upload PKG name: Upload PKG
with: with:
name: macOS .pkg name: macOS .pkg (${{matrix.arch}})
path: artifact-pkg path: artifact-pkg
- uses: actions/upload-artifact@master
name: Upload ZIP
with:
name: macOS .zip (${{matrix.arch}})
path: artifact-zip

View File

@@ -11,7 +11,7 @@ jobs:
- name: Installing Node - name: Installing Node
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: 10 node-version: 15
- name: Build - name: Build
shell: powershell shell: powershell

5
.gitignore vendored
View File

@@ -13,6 +13,9 @@ dist
*.xcuserstate *.xcuserstate
*.wixpdb *.wixpdb
.DS_Store
.DS_Store?
coverage coverage
.nyc_output .nyc_output
npm-debug.log npm-debug.log
@@ -28,3 +31,5 @@ docs/api
.electron-symbols .electron-symbols
sentry.properties sentry.properties
sentry-symbols.js sentry-symbols.js
terminus-ssh/util/pagent.exe

View File

@@ -1,5 +1,5 @@
language: node_js language: node_js
node_js: 11 node_js: 15
stages: stages:
- Build - Build

View File

@@ -111,6 +111,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
</tr> </tr>
<tr> <tr>
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td> <td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
</tr> </tr>
</table> </table>

View File

@@ -1,6 +1,4 @@
import { app, ipcMain, Menu, Tray, shell, globalShortcut } from 'electron' import { app, ipcMain, Menu, Tray, shell, screen, globalShortcut, MenuItemConstructorOptions } from 'electron'
// eslint-disable-next-line no-duplicate-imports
import * as electron from 'electron'
import { loadConfig } from './config' import { loadConfig } from './config'
import { Window, WindowOptions } from './window' import { Window, WindowOptions } from './window'
@@ -15,7 +13,7 @@ export class Application {
ipcMain.on('app:register-global-hotkey', (_event, specs) => { ipcMain.on('app:register-global-hotkey', (_event, specs) => {
globalShortcut.unregisterAll() globalShortcut.unregisterAll()
for (let spec of specs) { for (const spec of specs) {
globalShortcut.register(spec, () => { globalShortcut.register(spec, () => {
this.onGlobalHotkey() this.onGlobalHotkey()
}) })
@@ -41,11 +39,13 @@ export class Application {
} }
init (): void { init (): void {
electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed')) screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
screen.on('display-added', () => this.broadcast('host:displays-changed'))
screen.on('display-removed', () => this.broadcast('host:displays-changed'))
} }
async newWindow (options?: WindowOptions): Promise<Window> { async newWindow (options?: WindowOptions): Promise<Window> {
let window = new Window(options) const window = new Window(options)
this.windows.push(window) this.windows.push(window)
window.visible$.subscribe(visible => { window.visible$.subscribe(visible => {
if (visible) { if (visible) {
@@ -66,29 +66,29 @@ export class Application {
onGlobalHotkey (): void { onGlobalHotkey (): void {
if (this.windows.some(x => x.isFocused())) { if (this.windows.some(x => x.isFocused())) {
for (let window of this.windows) { for (const window of this.windows) {
window.hide() window.hide()
} }
} else { } else {
for (let window of this.windows) { for (const window of this.windows) {
window.present() window.present()
} }
} }
} }
presentAllWindows (): void { presentAllWindows (): void {
for (let window of this.windows) { for (const window of this.windows) {
window.present() window.present()
} }
} }
broadcast (event: string, ...args): void { broadcast (event: string, ...args: any[]): void {
for (const window of this.windows) { for (const window of this.windows) {
window.send(event, ...args) window.send(event, ...args)
} }
} }
async send (event: string, ...args): Promise<void> { async send (event: string, ...args: any[]): Promise<void> {
if (!this.hasWindows()) { if (!this.hasWindows()) {
await this.newWindow() await this.newWindow()
} }
@@ -132,20 +132,18 @@ export class Application {
} }
focus (): void { focus (): void {
for (let window of this.windows) { for (const window of this.windows) {
window.show() window.show()
} }
} }
handleSecondInstance (argv: string[], cwd: string): void { handleSecondInstance (argv: string[], cwd: string): void {
this.presentAllWindows() this.presentAllWindows()
for (let window of this.windows) { this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd)
window.handleSecondInstance(argv, cwd)
}
} }
private setupMenu () { private setupMenu () {
let template: Electron.MenuItemConstructorOptions[] = [ const template: MenuItemConstructorOptions[] = [
{ {
label: 'Application', label: 'Application',
submenu: [ submenu: [

View File

@@ -4,7 +4,7 @@ import * as yaml from 'js-yaml'
import { app } from 'electron' import { app } from 'electron'
export function loadConfig (): any { export function loadConfig (): any {
let configPath = path.join(app.getPath('userData'), 'config.yaml') const configPath = path.join(app.getPath('userData'), 'config.yaml')
if (fs.existsSync(configPath)) { if (fs.existsSync(configPath)) {
return yaml.safeLoad(fs.readFileSync(configPath, 'utf8')) return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
} else { } else {

View File

@@ -1,6 +1,6 @@
import * as createLRU from 'lru-cache' import * as LRU from 'lru-cache'
import * as fs from 'fs' import * as fs from 'fs'
const lru = createLRU({ max: 256, maxAge: 250 }) const lru = new LRU({ max: 256, maxAge: 250 })
const origLstat = fs.realpathSync.bind(fs) const origLstat = fs.realpathSync.bind(fs)
// NB: The biggest offender of thrashing realpathSync is the node module system // NB: The biggest offender of thrashing realpathSync is the node module system

View File

@@ -1,9 +1,9 @@
const { init } = process.type === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer') const { init } = String(process.type) === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer')
import * as isDev from 'electron-is-dev' import * as isDev from 'electron-is-dev'
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876' const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
let release let release = null
try { try {
release = require('electron').app.getVersion() release = require('electron').app.getVersion()
} catch { } catch {

View File

@@ -1,6 +1,11 @@
import * as glasstron from 'glasstron'
if (process.platform === 'win32' || process.platform === 'linux') {
glasstron.init()
}
import { Subject, Observable } from 'rxjs' import { Subject, Observable } from 'rxjs'
import { debounceTime } from 'rxjs/operators' import { debounceTime } from 'rxjs/operators'
import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen } from 'electron' import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen, BrowserWindowConstructorOptions } from 'electron'
import ElectronConfig = require('electron-config') import ElectronConfig = require('electron-config')
import * as os from 'os' import * as os from 'os'
import * as path from 'path' import * as path from 'path'
@@ -8,12 +13,8 @@ import * as path from 'path'
import { parseArgs } from './cli' import { parseArgs } from './cli'
import { loadConfig } from './config' import { loadConfig } from './config'
let SetWindowCompositionAttribute: any let DwmEnableBlurBehindWindow: any = null
let AccentState: any
let DwmEnableBlurBehindWindow: any
if (process.platform === 'win32') { if (process.platform === 'win32') {
SetWindowCompositionAttribute = require('windows-swca').SetWindowCompositionAttribute
AccentState = require('windows-swca').ACCENT_STATE
DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow
} }
@@ -21,11 +22,16 @@ export interface WindowOptions {
hidden?: boolean hidden?: boolean
} }
abstract class GlasstronWindow extends BrowserWindow {
blurType: string
abstract setBlur (_: boolean)
}
export class Window { export class Window {
ready: Promise<void> ready: Promise<void>
private visible = new Subject<boolean>() private visible = new Subject<boolean>()
private closed = new Subject<void>() private closed = new Subject<void>()
private window: BrowserWindow private window: GlasstronWindow
private windowConfig: ElectronConfig private windowConfig: ElectronConfig
private windowBounds: Rectangle private windowBounds: Rectangle
private closing = false private closing = false
@@ -44,8 +50,8 @@ export class Window {
this.windowConfig = new ElectronConfig({ name: 'window' }) this.windowConfig = new ElectronConfig({ name: 'window' })
this.windowBounds = this.windowConfig.get('windowBoundaries') this.windowBounds = this.windowConfig.get('windowBoundaries')
let maximized = this.windowConfig.get('maximized') const maximized = this.windowConfig.get('maximized')
let bwOptions: Electron.BrowserWindowConstructorOptions = { const bwOptions: BrowserWindowConstructorOptions = {
width: 800, width: 800,
height: 600, height: 600,
title: 'Terminus', title: 'Terminus',
@@ -55,6 +61,7 @@ export class Window {
nodeIntegration: true, nodeIntegration: true,
preload: path.join(__dirname, 'sentry.js'), preload: path.join(__dirname, 'sentry.js'),
backgroundThrottling: false, backgroundThrottling: false,
enableRemoteModule: true,
}, },
frame: false, frame: false,
show: false, show: false,
@@ -82,11 +89,8 @@ export class Window {
} }
} }
if (process.platform === 'linux') { this.window = new glasstron.BrowserWindow(bwOptions)
bwOptions.backgroundColor = '#131d27'
}
this.window = new BrowserWindow(bwOptions)
this.window.once('ready-to-show', () => { this.window.once('ready-to-show', () => {
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
this.window.setVibrancy('window') this.window.setVibrancy('window')
@@ -101,6 +105,7 @@ export class Window {
this.window.show() this.window.show()
} }
this.window.focus() this.window.focus()
this.window.moveTop()
} }
}) })
@@ -129,22 +134,20 @@ export class Window {
}) })
} }
setVibrancy (enabled: boolean, type?: string): void { setVibrancy (enabled: boolean, type?: string, userRequested?: boolean): void {
if (userRequested ?? true) {
this.lastVibrancy = { enabled, type } this.lastVibrancy = { enabled, type }
}
if (process.platform === 'win32') { if (process.platform === 'win32') {
if (parseFloat(os.release()) >= 10) { if (parseFloat(os.release()) >= 10) {
let attribValue = AccentState.ACCENT_DISABLED this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
if (enabled) { this.window.setBlur(enabled)
if (type === 'fluent') {
attribValue = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND
} else {
attribValue = AccentState.ACCENT_ENABLE_BLURBEHIND
}
}
SetWindowCompositionAttribute(this.window.getNativeWindowHandle(), attribValue, 0x00000000)
} else { } else {
DwmEnableBlurBehindWindow(this.window, enabled) DwmEnableBlurBehindWindow(this.window, enabled)
} }
} else if (process.platform === 'linux') {
this.window.setBackgroundColor(enabled ? '#00000000' : '#131d27')
this.window.setBlur(enabled)
} else { } else {
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269 this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
} }
@@ -152,13 +155,14 @@ export class Window {
show (): void { show (): void {
this.window.show() this.window.show()
this.window.moveTop()
} }
focus (): void { focus (): void {
this.window.focus() this.window.focus()
} }
send (event: string, ...args): void { send (event: string, ...args: any[]): void {
if (!this.window) { if (!this.window) {
return return
} }
@@ -212,10 +216,8 @@ export class Window {
} }
handleSecondInstance (argv: string[], cwd: string): void { handleSecondInstance (argv: string[], cwd: string): void {
if (!this.configStore.appearance?.dock) {
this.send('host:second-instance', parseArgs(argv, cwd), cwd) this.send('host:second-instance', parseArgs(argv, cwd), cwd)
} }
}
private setupWindowManagement () { private setupWindowManagement () {
this.window.on('show', () => { this.window.on('show', () => {
@@ -227,7 +229,7 @@ export class Window {
this.visible.next(false) this.visible.next(false)
}) })
let moveSubscription = new Observable<void>(observer => { const moveSubscription = new Observable<void>(observer => {
this.window.on('move', () => observer.next()) this.window.on('move', () => observer.next())
}).pipe(debounceTime(250)).subscribe(() => { }).pipe(debounceTime(250)).subscribe(() => {
this.send('host:window-moved') this.send('host:window-moved')
@@ -362,24 +364,21 @@ export class Window {
this.disableVibrancyWhileDragging = value this.disableVibrancyWhileDragging = value
}) })
this.window.on('will-move', () => { let moveEndedTimeout: number|null = null
const onBoundsChange = () => {
if (!this.lastVibrancy?.enabled || !this.disableVibrancyWhileDragging) { if (!this.lastVibrancy?.enabled || !this.disableVibrancyWhileDragging) {
return return
} }
let timeout: number|null = null this.setVibrancy(false, undefined, false)
const oldVibrancy = this.lastVibrancy if (moveEndedTimeout) {
this.setVibrancy(false) clearTimeout(moveEndedTimeout)
const onMove = () => {
if (timeout) {
clearTimeout(timeout)
} }
timeout = setTimeout(() => { moveEndedTimeout = setTimeout(() => {
this.window.off('move', onMove) this.setVibrancy(this.lastVibrancy.enabled, this.lastVibrancy.type)
this.setVibrancy(oldVibrancy.enabled, oldVibrancy.type) }, 50)
}, 500)
} }
this.window.on('move', onMove) this.window.on('move', onBoundsChange)
}) this.window.on('resize', onBoundsChange)
} }
private destroy () { private destroy () {

View File

@@ -13,43 +13,50 @@
"watch": "webpack --progress --color --watch" "watch": "webpack --progress --color --watch"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "9.1.4", "@angular/animations": "^9.1.9",
"@angular/common": "9.1.4", "@angular/common": "^9.1.11",
"@angular/compiler": "9.1.4", "@angular/compiler": "^9.1.9",
"@angular/core": "9.1.4", "@angular/core": "^9.1.9",
"@angular/forms": "9.1.4", "@angular/forms": "^9.1.11",
"@angular/platform-browser": "9.1.4", "@angular/platform-browser": "^9.1.9",
"@angular/platform-browser-dynamic": "9.1.4", "@angular/platform-browser-dynamic": "^9.1.9",
"@ng-bootstrap/ng-bootstrap": "^6.1.0", "@ng-bootstrap/ng-bootstrap": "^6.1.0",
"devtron": "1.4.0", "@terminus-term/node-pty": "0.10.0-beta10",
"electron-config": "2.0.0", "electron-config": "2.0.0",
"electron-debug": "^3.0.1", "electron-debug": "^3.0.1",
"electron-is-dev": "1.1.0", "electron-is-dev": "1.1.0",
"electron-updater": "^4.3.1", "fontmanager-redux": "1.0.0",
"fontmanager-redux": "0.4.0", "glasstron": "0.0.5",
"js-yaml": "3.13.1", "js-yaml": "3.14.0",
"keytar": "^5.6.0", "keytar": "^7.2.0",
"mz": "^2.7.0", "mz": "^2.7.0",
"ngx-toastr": "^12.0.1", "ngx-toastr": "^12.0.1",
"node-pty": "^0.10.0-beta8", "npm": "7.0.15",
"npm": "6.9.0",
"path": "0.12.7", "path": "0.12.7",
"rxjs": "^6.5.5", "rxjs": "^6.5.5",
"rxjs-compat": "^6.5.5", "rxjs-compat": "^6.6.0",
"yargs": "^15.3.1", "yargs": "^15.4.1",
"zone.js": "^0.10.3" "zone.js": "^0.11.3"
}, },
"optionalDependencies": { "optionalDependencies": {
"macos-native-processlist": "^1.0.2", "macos-native-processlist": "^2.0.0",
"serialport": "^8.0.7", "serialport": "^9.0.4",
"windows-blurbehind": "^1.0.1", "windows-blurbehind": "^1.0.1",
"windows-native-registry": "^1.0.17", "windows-native-registry": "^3.0.0",
"windows-process-tree": "^0.2.4", "windows-process-tree": "^0.2.4"
"windows-swca": "^2.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/mz": "0.0.32", "@types/mz": "0.0.32",
"@types/node": "12.7.12", "@types/node": "14.14.14",
"node-abi": "^2.16.0" "node-abi": "2.19.3"
},
"peerDependencies": {
"terminus-community-color-schemes": "*",
"terminus-core": "*",
"terminus-plugin-manager": "*",
"terminus-serial": "*",
"terminus-settings": "*",
"terminus-ssh": "*",
"terminus-terminal": "*"
} }
} }

View File

@@ -3,6 +3,7 @@ import 'source-sans-pro/source-sans-pro.css'
import 'source-code-pro/source-code-pro.css' import 'source-code-pro/source-code-pro.css'
import '@fortawesome/fontawesome-free/css/solid.css' import '@fortawesome/fontawesome-free/css/solid.css'
import '@fortawesome/fontawesome-free/css/brands.css' import '@fortawesome/fontawesome-free/css/brands.css'
import '@fortawesome/fontawesome-free/css/regular.css'
import '@fortawesome/fontawesome-free/css/fontawesome.css' import '@fortawesome/fontawesome-free/css/fontawesome.css'
import 'ngx-toastr/toastr.css' import 'ngx-toastr/toastr.css'
import './preload.scss' import './preload.scss'

View File

@@ -83,7 +83,7 @@ const originalRequire = (global as any).require
if (cachedBuiltinModules[query]) { if (cachedBuiltinModules[query]) {
return cachedBuiltinModules[query] return cachedBuiltinModules[query]
} }
return originalRequire.apply(this, arguments) return originalRequire.apply(this, [query])
} }
const originalModuleRequire = nodeModule.prototype.require const originalModuleRequire = nodeModule.prototype.require
@@ -173,8 +173,8 @@ export async function loadPlugins (foundPlugins: PluginInfo[], progress: Progres
console.time(label) console.time(label)
const packageModule = nodeRequire(foundPlugin.path) const packageModule = nodeRequire(foundPlugin.path)
const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
pluginModule['pluginName'] = foundPlugin.name pluginModule.pluginName = foundPlugin.name
pluginModule['bootstrap'] = packageModule.bootstrap pluginModule.bootstrap = packageModule.bootstrap
plugins.push(pluginModule) plugins.push(pluginModule)
console.timeEnd(label) console.timeEnd(label)
await new Promise(x => setTimeout(x, 50)) await new Promise(x => setTimeout(x, 50))

View File

@@ -9,6 +9,7 @@
padding: 10px; padding: 10px;
background-image: none; background-image: none;
width: auto; width: auto;
flex-basis: auto;
&.toast-error { &.toast-error {
background-color: #BD362F; background-color: #BD362F;

View File

@@ -12,7 +12,6 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUnusedParameters": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"lib": [ "lib": [
"dom", "dom",

View File

@@ -37,6 +37,7 @@ module.exports = {
'electron-config': 'commonjs electron-config', 'electron-config': 'commonjs electron-config',
'electron-vibrancy': 'commonjs electron-vibrancy', 'electron-vibrancy': 'commonjs electron-vibrancy',
fs: 'commonjs fs', fs: 'commonjs fs',
glasstron: 'commonjs glasstron',
mz: 'commonjs mz', mz: 'commonjs mz',
path: 'commonjs path', path: 'commonjs path',
yargs: 'commonjs yargs', yargs: 'commonjs yargs',

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ platform:
- x64 - x64
environment: environment:
nodejs_version: "10" nodejs_version: "15"
version: "{build}" version: "{build}"

View File

@@ -0,0 +1,16 @@
const fs = require('fs')
const signHook = require('./afterSignHook')
module.exports = async function (params) {
// notarize the app on Mac OS only.
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
return
}
console.log('afterBuild hook triggered')
let pkgName = fs.readdirSync('dist').find(x => x.endsWith('.pkg'))
signHook({
appOutDir: 'dist',
_pathOverride: pkgName,
})
}

View File

@@ -13,7 +13,7 @@ module.exports = async function (params) {
let appId = 'org.terminus' let appId = 'org.terminus'
let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`) let appPath = path.join(params.appOutDir, params._pathOverride || `${params.packager.appInfo.productFilename}.app`)
if (!fs.existsSync(appPath)) { if (!fs.existsSync(appPath)) {
throw new Error(`Cannot find application at: ${appPath}`) throw new Error(`Cannot find application at: ${appPath}`)
} }

View File

@@ -10,5 +10,9 @@
<true/> <true/>
<key>com.apple.security.cs.disable-library-validation</key> <key>com.apple.security.cs.disable-library-validation</key>
<true/> <true/>
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@@ -2,7 +2,9 @@
appId: org.terminus appId: org.terminus
productName: Terminus productName: Terminus
compression: normal compression: normal
npmRebuild: false
afterSign: "./build/mac/afterSignHook.js" afterSign: "./build/mac/afterSignHook.js"
afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
files: files:
- "**/*" - "**/*"
- dist - dist
@@ -24,14 +26,20 @@ nsis:
mac: mac:
category: public.app-category.video category: public.app-category.video
icon: "./build/mac/icon.icns" icon: "./build/mac/icon.icns"
artifactName: terminus-${version}-macos.${ext} artifactName: terminus-${version}-macos-${env.ARCH}.${ext}
hardenedRuntime: true hardenedRuntime: true
entitlements: "./build/mac/entitlements.plist" entitlements: "./build/mac/entitlements.plist"
entitlementsInherit: "./build/mac/entitlements.plist" entitlementsInherit: "./build/mac/entitlements.plist"
extendInfo: extendInfo:
NSRequiresAquaSystemAppearance: false NSRequiresAquaSystemAppearance: false
pkg: NSCameraUsageDescription: "A subprocess requests access to the device's camera."
artifactName: terminus-${version}-macos.pkg NSMicrophoneUsageDescription: "A subprocess requests access to the device's microphone."
NSLocationUsageDescription: "A subprocess requests access to the user's location information."
NSDesktopFolderUsageDescription: "A subprocess requests access to the user's Desktop folder."
NSDocumentsFolderUsageDescription: "A subprocess requests access to the user's Documents folder."
NSDownloadsFolderUsageDescription: "A subprocess requests access to the user's Downloads folder."
NSNetworkVolumesUsageDescription: 'A subprocess requests access to files on a network volume.'
NSRemovableVolumesUsageDescription: 'A subprocess requests access to files on a removable volume.'
linux: linux:
category: Utilities category: Utilities
@@ -48,6 +56,7 @@ deb:
depends: depends:
- gconf2 - gconf2
- gconf-service - gconf-service
- gnome-keyring
- libnotify4 - libnotify4
- libsecret-1-0 - libsecret-1-0
- libappindicator1 - libappindicator1
@@ -57,4 +66,4 @@ deb:
rpm: rpm:
depends: depends:
- screen - screen
- gnome-python2-gnomekeyring - gnome-keyring

Binary file not shown.

View File

@@ -1,67 +1,72 @@
{ {
"devDependencies": { "devDependencies": {
"@fortawesome/fontawesome-free": "^5.13.0", "@fortawesome/fontawesome-free": "^5.13.0",
"@sentry/cli": "^1.52.3", "@sentry/cli": "^1.61.0",
"@sentry/electron": "^1.2.1", "@sentry/electron": "^2.0.4",
"@types/electron-config": "^3.2.2", "@types/electron-config": "^3.2.2",
"@types/electron-debug": "^2.1.0", "@types/electron-debug": "^2.1.0",
"@types/js-yaml": "^3.12.3", "@types/fs-extra": "^8.1.1",
"@types/node": "12.7.12", "@types/js-yaml": "^3.12.5",
"@types/webpack-env": "^1.15.2", "@types/node": "14.14.14",
"@typescript-eslint/eslint-plugin": "^2.26.0", "@types/webpack-env": "^1.16.0",
"@typescript-eslint/parser": "^2.31.0", "@typescript-eslint/eslint-plugin": "^4.11.0",
"@typescript-eslint/parser": "^4.11.0",
"apply-loader": "2.0.0", "apply-loader": "2.0.0",
"awesome-typescript-loader": "^5.0.0", "awesome-typescript-loader": "^5.2.1",
"core-js": "^3.6.5", "core-js": "^3.8.1",
"cross-env": "7.0.2", "cross-env": "7.0.2",
"css-loader": "3.4.2", "css-loader": "3.4.2",
"electron": "^8.2.5", "electron": "^11.1.1",
"electron-builder": "22.5.1", "electron-builder": "22.10.3",
"electron-download": "^4.1.1", "electron-download": "^4.1.1",
"electron-installer-snap": "^5.0.0", "electron-installer-snap": "^5.1.0",
"electron-notarize": "^0.1.1", "electron-notarize": "^1.0.0",
"electron-rebuild": "^1.10.1", "electron-rebuild": "^2.3.4",
"eslint": "^6.8.0", "eslint": "^7.6.0",
"eslint-plugin-import": "^2.20.2", "eslint-plugin-import": "^2.21.1",
"file-loader": "^5.0.2", "file-loader": "^5.1.0",
"graceful-fs": "^4.2.4", "graceful-fs": "^4.2.4",
"html-loader": "0.5.5", "html-loader": "0.5.5",
"json-loader": "0.5.7", "json-loader": "0.5.7",
"node-abi": "^2.16.0", "lru-cache": "^6.0.0",
"node-gyp": "^6.1.0", "node-abi": "^2.19.3",
"node-sass": "^4.14.1", "node-gyp": "^7.1.2",
"node-sass": "^5.0.0",
"npmlog": "4.1.2", "npmlog": "4.1.2",
"npx": "^10.2.0", "npx": "^10.2.2",
"pug": "^2.0.4", "pug": "^2.0.4",
"pug-html-loader": "1.1.5", "pug-html-loader": "1.1.5",
"pug-lint": "^2.6.0", "pug-lint": "^2.6.0",
"pug-loader": "^2.4.0", "pug-loader": "^2.4.0",
"pug-static-loader": "2.0.0", "pug-static-loader": "2.0.0",
"raw-loader": "4.0.1", "raw-loader": "4.0.1",
"sass-loader": "^8.0.0", "sass-loader": "^10.1.0",
"shelljs": "0.8.4", "shelljs": "0.8.4",
"source-code-pro": "^2.30.2", "source-code-pro": "^2.30.2",
"source-sans-pro": "3.6.0", "source-sans-pro": "3.6.0",
"style-loader": "^1.1.4", "ssh2-streams": "^0.4.10",
"svg-inline-loader": "^0.8.0", "style-loader": "^1.3.0",
"svg-inline-loader": "^0.8.2",
"to-string-loader": "1.1.6", "to-string-loader": "1.1.6",
"tslib": "^1.11.1", "tslib": "^2.0.3",
"typedoc": "^0.17.6", "typedoc": "^0.18.0",
"typescript": "^3.8.3", "typescript": "^3.9.7",
"url-loader": "^3.0.0", "url-loader": "^3.0.0",
"val-loader": "2.1.1", "val-loader": "2.1.1",
"webpack": "^5.0.0-beta.16", "webpack": "^5.11.0",
"webpack-cli": "^3.3.10", "webpack-cli": "^4.2.0",
"yaml-loader": "0.6.0" "yaml-loader": "0.6.0"
}, },
"resolutions": { "resolutions": {
"*/node-abi": "^2.14.0" "*/node-abi": "^2.19.3",
"**/graceful-fs": "^4.2.4"
}, },
"scripts": { "scripts": {
"build": "npm run build:typings && webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js && webpack --color --config terminus-serial/webpack.config.js", "build": "npm run build:typings && webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js && webpack --color --config terminus-serial/webpack.config.js",
"build:typings": "node scripts/build-typings.js", "build:typings": "node scripts/build-typings.js",
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch", "watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
"start": "cross-env TERMINUS_DEV=1 electron app --debug", "start": "cross-env TERMINUS_DEV=1 electron app --debug",
"start:prod": "electron app --debug",
"prod": "cross-env TERMINUS_DEV=1 electron app", "prod": "cross-env TERMINUS_DEV=1 electron app",
"docs": "typedoc --out docs/api terminus-core/src && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src", "docs": "typedoc --out docs/api terminus-core/src && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src",
"lint": "eslint --ext ts */src */lib", "lint": "eslint --ext ts */src */lib",

View File

@@ -1,17 +0,0 @@
#!/usr/bin/env node
const builder = require('electron-builder').build
const vars = require('./vars')
const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/')
const isCI = !!process.env.GITHUB_REF
builder({
dir: true,
mac: ['zip'],
config: {
extraMetadata: {
version: vars.version,
},
},
publish: isTag ? 'always' : 'onTag',
}).catch(() => process.exit(1))

View File

@@ -1,17 +1,24 @@
#!/usr/bin/env node #!/usr/bin/env node
const builder = require('electron-builder').build const builder = require('electron-builder').build
const vars = require('./vars') const vars = require('./vars')
const fs = require('fs')
const signHook = require('../build/mac/afterSignHook')
const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/') const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/')
const isCI = !!process.env.GITHUB_REF
process.env.ARCH = process.env.ARCH || process.arch
builder({ builder({
dir: true, dir: true,
mac: ['pkg'], mac: ['pkg', 'zip'],
arm64: process.env.ARCH === 'arm64',
config: { config: {
extraMetadata: { extraMetadata: {
version: vars.version, version: vars.version,
}, },
}, },
publish: isTag ? 'always' : 'onTag', publish: isTag ? 'always' : 'onTag',
}).catch(() => process.exit(1)) }).catch(e => {
console.error(e)
process.exit(1)
})

View File

@@ -8,6 +8,7 @@ for (let dir of ['app', 'terminus-core', 'terminus-ssh', 'terminus-terminal']) {
const build = rebuild({ const build = rebuild({
buildPath: path.resolve(__dirname, '../' + dir), buildPath: path.resolve(__dirname, '../' + dir),
electronVersion: vars.electronVersion, electronVersion: vars.electronVersion,
arch: process.env.ARCH ?? process.arch,
force: true, force: true,
}) })
build.catch(e => { build.catch(e => {

View File

@@ -10,13 +10,13 @@ const npx = `${localBinPath}/npx`;
log.info('deps', 'app') log.info('deps', 'app')
sh.cd('app') sh.cd('app')
sh.exec(`${npx} yarn install`) sh.exec(`${npx} yarn install --force`)
sh.cd('..') sh.cd('..')
vars.builtinPlugins.forEach(plugin => { vars.builtinPlugins.forEach(plugin => {
log.info('deps', plugin) log.info('deps', plugin)
sh.cd(plugin) sh.cd(plugin)
sh.exec(`${npx} yarn install`) sh.exec(`${npx} yarn install --force`)
sh.cd('..') sh.cd('..')
}) })

View File

@@ -15,10 +15,17 @@ vars.builtinPlugins.forEach(plugin => {
sh.cp('-r', path.join('..', plugin), '.') sh.cp('-r', path.join('..', plugin), '.')
sh.rm('-rf', path.join(plugin, 'node_modules')) sh.rm('-rf', path.join(plugin, 'node_modules'))
sh.cd(plugin) sh.cd(plugin)
sh.exec(`npm install --only=prod`) sh.exec(`yarn install --force --production`)
log.info('rebuild', 'native') log.info('rebuild', 'native')
if (fs.existsSync('node_modules')) { if (fs.existsSync('node_modules')) {
rebuild(path.resolve('.'), vars.electronVersion, process.arch, [], true) rebuild({
buildPath: path.resolve('.'),
electronVersion: vars.electronVersion,
arch: process.env.ARCH ?? process.arch,
force: true,
})
} }
sh.cd('..') sh.cd('..')
}) })

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-community-color-schemes", "name": "terminus-community-color-schemes",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "Community color schemes for Terminus", "description": "Community color schemes for Terminus",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -17,7 +17,7 @@
"author": "Eugene Pankov", "author": "Eugene Pankov",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"@angular/core": "^7", "@angular/core": "^9.1.9",
"terminus-core": "*", "terminus-core": "*",
"terminus-terminal": "*" "terminus-terminal": "*"
} }

View File

@@ -4,7 +4,7 @@ module.exports = {
target: 'node', target: 'node',
entry: 'src/index.ts', entry: 'src/index.ts',
context: __dirname, context: __dirname,
devtool: 'eval-cheap-module-source-map', devtool: 'cheap-module-source-map',
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'index.js', filename: 'index.js',

View File

@@ -1,2 +1 @@
dist dist
node_modules

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-core", "name": "terminus-core",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "Terminus core", "description": "Terminus core",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -29,17 +29,18 @@
"mixpanel": "^0.10.2", "mixpanel": "^0.10.2",
"ng2-dnd": "^5.0.2", "ng2-dnd": "^5.0.2",
"ngx-perfect-scrollbar": "^8.0.0", "ngx-perfect-scrollbar": "^8.0.0",
"readable-stream": "2.3.7",
"shell-escape": "^0.2.0", "shell-escape": "^0.2.0",
"uuid": "^8.0.0", "uuid": "^8.0.0",
"winston": "^3.2.1" "winston": "^3.3.3"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/animations": "^7", "@angular/animations": "^9.1.9",
"@angular/common": "^7", "@angular/common": "^9.1.11",
"@angular/core": "^7", "@angular/core": "^9.1.9",
"@angular/forms": "^7", "@angular/forms": "^9.1.11",
"@angular/platform-browser": "^7", "@angular/platform-browser": "^9.1.11",
"@angular/platform-browser-dynamic": "^7", "@angular/platform-browser-dynamic": "^9.1.11",
"rxjs": "^5" "rxjs": "^6.6.3"
} }
} }

View File

@@ -33,5 +33,5 @@ export abstract class ConfigProvider {
* } * }
* ``` * ```
*/ */
platformDefaults: {[platform: string]: any} = {} platformDefaults: Record<string, any> = {}
} }

View File

@@ -1,3 +1,4 @@
import type { MenuItemConstructorOptions } from 'electron'
import { BaseTabComponent } from '../components/baseTab.component' import { BaseTabComponent } from '../components/baseTab.component'
import { TabHeaderComponent } from '../components/tabHeader.component' import { TabHeaderComponent } from '../components/tabHeader.component'
@@ -7,5 +8,5 @@ import { TabHeaderComponent } from '../components/tabHeader.component'
export abstract class TabContextMenuItemProvider { export abstract class TabContextMenuItemProvider {
weight = 0 weight = 0
abstract async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> abstract async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]>
} }

View File

@@ -4,10 +4,13 @@ title-bar(
) )
.content( .content(
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top"' [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"',
[class.tabs-on-side]='hasVerticalTabs()',
) )
.tab-bar .tab-bar
.inset.background(*ngIf='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"') .inset.background(*ngIf='hostApp.platform == Platform.macOS \
&& config.store.appearance.frame == "thin" \
&& (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")')
.tabs( .tabs(
dnd-sortable-container, dnd-sortable-container,
[sortableData]='app.tabs', [sortableData]='app.tabs',
@@ -18,12 +21,12 @@ title-bar(
[sortableIndex]='idx', [sortableIndex]='idx',
(onDragStart)='onTabDragStart()', (onDragStart)='onTabDragStart()',
(onDragEnd)='onTabDragEnd()', (onDragEnd)='onTabDragEnd()',
[index]='idx', [index]='idx',
[tab]='tab', [tab]='tab',
[active]='tab == app.activeTab', [active]='tab == app.activeTab',
[hasActivity]='tab.activity$|async', [hasActivity]='tab.activity$|async',
@animateTab, @animateTab,
[@.disabled]='hasVerticalTabs()',
(click)='app.selectTab(tab)', (click)='app.selectTab(tab)',
[class.fully-draggable]='hostApp.platform != Platform.macOS', [class.fully-draggable]='hostApp.platform != Platform.macOS',
[class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging',
@@ -87,7 +90,8 @@ title-bar(
) )
window-controls.background( window-controls.background(
*ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', *ngIf='config.store.appearance.frame == "thin" \
&& (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
) )
start-page(*ngIf='ready && app.tabs.length == 0') start-page(*ngIf='ready && app.tabs.length == 0')

View File

@@ -15,10 +15,18 @@
$tabs-height: 38px; $tabs-height: 38px;
$tab-border-radius: 4px; $tab-border-radius: 4px;
$side-tab-width: 200px;
.wrap {
display: flex;
width: 100vw;
height: 100vh;
flex-direction: row;
}
.content { .content {
height: 100%; width: 100vw;
height: 100vh;
flex: auto; flex: auto;
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
@@ -26,15 +34,50 @@ $tab-border-radius: 4px;
&.tabs-on-top { &.tabs-on-top {
flex-direction: column; flex-direction: column;
} }
&.tabs-on-side {
flex-direction: row-reverse;
&.tabs-on-top {
flex-direction: row;
} }
}
}
.content.tabs-on-side > .tab-bar {
height: 100%;
width: $side-tab-width;
overflow-y: auto;
overflow-x: hidden;
flex-direction: column;
background: rgba(0, 0, 0, 0.25);
.tabs {
width: $side-tab-width;
flex: none;
flex-direction: column;
tab-header {
flex: 0 0 $tabs-height;
}
}
.drag-space {
flex: auto;
}
}
.tab-bar { .tab-bar {
flex: none; flex: none;
height: $tabs-height; height: $tabs-height;
display: flex; display: flex;
width: 100%;
.btn-tab-bar { .btn-tab-bar {
line-height: $tabs-height + 2px; line-height: $tabs-height + 2px;
height: $tabs-height;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@@ -50,6 +93,8 @@ $tab-border-radius: 4px;
border: none; border: none;
border-radius: 0; border-radius: 0;
align-items: center;
&.dropdown-toggle::after { &.dropdown-toggle::after {
display: none; display: none;
} }
@@ -74,7 +119,10 @@ $tab-border-radius: 4px;
& > .inset { & > .inset {
width: 85px; width: 85px;
height: $tabs-height;
flex: none; flex: none;
opacity: 0;
-webkit-app-region: drag;
} }
window-controls { window-controls {

View File

@@ -184,6 +184,10 @@ export class AppRootComponent {
return false return false
} }
hasVerticalTabs () {
return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right'
}
async updateApp () { async updateApp () {
if ((await this.electron.showMessageBox( if ((await this.electron.showMessageBox(
this.hostApp.getWindow(), this.hostApp.getWindow(),

View File

@@ -157,6 +157,10 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
/** @hidden */ /** @hidden */
_spanners: SplitSpannerInfo[] = [] _spanners: SplitSpannerInfo[] = []
/** @hidden */
_allFocusMode = false
/** @hidden */
private focusedTab: BaseTabComponent private focusedTab: BaseTabComponent
private maximizedTab: BaseTabComponent|null = null private maximizedTab: BaseTabComponent|null = null
private hotkeysSubscription: Subscription private hotkeysSubscription: Subscription
@@ -254,12 +258,13 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
if (this._recoveredState) { if (this._recoveredState) {
await this.recoverContainer(this.root, this._recoveredState) await this.recoverContainer(this.root, this._recoveredState)
this.layout() this.layout()
setImmediate(() => { setTimeout(() => {
if (this.hasFocus) { if (this.hasFocus) {
this.getAllTabs().forEach(x => x.emitFocused()) for (const tab of this.getAllTabs()) {
this.focusAnyIn(this.root) this.focus(tab)
} }
}) }
}, 100)
} }
this.initialized.next() this.initialized.next()
this.initialized.complete() this.initialized.complete()
@@ -480,6 +485,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
} }
layout (): void {
this.root.normalize()
this._spanners = []
this.layoutInternal(this.root, 0, 0, 100, 100)
}
private attachTabView (tab: BaseTabComponent) { private attachTabView (tab: BaseTabComponent) {
const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any> // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any> // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
this.viewRefs.set(tab, ref) this.viewRefs.set(tab, ref)
@@ -505,12 +516,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
} }
} }
private layout () {
this.root.normalize()
this._spanners = []
this.layoutInternal(this.root, 0, 0, 100, 100)
}
private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) { private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
const size = root.orientation === 'v' ? h : w const size = root.orientation === 'v' ? h : w
const sizes = root.ratios.map(x => x * size) const sizes = root.ratios.map(x => x * size)
@@ -535,7 +540,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
element.classList.toggle('child', true) element.classList.toggle('child', true)
element.classList.toggle('maximized', child === this.maximizedTab) element.classList.toggle('maximized', child === this.maximizedTab)
element.classList.toggle('minimized', this.maximizedTab && child !== this.maximizedTab) element.classList.toggle('minimized', this.maximizedTab && child !== this.maximizedTab)
element.classList.toggle('focused', child === this.focusedTab) element.classList.toggle('focused', this._allFocusMode || child === this.focusedTab)
element.style.left = `${childX}%` element.style.left = `${childX}%`
element.style.top = `${childY}%` element.style.top = `${childY}%`
element.style.width = `${childW}%` element.style.width = `${childW}%`

View File

@@ -1,7 +1,7 @@
.progressbar([style.width]='progress + "%"', *ngIf='progress != null') .progressbar([style.width]='progress + "%"', *ngIf='progress != null')
.index( .index(*ngIf='!config.store.terminal.hideTabIndex',
#handle, #handle,
[style.background-color]='tab.color', [style.background-color]='tab.color',
) {{index + 1}} ) {{index + 1}}
.name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}} .name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}}
button((click)='app.closeTab(tab, true)') &times; button(*ngIf='!config.store.terminal.hideCloseButton',(click)='app.closeTab(tab, true)') &times;

View File

@@ -13,6 +13,11 @@ $tabs-height: 38px;
overflow: hidden; overflow: hidden;
&.vertical {
flex: none;
height: $tabs-height;
}
.index { .index {
flex: none; flex: none;
font-weight: bold; font-weight: bold;

View File

@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import type { MenuItemConstructorOptions } from 'electron'
import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core' import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core'
import { SortableComponent } from 'ng2-dnd' import { SortableComponent } from 'ng2-dnd'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@@ -9,10 +10,11 @@ import { HotkeysService } from '../services/hotkeys.service'
import { ElectronService } from '../services/electron.service' import { ElectronService } from '../services/electron.service'
import { AppService } from '../services/app.service' import { AppService } from '../services/app.service'
import { HostAppService, Platform } from '../services/hostApp.service' import { HostAppService, Platform } from '../services/hostApp.service'
import { ConfigService } from '../services/config.service'
/** @hidden */ /** @hidden */
export interface SortableComponentProxy { export interface SortableComponentProxy {
setDragHandle (_: HTMLElement) setDragHandle: (_: HTMLElement) => void
} }
/** @hidden */ /** @hidden */
@@ -31,6 +33,7 @@ export class TabHeaderComponent {
private constructor ( private constructor (
public app: AppService, public app: AppService,
public config: ConfigService,
private electron: ElectronService, private electron: ElectronService,
private hostApp: HostAppService, private hostApp: HostAppService,
private ngbModal: NgbModal, private ngbModal: NgbModal,
@@ -69,8 +72,8 @@ export class TabHeaderComponent {
}).catch(() => null) }).catch(() => null)
} }
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> { async buildContextMenu (): Promise<MenuItemConstructorOptions[]> {
let items: Electron.MenuItemConstructorOptions[] = [] let items: MenuItemConstructorOptions[] = []
for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this.tab, this)))) { for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this.tab, this)))) {
items.push({ type: 'separator' }) items.push({ type: 'separator' })
items = items.concat(section) items = items.concat(section)

View File

@@ -9,18 +9,25 @@
.form-line .form-line
.header .header
.title Enable analytics .title Enable analytics
.description Help us track the number of Terminus installs across the world! .description Help track the number of Terminus installs across the world!
toggle([(ngModel)]='config.store.enableAnalytics') toggle([(ngModel)]='config.store.enableAnalytics')
.form-line .form-line
.header .header
.title Enable SSH plugin .title Enable global hotkey (#[strong Ctrl-Space])
.description Toggles the Terminus window visibility
toggle([(ngModel)]='enableGlobalHotkey')
.form-line
.header
.title Enable #[strong SSH] plugin
.description Adds an SSH connection manager UI to Terminus .description Adds an SSH connection manager UI to Terminus
toggle([(ngModel)]='enableSSH') toggle([(ngModel)]='enableSSH')
.form-line .form-line
.header .header
.title Enable Serial plugin .title Enable #[strong Serial] plugin
.description Allows attaching Terminus to serial ports .description Allows attaching Terminus to serial ports
toggle([(ngModel)]='enableSerial') toggle([(ngModel)]='enableSerial')

View File

@@ -13,6 +13,7 @@ import { HostAppService } from '../services/hostApp.service'
export class WelcomeTabComponent extends BaseTabComponent { export class WelcomeTabComponent extends BaseTabComponent {
enableSSH = false enableSSH = false
enableSerial = false enableSerial = false
enableGlobalHotkey = true
constructor ( constructor (
private hostApp: HostAppService, private hostApp: HostAppService,
@@ -33,6 +34,9 @@ export class WelcomeTabComponent extends BaseTabComponent {
if (!this.enableSerial) { if (!this.enableSerial) {
this.config.store.pluginBlacklist.push('serial') this.config.store.pluginBlacklist.push('serial')
} }
if (!this.enableGlobalHotkey) {
this.config.store.hotkeys['toggle-window'] = []
}
this.config.save() this.config.save()
this.hostApp.getWindow().reload() this.hostApp.getWindow().reload()
} }

View File

@@ -12,6 +12,7 @@ button {
padding: 0; padding: 0;
line-height: 0; line-height: 0;
text-align: center; text-align: center;
align-items: center;
&:not(:hover):not(:active) { &:not(:hover):not(:active) {
background: transparent; background: transparent;

View File

@@ -97,7 +97,7 @@ export class ConfigService {
private changed = new Subject<void>() private changed = new Subject<void>()
private _store: any private _store: any
private defaults: any private defaults: any
private servicesCache: { [id: string]: Function[] }|null = null private servicesCache: Record<string, Function[]>|null = null // eslint-disable-line @typescript-eslint/ban-types
get changed$ (): Observable<void> { return this.changed } get changed$ (): Observable<void> { return this.changed }
@@ -159,7 +159,7 @@ export class ConfigService {
this._store = JSON.parse(JSON.stringify(this._store)) this._store = JSON.parse(JSON.stringify(this._store))
fs.writeFileSync(this.path, yaml.safeDump(this._store), 'utf8') fs.writeFileSync(this.path, yaml.safeDump(this._store), 'utf8')
this.emitChange() this.emitChange()
this.hostApp.broadcastConfigChange(this.store) this.hostApp.broadcastConfigChange(JSON.parse(JSON.stringify(this.store)))
} }
/** /**
@@ -189,15 +189,15 @@ export class ConfigService {
* *
* @typeparam T Base provider type * @typeparam T Base provider type
*/ */
enabledServices<T extends object> (services: T[]): T[] { enabledServices<T extends object> (services: T[]): T[] { // eslint-disable-line @typescript-eslint/ban-types
if (!this.servicesCache) { if (!this.servicesCache) {
this.servicesCache = {} this.servicesCache = {}
const ngModule = window['rootModule'].ɵinj const ngModule = window['rootModule'].ɵinj
for (const imp of ngModule.imports) { for (const imp of ngModule.imports) {
const module = imp['ngModule'] || imp const module = imp.ngModule || imp
if (module.ɵinj?.providers) { if (module.ɵinj?.providers) {
this.servicesCache[module['pluginName']] = module.ɵinj.providers.map(provider => { this.servicesCache[module.pluginName] = module.ɵinj.providers.map(provider => {
return provider['useClass'] || provider return provider.useClass || provider
}) })
} }
} }

View File

@@ -1,3 +1,4 @@
import type { Display } from 'electron'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { ConfigService } from '../services/config.service' import { ConfigService } from '../services/config.service'
import { ElectronService } from '../services/electron.service' import { ElectronService } from '../services/electron.service'
@@ -11,8 +12,8 @@ export class DockingService {
private config: ConfigService, private config: ConfigService,
private hostApp: HostAppService, private hostApp: HostAppService,
) { ) {
electron.screen.on('display-removed', () => this.repositionWindow()) hostApp.displaysChanged$.subscribe(() => this.repositionWindow())
electron.screen.on('display-metrics-changed', () => this.repositionWindow()) hostApp.displayMetricsChanged$.subscribe(() => this.repositionWindow())
} }
dock (): void { dock (): void {
@@ -61,11 +62,11 @@ export class DockingService {
}) })
} }
getCurrentScreen (): Electron.Display { getCurrentScreen (): Display {
return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint()) return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint())
} }
getScreens (): Electron.Display[] { getScreens (): Display[] {
const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id
return this.electron.screen.getAllDisplays().sort((a, b) => return this.electron.screen.getAllDisplays().sort((a, b) =>
a.bounds.x === b.bounds.x ? a.bounds.y - b.bounds.y : a.bounds.x - b.bounds.x a.bounds.x === b.bounds.x ? a.bounds.y - b.bounds.y : a.bounds.x - b.bounds.x

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { TouchBar, BrowserWindow, Menu, MenuItem, NativeImage } from 'electron' import { App, IpcRenderer, Shell, Dialog, Clipboard, GlobalShortcut, Screen, Remote, AutoUpdater, TouchBar, BrowserWindow, Menu, MenuItem, NativeImage, MessageBoxOptions } from 'electron'
export interface MessageBoxResponse { export interface MessageBoxResponse {
response: number response: number
@@ -8,16 +8,16 @@ export interface MessageBoxResponse {
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ElectronService { export class ElectronService {
app: Electron.App app: App
ipcRenderer: Electron.IpcRenderer ipcRenderer: IpcRenderer
shell: Electron.Shell shell: Shell
dialog: Electron.Dialog dialog: Dialog
clipboard: Electron.Clipboard clipboard: Clipboard
globalShortcut: Electron.GlobalShortcut globalShortcut: GlobalShortcut
nativeImage: typeof NativeImage nativeImage: typeof NativeImage
screen: Electron.Screen screen: Screen
remote: Electron.Remote remote: Remote
autoUpdater: Electron.AutoUpdater autoUpdater: AutoUpdater
TouchBar: typeof TouchBar TouchBar: typeof TouchBar
BrowserWindow: typeof BrowserWindow BrowserWindow: typeof BrowserWindow
Menu: typeof Menu Menu: typeof Menu
@@ -44,8 +44,8 @@ export class ElectronService {
} }
async showMessageBox ( async showMessageBox (
browserWindow: Electron.BrowserWindow, browserWindow: BrowserWindow,
options: Electron.MessageBoxOptions options: MessageBoxOptions
): Promise<MessageBoxResponse> { ): Promise<MessageBoxResponse> {
return this.dialog.showMessageBox(browserWindow, options) return this.dialog.showMessageBox(browserWindow, options)
} }

View File

@@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'
import { ElectronService } from './electron.service' import { ElectronService } from './electron.service'
import { ConfigService } from './config.service' import { ConfigService } from './config.service'
import * as mixpanel from 'mixpanel' import * as mixpanel from 'mixpanel'
import { v4 as uuidv4 } from 'uuid/v4' import { v4 as uuidv4 } from 'uuid'
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class HomeBaseService { export class HomeBaseService {
@@ -58,7 +58,7 @@ export class HomeBaseService {
getAnalyticsProperties (): Record<string, string> { getAnalyticsProperties (): Record<string, string> {
return { return {
distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase distinct_id: window.localStorage.analyticsUserID,
platform: process.platform, platform: process.platform,
os: os.release(), os: os.release(),
version: this.appVersion, version: this.appVersion,

View File

@@ -1,13 +1,16 @@
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
import * as path from 'path' import * as path from 'path'
import shellEscape from 'shell-escape' import shellEscape from 'shell-escape'
import { Observable, Subject } from 'rxjs' import { Observable, Subject } from 'rxjs'
import { Injectable, NgZone, EventEmitter } from '@angular/core' import { Injectable, NgZone, EventEmitter } from '@angular/core'
import { ElectronService } from './electron.service' import { ElectronService } from './electron.service'
import { Logger, LogService } from './log.service' import { Logger, LogService } from './log.service'
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils' import { isWindowsBuild, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
export enum Platform { export enum Platform {
Linux, macOS, Windows, Linux = 'Linux',
macOS = 'macOS',
Windows = 'Windows',
} }
export interface Bounds { export interface Bounds {
@@ -42,6 +45,7 @@ export class HostAppService {
private windowMoved = new Subject<void>() private windowMoved = new Subject<void>()
private windowFocused = new Subject<void>() private windowFocused = new Subject<void>()
private displayMetricsChanged = new Subject<void>() private displayMetricsChanged = new Subject<void>()
private displaysChanged = new Subject<void>()
private logger: Logger private logger: Logger
private windowId: number private windowId: number
@@ -91,6 +95,8 @@ export class HostAppService {
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged } get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
get displaysChanged$ (): Observable<void> { return this.displaysChanged }
private constructor ( private constructor (
private zone: NgZone, private zone: NgZone,
private electron: ElectronService, private electron: ElectronService,
@@ -140,6 +146,10 @@ export class HostAppService {
this.zone.run(() => this.displayMetricsChanged.next()) this.zone.run(() => this.displayMetricsChanged.next())
}) })
electron.ipcRenderer.on('host:displays-changed', () => {
this.zone.run(() => this.displaysChanged.next())
})
electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => { electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => {
this.logger.info('Second instance', argv) this.logger.info('Second instance', argv)
const op = argv._[0] const op = argv._[0]
@@ -166,10 +176,7 @@ export class HostAppService {
this.configChangeBroadcast.next() this.configChangeBroadcast.next()
})) }))
if ( if (isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED) &&
!isWindowsBuild(WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED)
) {
electron.ipcRenderer.send('window-set-disable-vibrancy-while-dragging', true) electron.ipcRenderer.send('window-set-disable-vibrancy-while-dragging', true)
} }
} }
@@ -177,8 +184,8 @@ export class HostAppService {
/** /**
* Returns the current remote [[BrowserWindow]] * Returns the current remote [[BrowserWindow]]
*/ */
getWindow (): Electron.BrowserWindow { getWindow (): BrowserWindow {
return this.electron.BrowserWindow.fromId(this.windowId) return this.electron.BrowserWindow.fromId(this.windowId)!
} }
newWindow (): void { newWindow (): void {
@@ -239,18 +246,18 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-set-title', title) this.electron.ipcRenderer.send('window-set-title', title)
} }
setTouchBar (touchBar: Electron.TouchBar): void { setTouchBar (touchBar: TouchBar): void {
this.getWindow().setTouchBar(touchBar) this.getWindow().setTouchBar(touchBar)
} }
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]): void { popupContextMenu (menuDefinition: MenuItemConstructorOptions[]): void {
this.electron.Menu.buildFromTemplate(menuDefinition).popup({}) this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
} }
/** /**
* Notifies other windows of config file changes * Notifies other windows of config file changes
*/ */
broadcastConfigChange (configStore: {[k: string]: any}): void { broadcastConfigChange (configStore: Record<string, any>): void {
this.electron.ipcRenderer.send('app:config-change', configStore) this.electron.ipcRenderer.send('app:config-change', configStore)
} }

View File

@@ -189,6 +189,7 @@ export class HotkeysService {
try { try {
let electronKeySpec = item[0] let electronKeySpec = item[0]
electronKeySpec = electronKeySpec.replace('Meta', 'Super')
electronKeySpec = electronKeySpec.replace('⌘', 'Command') electronKeySpec = electronKeySpec.replace('⌘', 'Command')
electronKeySpec = electronKeySpec.replace('⌥', 'Alt') electronKeySpec = electronKeySpec.replace('⌥', 'Alt')
electronKeySpec = electronKeySpec.replace(/-/g, '+') electronKeySpec = electronKeySpec.replace(/-/g, '+')

View File

@@ -28,7 +28,7 @@ const initializeWinston = (electron: ElectronService) => {
export class Logger { export class Logger {
constructor ( constructor (
private winstonLogger: any, private winstonLogger: winston.Logger,
private name: string, private name: string,
) {} ) {}
@@ -62,7 +62,7 @@ export class Logger {
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class LogService { export class LogService {
private log: any private log: winston.Logger
/** @hidden */ /** @hidden */
private constructor (electron: ElectronService) { private constructor (electron: ElectronService) {

View File

@@ -44,7 +44,7 @@ export class ShellIntegrationService {
'extras', 'extras',
'automator-workflows', 'automator-workflows',
) )
this.automatorWorkflowsDestination = path.join(process.env.HOME as string, 'Library', 'Services') this.automatorWorkflowsDestination = path.join(process.env.HOME!, 'Library', 'Services')
} }
this.updatePaths() this.updatePaths()
} }

View File

@@ -1,5 +1,5 @@
import { NativeImage, SegmentedControlSegment, TouchBarSegmentedControl } from 'electron'
import { Injectable, Inject, NgZone } from '@angular/core' import { Injectable, Inject, NgZone } from '@angular/core'
import { TouchBarSegmentedControl, SegmentedControlSegment } from 'electron'
import { AppService } from './app.service' import { AppService } from './app.service'
import { ConfigService } from './config.service' import { ConfigService } from './config.service'
import { ElectronService } from './electron.service' import { ElectronService } from './electron.service'
@@ -12,7 +12,7 @@ export class TouchbarService {
private tabsSegmentedControl: TouchBarSegmentedControl private tabsSegmentedControl: TouchBarSegmentedControl
private buttonsSegmentedControl: TouchBarSegmentedControl private buttonsSegmentedControl: TouchBarSegmentedControl
private tabSegments: SegmentedControlSegment[] = [] private tabSegments: SegmentedControlSegment[] = []
private nsImageCache: {[id: string]: Electron.NativeImage} = {} private nsImageCache: Record<string, NativeImage> = {}
private constructor ( private constructor (
private app: AppService, private app: AppService,
@@ -100,7 +100,7 @@ export class TouchbarService {
this.hostApp.setTouchBar(touchBar) this.hostApp.setTouchBar(touchBar)
} }
private getButton (button: ToolbarButton): Electron.SegmentedControlSegment { private getButton (button: ToolbarButton): SegmentedControlSegment {
return { return {
label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle || button.title), label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle || button.title),
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : undefined, icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : undefined,

View File

@@ -1,14 +1,9 @@
import axios from 'axios' import axios from 'axios'
import * as fs from 'fs'
import os from 'os'
import { spawn } from 'mz/child_process'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { Logger, LogService } from './log.service' import { Logger, LogService } from './log.service'
import { ElectronService } from './electron.service' import { ElectronService } from './electron.service'
import { ConfigService } from './config.service' import { ConfigService } from './config.service'
import { AppUpdater } from 'electron-updater'
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest' const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
@@ -19,7 +14,6 @@ export class UpdaterService {
private downloaded: Promise<boolean> private downloaded: Promise<boolean>
private electronUpdaterAvailable = true private electronUpdaterAvailable = true
private updateURL: string private updateURL: string
private autoUpdater: AppUpdater
private constructor ( private constructor (
log: LogService, log: LogService,
@@ -33,26 +27,25 @@ export class UpdaterService {
return return
} }
this.autoUpdater = electron.remote.require('electron-updater').autoUpdater electron.autoUpdater.on('update-available', () => {
this.autoUpdater.autoInstallOnAppQuit = !!config.store.enableAutomaticUpdates
this.autoUpdater.on('update-available', () => {
this.logger.info('Update available') this.logger.info('Update available')
this.autoUpdater.downloadUpdate()
}) })
this.autoUpdater.once('update-not-available', () => {
electron.autoUpdater.once('update-not-available', () => {
this.logger.info('No updates') this.logger.info('No updates')
}) })
this.downloaded = new Promise<boolean>(resolve => { this.downloaded = new Promise<boolean>(resolve => {
this.autoUpdater.once('update-downloaded', () => resolve(true)) electron.autoUpdater.once('update-downloaded', () => resolve(true))
}) })
if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) { if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
this.logger.debug('Checking for updates') this.logger.debug('Checking for updates')
try { try {
this.autoUpdater.checkForUpdates() electron.autoUpdater.setFeedURL({
url: `https://update.electronjs.org/eugeny/terminus/${process.platform}-${process.arch}/${electron.app.getVersion()}`,
})
electron.autoUpdater.checkForUpdates()
} catch (e) { } catch (e) {
this.electronUpdaterAvailable = false this.electronUpdaterAvailable = false
this.logger.info('Electron updater unavailable, falling back', e) this.logger.info('Electron updater unavailable, falling back', e)
@@ -83,22 +76,9 @@ export class UpdaterService {
async update (): Promise<void> { async update (): Promise<void> {
if (!this.electronUpdaterAvailable) { if (!this.electronUpdaterAvailable) {
this.electron.shell.openExternal(this.updateURL) this.electron.shell.openExternal(this.updateURL)
} else {
if (process.platform === 'win32') {
let downloadpath = await this.autoUpdater.downloadUpdate()
fs.exists(downloadpath[0], (exists) => {
if (exists) {
fs.copyFile(downloadpath[0], os.tmpdir() + 'terminus-installer-temp.exe', (err) => {
if (!err) {
spawn(os.tmpdir() + 'terminus-installer-temp.exe', ['--force-run'], { detached: true, stdio: 'ignore' })
}
})
}
})
} else { } else {
await this.downloaded await this.downloaded
this.autoUpdater.quitAndInstall(false, true) this.electron.autoUpdater.quitAndInstall()
}
} }
} }
} }

View File

@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import type { MenuItemConstructorOptions } from 'electron'
import { Injectable, NgZone } from '@angular/core' import { Injectable, NgZone } from '@angular/core'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
import { AppService } from './services/app.service' import { AppService } from './services/app.service'
@@ -10,7 +11,7 @@ import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
/** @hidden */ /** @hidden */
@Injectable() @Injectable()
export class TabManagementContextMenu extends TabContextMenuItemProvider { export class TabManagementContextMenu extends TabContextMenuItemProvider {
weight = -5 weight = 99
constructor ( constructor (
private app: AppService, private app: AppService,
@@ -19,8 +20,8 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
super() super()
} }
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> { async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
let items: Electron.MenuItemConstructorOptions[] = [ let items: MenuItemConstructorOptions[] = [
{ {
label: 'Close', label: 'Close',
click: () => this.zone.run(() => { click: () => this.zone.run(() => {
@@ -75,7 +76,7 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
click: () => this.zone.run(() => { click: () => this.zone.run(() => {
(tab.parent as SplitTabComponent).splitTab(tab, dir) (tab.parent as SplitTabComponent).splitTab(tab, dir)
}), }),
})) as Electron.MenuItemConstructorOptions[], })) as MenuItemConstructorOptions[],
}) })
} }
} }
@@ -105,8 +106,8 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
super() super()
} }
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> { async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
let items: Electron.MenuItemConstructorOptions[] = [] let items: MenuItemConstructorOptions[] = []
if (tabHeader) { if (tabHeader) {
items = [ items = [
...items, ...items,
@@ -120,7 +121,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
}, },
{ {
label: 'Color', label: 'Color',
sublabel: COLORS.find(x => x.value === tab.color)!.name, sublabel: COLORS.find(x => x.value === tab.color)?.name,
submenu: COLORS.map(color => ({ submenu: COLORS.map(color => ({
label: color.name, label: color.name,
type: 'radio', type: 'radio',
@@ -128,7 +129,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
click: () => this.zone.run(() => { click: () => this.zone.run(() => {
tab.color = color.value tab.color = color.value
}), }),
})) as Electron.MenuItemConstructorOptions[], })) as MenuItemConstructorOptions[],
}, },
] ]
} }
@@ -146,9 +147,9 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
super() super()
} }
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> { async getItems (tab: BaseTabComponent): Promise<MenuItemConstructorOptions[]> {
const process = await tab.getCurrentProcess() const process = await tab.getCurrentProcess()
let items: Electron.MenuItemConstructorOptions[] = [] const items: MenuItemConstructorOptions[] = []
const extTab: (BaseTabComponent & { __completionNotificationEnabled?: boolean, __outputNotificationSubscription?: Subscription|null }) = tab const extTab: (BaseTabComponent & { __completionNotificationEnabled?: boolean, __outputNotificationSubscription?: Subscription|null }) = tab

View File

@@ -6,7 +6,8 @@ app-root {
.btn-tab-bar { .btn-tab-bar {
line-height: 29px !important; line-height: 29px !important;
height: 27px !important;
align-items: center;
svg { svg {
height: 14px; height: 14px;
} }

View File

@@ -137,7 +137,7 @@ app-root {
.btn-tab-bar { .btn-tab-bar {
background: transparent; background: transparent;
line-height: 42px; line-height: 42px;
align-items: center;
svg, path { svg, path {
fill: $black; fill: $black;
fill-opacity: 0.75; fill-opacity: 0.75;

View File

@@ -29,7 +29,7 @@ body {
background: $body-bg; background: $body-bg;
&.vibrant { &.vibrant {
background: rgba(0,0,0,.4); background: rgba(0,0,0,.65);
} }
} }
@@ -358,6 +358,7 @@ search-panel {
.btn-secondary:not(:disabled):not(.disabled) { .btn-secondary:not(:disabled):not(.disabled) {
&.active, &:active { &.active, &:active {
background: #191e23; background: #191e23;
align-items: center;
} }
} }

View File

@@ -4,7 +4,6 @@ export const WIN_BUILD_CONPTY_SUPPORTED = 17692
export const WIN_BUILD_CONPTY_STABLE = 18309 export const WIN_BUILD_CONPTY_STABLE = 18309
export const WIN_BUILD_WSL_EXE_DISTRO_FLAG = 17763 export const WIN_BUILD_WSL_EXE_DISTRO_FLAG = 17763
export const WIN_BUILD_FLUENT_BG_SUPPORTED = 17063 export const WIN_BUILD_FLUENT_BG_SUPPORTED = 17063
export const WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED = 18917
export function isWindowsBuild (build: number): boolean { export function isWindowsBuild (build: number): boolean {
return process.platform === 'win32' && parseFloat(os.release()) >= 10 && parseInt(os.release().split('.')[2]) >= build return process.platform === 'win32' && parseFloat(os.release()) >= 10 && parseInt(os.release().split('.')[2]) >= build

View File

@@ -4,7 +4,7 @@ module.exports = {
target: 'node', target: 'node',
entry: 'src/index.ts', entry: 'src/index.ts',
context: __dirname, context: __dirname,
devtool: 'eval-cheap-module-source-map', devtool: 'cheap-module-source-map',
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'index.js', filename: 'index.js',

View File

@@ -2,22 +2,24 @@
# yarn lockfile v1 # yarn lockfile v1
"@types/js-yaml@^3.9.0": "@dabh/diagnostics@^2.0.2":
version "3.12.3" version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.3.tgz#abf383c5b639d0aa8b8c4a420d6a85f703357d6c" resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
integrity sha512-otRe77JNNWzoVGLKw8TCspKswRoQToys4tuL6XYVBFxjgeM0RUrx7m3jkaTdxILxeGry3zM8mGYkGXMeQ02guA== integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==
"@types/node@*":
version "13.7.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.1.tgz#238eb34a66431b71d2aaddeaa7db166f25971a0d"
integrity sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA==
"@types/semver@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408"
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==
dependencies: dependencies:
"@types/node" "*" colorspace "1.1.x"
enabled "2.0.x"
kuler "^2.0.0"
"@types/js-yaml@^3.9.0":
version "3.12.5"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.5.tgz#136d5e6a57a931e1cce6f9d8126aa98a9c92a6bb"
integrity sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww==
"@types/semver@^7.3.1":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
"@types/shell-escape@^0.2.0": "@types/shell-escape@^0.2.0":
version "0.2.0" version "0.2.0"
@@ -45,12 +47,10 @@ argparse@^1.0.7:
dependencies: dependencies:
sprintf-js "~1.0.2" sprintf-js "~1.0.2"
async@^2.6.1: async@^3.1.0:
version "2.6.2" version "3.2.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
dependencies:
lodash "^4.17.11"
at-least-node@^1.0.0: at-least-node@^1.0.0:
version "1.0.0" version "1.0.0"
@@ -65,14 +65,14 @@ axios@^0.19.0:
follow-redirects "1.5.10" follow-redirects "1.5.10"
bootstrap@^4.1.3: bootstrap@^4.1.3:
version "4.4.1" version "4.5.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA== integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==
builder-util-runtime@8.7.0: builder-util-runtime@8.7.2:
version "8.7.0" version "8.7.2"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.0.tgz#e48ad004835c8284662e8eaf47a53468c66e8e8d" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72"
integrity sha512-G1AqqVM2vYTrSFR982c1NNzwXKrGLQjVjaZaWQdn4O6Z3YKjdMDofw88aD9jpyK9ZXkrCxR0tI3Qe9wNbyTlXg== integrity sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA==
dependencies: dependencies:
debug "^4.1.1" debug "^4.1.1"
sax "^1.2.4" sax "^1.2.4"
@@ -95,9 +95,9 @@ color-name@^1.0.0:
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.5.2: color-string@^1.5.2:
version "1.5.3" version "1.5.4"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6"
integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==
dependencies: dependencies:
color-name "^1.0.0" color-name "^1.0.0"
simple-swizzle "^0.2.2" simple-swizzle "^0.2.2"
@@ -110,15 +110,10 @@ color@3.0.x:
color-convert "^1.9.1" color-convert "^1.9.1"
color-string "^1.5.2" color-string "^1.5.2"
colornames@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96"
integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=
colors@^1.2.1: colors@^1.2.1:
version "1.3.3" version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
colorspace@1.1.x: colorspace@1.1.x:
version "1.1.2" version "1.1.2"
@@ -129,9 +124,9 @@ colorspace@1.1.x:
text-hex "1.0.x" text-hex "1.0.x"
core-js@^3.1.2: core-js@^3.1.2:
version "3.6.5" version "3.7.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f"
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==
core-util-is@~1.0.0: core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
@@ -153,55 +148,39 @@ debug@^3.1.0:
ms "^2.1.1" ms "^2.1.1"
debug@^4.1.1: debug@^4.1.1:
version "4.1.1" version "4.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
dependencies: dependencies:
ms "^2.1.1" ms "2.1.2"
deepmerge@^4.1.1: deepmerge@^4.1.1:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
diagnostics@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a"
integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==
dependencies:
colorspace "1.1.x"
enabled "1.0.x"
kuler "1.0.x"
electron-updater@^4.0.6: electron-updater@^4.0.6:
version "4.3.1" version "4.3.5"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.1.tgz#9d485b6262bc56fcf7ee62b1dc1b3b105a3e96a7" resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.5.tgz#4fb36f593a031c87ea07ee141c9f064d5deffb15"
integrity sha512-UDC5AHCgeiHJYDYWZG/rsl1vdAFKqI/Lm7whN57LKAk8EfhTewhcEHzheRcncLgikMcQL8gFo1KeX51tf5a5Wg== integrity sha512-5jjN7ebvfj1cLI0VZMdCnJk6aC4bP+dy7ryBf21vArR0JzpRVk0OZHA2QBD+H5rm6ZSeDYHOY6+8PrMEqJ4wlQ==
dependencies: dependencies:
"@types/semver" "^7.1.0" "@types/semver" "^7.3.1"
builder-util-runtime "8.7.0" builder-util-runtime "8.7.2"
fs-extra "^9.0.0" fs-extra "^9.0.1"
js-yaml "^3.13.1" js-yaml "^3.14.0"
lazy-val "^1.0.4" lazy-val "^1.0.4"
lodash.isequal "^4.5.0" lodash.isequal "^4.5.0"
semver "^7.1.3" semver "^7.3.2"
enabled@1.0.x: enabled@2.0.x:
version "1.0.2" version "2.0.0"
resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93" resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M= integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
dependencies:
env-variable "0.0.x"
env-variable@0.0.x:
version "0.0.5"
resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88"
integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==
es6-promise@^4.0.3: es6-promise@^4.0.3:
version "4.2.6" version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0: es6-promisify@^5.0.0:
version "5.0.0" version "5.0.0"
@@ -216,14 +195,19 @@ esprima@^4.0.0:
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
fast-safe-stringify@^2.0.4: fast-safe-stringify@^2.0.4:
version "2.0.6" version "2.0.7"
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg== integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
fecha@^2.3.3: fecha@^4.2.0:
version "2.3.3" version "4.2.0"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41"
integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg== integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==
fn.name@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
follow-redirects@1.5.10: follow-redirects@1.5.10:
version "1.5.10" version "1.5.10"
@@ -232,10 +216,10 @@ follow-redirects@1.5.10:
dependencies: dependencies:
debug "=3.1.0" debug "=3.1.0"
fs-extra@^9.0.0: fs-extra@^9.0.1:
version "9.0.0" version "9.0.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc"
integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g== integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==
dependencies: dependencies:
at-least-node "^1.0.0" at-least-node "^1.0.0"
graceful-fs "^4.2.0" graceful-fs "^4.2.0"
@@ -243,9 +227,9 @@ fs-extra@^9.0.0:
universalify "^1.0.0" universalify "^1.0.0"
graceful-fs@^4.1.6, graceful-fs@^4.2.0: graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.2" version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
https-proxy-agent@3.0.0: https-proxy-agent@3.0.0:
version "3.0.0" version "3.0.0"
@@ -256,48 +240,46 @@ https-proxy-agent@3.0.0:
debug "^3.1.0" debug "^3.1.0"
inherits@^2.0.3, inherits@~2.0.3: inherits@^2.0.3, inherits@~2.0.3:
version "2.0.3" version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-arrayish@^0.3.1: is-arrayish@^0.3.1:
version "0.3.2" version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-stream@^1.1.0: is-stream@^2.0.0:
version "1.1.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
isarray@~1.0.0: isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
js-yaml@^3.13.1, js-yaml@^3.9.0: js-yaml@^3.14.0, js-yaml@^3.9.0:
version "3.13.1" version "3.14.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
dependencies: dependencies:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
jsonfile@^6.0.1: jsonfile@^6.0.1:
version "6.0.1" version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies: dependencies:
universalify "^1.0.0" universalify "^2.0.0"
optionalDependencies: optionalDependencies:
graceful-fs "^4.1.6" graceful-fs "^4.1.6"
kuler@1.0.x: kuler@^2.0.0:
version "1.0.1" version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6" resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ== integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
dependencies:
colornames "^1.1.1"
lazy-val@^1.0.4: lazy-val@^1.0.4:
version "1.0.4" version "1.0.4"
@@ -309,19 +291,14 @@ lodash.isequal@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash@^4.17.11: logform@^2.2.0:
version "4.17.14" version "2.2.0"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==
logform@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360"
integrity sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==
dependencies: dependencies:
colors "^1.2.1" colors "^1.2.1"
fast-safe-stringify "^2.0.4" fast-safe-stringify "^2.0.4"
fecha "^2.3.3" fecha "^4.2.0"
ms "^2.1.1" ms "^2.1.1"
triple-beam "^1.3.0" triple-beam "^1.3.0"
@@ -337,7 +314,7 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1: ms@2.1.2, ms@^2.1.1:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
@@ -355,25 +332,27 @@ ngx-perfect-scrollbar@^8.0.0:
perfect-scrollbar "^1.4.0" perfect-scrollbar "^1.4.0"
resize-observer-polyfill "^1.5.0" resize-observer-polyfill "^1.5.0"
one-time@0.0.4: one-time@^1.0.0:
version "0.0.4" version "1.0.0"
resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e" resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4= integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
dependencies:
fn.name "1.x.x"
perfect-scrollbar@^1.4.0: perfect-scrollbar@^1.4.0:
version "1.4.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.4.0.tgz#5d014ef9775e1f43058a1dbae9ed1daf0e7091f1" resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.0.tgz#821d224ed8ff61990c23f26db63048cdc75b6b83"
integrity sha512-/2Sk/khljhdrsamjJYS5NjrH+GKEHEwh7zFSiYyxROyYKagkE4kSn2zDQDRTOMo8mpT2jikxx6yI1dG7lNP/hw== integrity sha512-NrNHJn5mUGupSiheBTy6x+6SXCFbLlm8fVZh9moIzw/LgqElN5q4ncR4pbCBCYuCJ8Kcl9mYM0NgDxvW+b4LxA==
process-nextick-args@~2.0.0: process-nextick-args@~2.0.0:
version "2.0.0" version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
readable-stream@^2.3.6: readable-stream@2.3.7, readable-stream@^2.3.7:
version "2.3.6" version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
dependencies: dependencies:
core-util-is "~1.0.0" core-util-is "~1.0.0"
inherits "~2.0.3" inherits "~2.0.3"
@@ -383,10 +362,10 @@ readable-stream@^2.3.6:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readable-stream@^3.1.1: readable-stream@^3.4.0:
version "3.3.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw== integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies: dependencies:
inherits "^2.0.3" inherits "^2.0.3"
string_decoder "^1.1.1" string_decoder "^1.1.1"
@@ -402,15 +381,20 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
sax@^1.2.4: sax@^1.2.4:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
semver@^7.1.3: semver@^7.3.2:
version "7.1.3" version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA== integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
shell-escape@^0.2.0: shell-escape@^0.2.0:
version "0.2.0" version "0.2.0"
@@ -435,11 +419,11 @@ stack-trace@0.0.x:
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
string_decoder@^1.1.1: string_decoder@^1.1.1:
version "1.2.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies: dependencies:
safe-buffer "~5.1.0" safe-buffer "~5.2.0"
string_decoder@~1.1.1: string_decoder@~1.1.1:
version "1.1.1" version "1.1.1"
@@ -463,35 +447,40 @@ universalify@^1.0.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
util-deprecate@^1.0.1, util-deprecate@~1.0.1: util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
uuid@^8.0.0: uuid@^8.0.0:
version "8.0.0" version "8.3.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
winston-transport@^4.3.0: winston-transport@^4.4.0:
version "4.3.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.3.0.tgz#df68c0c202482c448d9b47313c07304c2d7c2c66" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
integrity sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A== integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
dependencies: dependencies:
readable-stream "^2.3.6" readable-stream "^2.3.7"
triple-beam "^1.2.0" triple-beam "^1.2.0"
winston@*, winston@^3.2.1: winston@*, winston@^3.3.3:
version "3.2.1" version "3.3.3"
resolved "https://registry.yarnpkg.com/winston/-/winston-3.2.1.tgz#63061377976c73584028be2490a1846055f77f07" resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
integrity sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw== integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
dependencies: dependencies:
async "^2.6.1" "@dabh/diagnostics" "^2.0.2"
diagnostics "^1.1.1" async "^3.1.0"
is-stream "^1.1.0" is-stream "^2.0.0"
logform "^2.1.1" logform "^2.2.0"
one-time "0.0.4" one-time "^1.0.0"
readable-stream "^3.1.1" readable-stream "^3.4.0"
stack-trace "0.0.x" stack-trace "0.0.x"
triple-beam "^1.3.0" triple-beam "^1.3.0"
winston-transport "^4.3.0" winston-transport "^4.4.0"

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-plugin-manager", "name": "terminus-plugin-manager",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "Terminus' plugin manager", "description": "Terminus' plugin manager",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -23,12 +23,12 @@
"semver": "^7.1.1" "semver": "^7.1.1"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^7", "@angular/common": "^9.1.11",
"@angular/core": "^7", "@angular/core": "^9.1.9",
"@angular/forms": "^7", "@angular/forms": "^9.1.11",
"@angular/platform-browser": "^7", "@angular/platform-browser": "^9.1.11",
"@ng-bootstrap/ng-bootstrap": "^1", "@ng-bootstrap/ng-bootstrap": "^6.1.0",
"rxjs": "^5", "rxjs": "^6.5.5",
"terminus-core": "*", "terminus-core": "*",
"terminus-settings": "*" "terminus-settings": "*"
} }

View File

@@ -7,7 +7,7 @@ import { Component, Input } from '@angular/core'
import { ConfigService, ElectronService } from 'terminus-core' import { ConfigService, ElectronService } from 'terminus-core'
import { PluginInfo, PluginManagerService } from '../services/pluginManager.service' import { PluginInfo, PluginManagerService } from '../services/pluginManager.service'
enum BusyState { Installing, Uninstalling } enum BusyState { Installing = 'Installing', Uninstalling = 'Uninstalling' }
/** @hidden */ /** @hidden */
@Component({ @Component({
@@ -19,8 +19,8 @@ export class PluginsSettingsTabComponent {
@Input() availablePlugins$: Observable<PluginInfo[]> @Input() availablePlugins$: Observable<PluginInfo[]>
@Input() availablePluginsQuery$ = new BehaviorSubject<string>('') @Input() availablePluginsQuery$ = new BehaviorSubject<string>('')
@Input() availablePluginsReady = false @Input() availablePluginsReady = false
@Input() knownUpgrades: {[id: string]: PluginInfo|null} = {} @Input() knownUpgrades: Record<string, PluginInfo|null> = {}
@Input() busy: {[id: string]: BusyState} = {} @Input() busy: Record<string, BusyState> = {}
@Input() erroredPlugin: string @Input() erroredPlugin: string
@Input() errorMessage: string @Input() errorMessage: string
@@ -55,7 +55,7 @@ export class PluginsSettingsTabComponent {
} }
openPluginsFolder (): void { openPluginsFolder (): void {
this.electron.shell.openItem(this.pluginManager.userPluginsPath) this.electron.shell.openPath(this.pluginManager.userPluginsPath)
} }
searchAvailable (query: string) { searchAvailable (query: string) {

View File

@@ -4,7 +4,7 @@ module.exports = {
target: 'node', target: 'node',
entry: 'src/index.ts', entry: 'src/index.ts',
context: __dirname, context: __dirname,
devtool: 'eval-cheap-module-source-map', devtool: 'cheap-module-source-map',
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'index.js', filename: 'index.js',

View File

@@ -2,17 +2,10 @@
# yarn lockfile v1 # yarn lockfile v1
"@types/node@*":
version "13.7.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.6.tgz#cb734a7c191472ae6a2b3a502b4dfffcea974113"
integrity sha512-eyK7MWD0R1HqVTp+PtwRgFeIsemzuj4gBFSQxfPHY5iMjS7474e5wq+VFgTcdpyHeNxyKSaetYAjdMLJlKoWqA==
"@types/semver@^7.1.0": "@types/semver@^7.1.0":
version "7.1.0" version "7.3.4"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA== integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
dependencies:
"@types/node" "*"
any-promise@^1.0.0: any-promise@^1.0.0:
version "1.3.0" version "1.3.0"
@@ -60,9 +53,9 @@ object-assign@^4.0.1:
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
semver@^7.1.1: semver@^7.1.1:
version "7.2.2" version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.2.2.tgz#d01432d74ed3010a20ffaf909d63a691520521cd" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-Zo84u6o2PebMSK3zjJ6Zp5wi8VnQZnEaCP13Ul/lt1ANsLACxnJxq4EEm1PY94/por1Hm9+7xpIswdS5AkieMA== integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
thenify-all@^1.0.0: thenify-all@^1.0.0:
version "1.6.0" version "1.6.0"
@@ -72,8 +65,8 @@ thenify-all@^1.0.0:
thenify ">= 3.1.0 < 4" thenify ">= 3.1.0 < 4"
"thenify@>= 3.1.0 < 4": "thenify@>= 3.1.0 < 4":
version "3.3.0" version "3.3.1"
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
dependencies: dependencies:
any-promise "^1.0.0" any-promise "^1.0.0"

0
terminus-serial/.gitignore vendored Normal file
View File

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-serial", "name": "terminus-serial",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "Serial connection manager for Terminus", "description": "Serial connection manager for Terminus",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -17,19 +17,20 @@
"author": "Eugene Pankov", "author": "Eugene Pankov",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/node": "12.7.3", "@types/node": "14.14.14",
"@types/ssh2": "^0.5.35", "@types/ssh2": "^0.5.35",
"ansi-colors": "^4.1.1", "ansi-colors": "^4.1.1",
"cli-spinner": "^0.2.10", "cli-spinner": "^0.2.10"
"electron-rebuild": "^1.10.0",
"terminus-terminal": "^1.0.98-nightly.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^7", "@angular/animations": "^9.1.9",
"@angular/core": "^7", "@angular/common": "^9.1.11",
"@angular/forms": "^7", "@angular/core": "^9.1.9",
"@ng-bootstrap/ng-bootstrap": "^1", "@angular/forms": "^9.1.11",
"rxjs": "^5", "@angular/platform-browser": "^9.1.11",
"@angular/platform-browser-dynamic": "^9.1.11",
"@ng-bootstrap/ng-bootstrap": "^6.2.0",
"rxjs": "^6.6.3",
"terminus-core": "*", "terminus-core": "*",
"terminus-settings": "*", "terminus-settings": "*",
"terminus-terminal": "*" "terminus-terminal": "*"

View File

@@ -11,7 +11,7 @@ import { Subscription } from 'rxjs'
/** @hidden */ /** @hidden */
@Component({ @Component({
selector: 'serial-tab', selector: 'serial-tab',
template: BaseTerminalTabComponent.template + require<string>('./serialTab.component.pug'), template: BaseTerminalTabComponent.template + (require('./serialTab.component.pug') as string),
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles], styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
animations: BaseTerminalTabComponent.animations, animations: BaseTerminalTabComponent.animations,
}) })
@@ -64,7 +64,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
this.session = this.injector.get(SerialService).createSession(this.connection) this.session = this.injector.get(SerialService).createSession(this.connection)
this.session.serviceMessage$.subscribe(msg => { this.session.serviceMessage$.subscribe(msg => {
this.write('\r\n' + colors.black.bgWhite(' serial ') + ' ' + msg + '\r\n') this.write(`\r\n${colors.black.bgWhite(' serial ')} ${msg}\r\n`)
this.session.resize(this.size.columns, this.size.rows) this.session.resize(this.size.columns, this.size.rows)
}) })
this.attachSessionHandlers() this.attachSessionHandlers()

View File

@@ -11,8 +11,8 @@ export class RecoveryProvider extends TabRecoveryProvider {
return { return {
type: SerialTabComponent, type: SerialTabComponent,
options: { options: {
connection: recoveryToken['connection'], connection: recoveryToken.connection,
savedState: recoveryToken['savedState'], savedState: recoveryToken.savedState,
}, },
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-settings", "name": "terminus-settings",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "Terminus terminal settings page", "description": "Terminus terminal settings page",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -20,12 +20,13 @@
"@types/deep-equal": "1.0.1" "@types/deep-equal": "1.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^7", "@angular/animations": "^9.1.9",
"@angular/core": "^7", "@angular/common": "^9.1.11",
"@angular/forms": "^7", "@angular/core": "^9.1.9",
"@angular/platform-browser": "^7", "@angular/forms": "^9.1.11",
"@ng-bootstrap/ng-bootstrap": "^1", "@angular/platform-browser": "^9.1.11",
"rxjs": "^5", "@ng-bootstrap/ng-bootstrap": "^6.1.0",
"rxjs": "^6.5.5",
"terminus-core": "*" "terminus-core": "*"
} }
} }

View File

@@ -43,18 +43,32 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
ngbButton, ngbButton,
[value]='"top"' [value]='"top"'
) )
| On the top | Top
label.btn.btn-secondary(ngbButtonLabel) label.btn.btn-secondary(ngbButtonLabel)
input( input(
type='radio', type='radio',
ngbButton, ngbButton,
[value]='"bottom"' [value]='"bottom"'
) )
| At the bottom | Bottom
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"left"'
)
| Left
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"right"'
)
| Right
.form-line(*ngIf='hostApp.platform !== Platform.Linux') .form-line
.header .header
.title(*ngIf='hostApp.platform === Platform.Windows') Acrylic background .title(*ngIf='hostApp.platform !== Platform.macOS') Acrylic background
.title(*ngIf='hostApp.platform === Platform.macOS') Vibrancy .title(*ngIf='hostApp.platform === Platform.macOS') Vibrancy
.description Gives the window a blurred transparent background .description Gives the window a blurred transparent background
@@ -288,7 +302,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
th ID th ID
th Hotkey th Hotkey
ng-container(*ngFor='let hotkey of hotkeyDescriptions') ng-container(*ngFor='let hotkey of hotkeyDescriptions')
tr(*ngIf='!hotkeyFilter || hotkey.name.toLowerCase().includes(hotkeyFilter.toLowerCase())') tr(*ngIf='!hotkeyFilter || hotkeyFilterFn(hotkey, hotkeyFilter)')
td {{hotkey.name}} td {{hotkey.name}}
td {{hotkey.id}} td {{hotkey.id}}
td.pr-5 td.pr-5

View File

@@ -65,19 +65,15 @@ export class SettingsTabComponent extends BaseTabComponent {
const onConfigChange = () => { const onConfigChange = () => {
this.configFile = config.readRaw() this.configFile = config.readRaw()
this.padWindowControls = hostApp.platform === Platform.macOS this.padWindowControls = hostApp.platform === Platform.macOS
&& config.store.appearance.tabsLocation === 'bottom' && config.store.appearance.tabsLocation !== 'top'
} }
this.configSubscription = config.changed$.subscribe(onConfigChange) this.configSubscription = config.changed$.subscribe(onConfigChange)
onConfigChange() onConfigChange()
const onScreenChange = () => { hostApp.displaysChanged$.subscribe(() => {
this.zone.run(() => this.screens = this.docking.getScreens()) this.zone.run(() => this.screens = this.docking.getScreens())
} })
electron.screen.on('display-added', onScreenChange)
electron.screen.on('display-removed', onScreenChange)
electron.screen.on('display-metrics-changed', onScreenChange)
hotkeys.getHotkeyDescriptions().then(descriptions => { hotkeys.getHotkeyDescriptions().then(descriptions => {
this.hotkeyDescriptions = descriptions this.hotkeyDescriptions = descriptions
@@ -144,4 +140,10 @@ export class SettingsTabComponent extends BaseTabComponent {
} }
ptr[prop] = value ptr[prop] = value
} }
hotkeyFilterFn (hotkey: HotkeyDescription, query: string): boolean {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
const s = hotkey.name + (this.getHotkey(hotkey.id) || []).toString()
return s.toLowerCase().includes(query.toLowerCase())
}
} }

View File

@@ -4,7 +4,7 @@ module.exports = {
target: 'node', target: 'node',
entry: 'src/index.ts', entry: 'src/index.ts',
context: __dirname, context: __dirname,
devtool: 'eval-cheap-module-source-map', devtool: 'cheap-module-source-map',
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'index.js', filename: 'index.js',

0
terminus-ssh/.gitignore vendored Normal file
View File

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-ssh", "name": "terminus-ssh",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "SSH connection manager for Terminus", "description": "SSH connection manager for Terminus",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -9,30 +9,40 @@
"typings": "typings/index.d.ts", "typings": "typings/index.d.ts",
"scripts": { "scripts": {
"build": "webpack --progress --color", "build": "webpack --progress --color",
"watch": "webpack --progress --color --watch" "watch": "webpack --progress --color --watch",
"postinstall": "run-script-os",
"postinstall:darwin:linux": "exit",
"postinstall:win32": "xcopy /i /y node_modules\\ssh2\\util\\pagent.exe util\\"
}, },
"files": [ "files": [
"dist" "dist",
"util/pagent.exe"
], ],
"author": "Eugene Pankov", "author": "Eugene Pankov",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/node": "12.7.3", "@types/node": "14.14.14",
"@types/ssh2": "^0.5.35", "@types/ssh2": "^0.5.35",
"ansi-colors": "^4.1.1", "ansi-colors": "^4.1.1",
"cli-spinner": "^0.2.10", "cli-spinner": "^0.2.10",
"ssh2": "^0.8.2", "run-script-os": "^1.1.3",
"ssh2-streams": "^0.4.2", "ssh2": "^0.8.9",
"ssh2-streams": "Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5",
"sshpk": "^1.16.1", "sshpk": "^1.16.1",
"temp": "^0.9.1", "strip-ansi": "^6.0.0",
"terminus-terminal": "^1.0.98-nightly.0" "temp": "^0.9.1"
},
"dependencies": {
"socksv5": "^0.0.6"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^7", "@angular/animations": "^9.1.9",
"@angular/core": "^7", "@angular/common": "^9.1.11",
"@angular/forms": "^7", "@angular/core": "^9.1.9",
"@ng-bootstrap/ng-bootstrap": "^1", "@angular/forms": "^9.1.11",
"rxjs": "^5", "@angular/platform-browser": "^9.1.11",
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
"rxjs": "^6.5.5",
"terminus-core": "*", "terminus-core": "*",
"terminus-settings": "*", "terminus-settings": "*",
"terminus-terminal": "*" "terminus-terminal": "*"

View File

@@ -1,4 +1,6 @@
import colors from 'ansi-colors' import colors from 'ansi-colors'
import stripAnsi from 'strip-ansi'
import socksv5 from 'socksv5'
import { BaseSession } from 'terminus-terminal' import { BaseSession } from 'terminus-terminal'
import { Server, Socket, createServer, createConnection } from 'net' import { Server, Socket, createServer, createConnection } from 'net'
import { Client, ClientChannel } from 'ssh2' import { Client, ClientChannel } from 'ssh2'
@@ -16,7 +18,7 @@ export enum SSHAlgorithmType {
HMAC = 'hmac', HMAC = 'hmac',
KEX = 'kex', KEX = 'kex',
CIPHER = 'cipher', CIPHER = 'cipher',
HOSTKEY = 'serverHostKey' HOSTKEY = 'serverHostKey',
} }
export interface SSHConnection { export interface SSHConnection {
@@ -24,6 +26,7 @@ export interface SSHConnection {
host: string host: string
port: number port: number
user: string user: string
auth?: null|'password'|'publicKey'|'agent'|'keyboardInteractive'
password?: string password?: string
privateKey?: string privateKey?: string
group: string | null group: string | null
@@ -36,12 +39,15 @@ export interface SSHConnection {
skipBanner?: boolean skipBanner?: boolean
disableDynamicTitle?: boolean disableDynamicTitle?: boolean
jumpHost?: string jumpHost?: string
agentForward?: boolean
algorithms?: {[t: string]: string[]} warnOnClose?: boolean
algorithms?: Record<string, string[]>
} }
export enum PortForwardType { export enum PortForwardType {
Local, Remote Local = 'Local',
Remote = 'Remote',
Dynamic = 'Dynamic',
} }
export class ForwardedPort { export class ForwardedPort {
@@ -53,13 +59,40 @@ export class ForwardedPort {
private listener: Server private listener: Server
async startLocalListener (callback: (Socket) => void): Promise<void> { async startLocalListener (callback: (accept: () => Socket, reject: () => void, sourceAddress: string|null, sourcePort: number|null, targetAddress: string, targetPort: number) => void): Promise<void> {
this.listener = createServer(callback) if (this.type === PortForwardType.Local) {
this.listener = createServer(s => callback(
() => s,
() => s.destroy(),
s.remoteAddress ?? null,
s.remotePort ?? null,
this.targetAddress,
this.targetPort,
))
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.listener.listen(this.port, '127.0.0.1') this.listener.listen(this.port, this.host)
this.listener.on('error', reject) this.listener.on('error', reject)
this.listener.on('listening', resolve) this.listener.on('listening', resolve)
}) })
} else if (this.type === PortForwardType.Dynamic) {
return new Promise((resolve, reject) => {
this.listener = socksv5.createServer((info, accept, reject) => {
callback(
() => accept(true),
() => reject(),
null,
null,
info.dstAddr,
info.dstPort,
)
})
this.listener.on('error', reject)
this.listener.listen(this.port, this.host, resolve)
;(this.listener as any).useAuth(socksv5.auth.None())
})
} else {
throw new Error('Invalid forward type for a local listener')
}
} }
stopLocalListener (): void { stopLocalListener (): void {
@@ -69,8 +102,10 @@ export class ForwardedPort {
toString (): string { toString (): string {
if (this.type === PortForwardType.Local) { if (this.type === PortForwardType.Local) {
return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}` return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}`
} else { } if (this.type === PortForwardType.Remote) {
return `(remote) ${this.host}:${this.port} → (local) ${this.targetAddress}:${this.targetPort}` return `(remote) ${this.host}:${this.port} → (local) ${this.targetAddress}:${this.targetPort}`
} else {
return `(dynamic) ${this.host}:${this.port}`
} }
} }
} }
@@ -105,6 +140,7 @@ export class SSHSession extends BaseSession {
this.shell = await this.openShellChannel({ x11: this.connection.x11 }) this.shell = await this.openShellChannel({ x11: this.connection.x11 })
} catch (err) { } catch (err) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected opening a shell channel: ${err}`) this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected opening a shell channel: ${err}`)
return
} }
this.shell.on('greeting', greeting => { this.shell.on('greeting', greeting => {
@@ -196,11 +232,11 @@ export class SSHSession extends BaseSession {
this.ssh.on('x11', (details, accept, reject) => { this.ssh.on('x11', (details, accept, reject) => {
this.logger.info(`Incoming X11 connection from ${details.srcIP}:${details.srcPort}`) this.logger.info(`Incoming X11 connection from ${details.srcIP}:${details.srcPort}`)
let displaySpec = process.env.DISPLAY || ':0' const displaySpec = process.env.DISPLAY || ':0'
this.logger.debug(`Trying display ${displaySpec}`) this.logger.debug(`Trying display ${displaySpec}`)
let xHost = displaySpec.split(':')[0] const xHost = displaySpec.split(':')[0]
let xDisplay = parseInt(displaySpec.split(':')[1].split('.')[0] || '0') const xDisplay = parseInt(displaySpec.split(':')[1].split('.')[0] || '0')
let xPort = xDisplay < 100 ? xDisplay + 6000 : xDisplay const xPort = xDisplay < 100 ? xDisplay + 6000 : xDisplay
const socket = displaySpec.startsWith('/') ? createConnection(displaySpec) : new Socket() const socket = displaySpec.startsWith('/') ? createConnection(displaySpec) : new Socket()
if (!displaySpec.startsWith('/')) { if (!displaySpec.startsWith('/')) {
@@ -229,25 +265,26 @@ export class SSHSession extends BaseSession {
emitServiceMessage (msg: string): void { emitServiceMessage (msg: string): void {
this.serviceMessage.next(msg) this.serviceMessage.next(msg)
this.logger.info(msg) this.logger.info(stripAnsi(msg))
} }
async addPortForward (fw: ForwardedPort): Promise<void> { async addPortForward (fw: ForwardedPort): Promise<void> {
if (fw.type === PortForwardType.Local) { if (fw.type === PortForwardType.Local || fw.type === PortForwardType.Dynamic) {
await fw.startLocalListener((socket: Socket) => { await fw.startLocalListener((accept, reject, sourceAddress, sourcePort, targetAddress, targetPort) => {
this.logger.info(`New connection on ${fw}`) this.logger.info(`New connection on ${fw}`)
this.ssh.forwardOut( this.ssh.forwardOut(
socket.remoteAddress || '127.0.0.1', sourceAddress || '127.0.0.1',
socket.remotePort || 0, sourcePort || 0,
fw.targetAddress, targetAddress,
fw.targetPort, targetPort,
(err, stream) => { (err, stream) => {
if (err) { if (err) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwaded connection via ${fw}: ${err}`) this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwarded connection to ${targetAddress}:${targetPort} via ${fw}: ${err}`)
socket.destroy() reject()
return return
} }
if (stream) { if (stream) {
const socket = accept()
stream.pipe(socket) stream.pipe(socket)
socket.pipe(stream) socket.pipe(stream)
stream.on('close', () => { stream.on('close', () => {
@@ -260,7 +297,7 @@ export class SSHSession extends BaseSession {
} }
) )
}).then(() => { }).then(() => {
this.emitServiceMessage(colors.bgGreen.black(' -> ') + ` Forwaded ${fw}`) this.emitServiceMessage(colors.bgGreen.black(' -> ') + ` Forwarded ${fw}`)
this.forwardedPorts.push(fw) this.forwardedPorts.push(fw)
}).catch(e => { }).catch(e => {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Failed to forward port ${fw}: ${e}`) this.emitServiceMessage(colors.bgRed.black(' X ') + ` Failed to forward port ${fw}: ${e}`)
@@ -277,13 +314,13 @@ export class SSHSession extends BaseSession {
resolve() resolve()
}) })
}) })
this.emitServiceMessage(colors.bgGreen.black(' <- ') + ` Forwaded ${fw}`) this.emitServiceMessage(colors.bgGreen.black(' <- ') + ` Forwarded ${fw}`)
this.forwardedPorts.push(fw) this.forwardedPorts.push(fw)
} }
} }
async removePortForward (fw: ForwardedPort): Promise<void> { async removePortForward (fw: ForwardedPort): Promise<void> {
if (fw.type === PortForwardType.Local) { if (fw.type === PortForwardType.Local || fw.type === PortForwardType.Dynamic) {
fw.stopLocalListener() fw.stopLocalListener()
this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw) this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw)
} }

View File

@@ -19,6 +19,7 @@
[(ngModel)]='connection.group', [(ngModel)]='connection.group',
) )
.d-flex
.form-group .form-group
label Host label Host
input.form-control( input.form-control(
@@ -42,6 +43,34 @@
) )
.form-line .form-line
.header
.title Authentication
.btn-group.w-100(
[(ngModel)]='connection.auth',
ngbRadioGroup
)
label.btn.btn-outline-secondary(ngbButtonLabel)
input(type='radio', ngbButton, [value]='null')
i.far.fa-lightbulb
.m-0 Auto
label.btn.btn-outline-secondary(ngbButtonLabel)
input(type='radio', ngbButton, [value]='"password"')
i.fas.fa-font
.m-0 Password
label.btn.btn-outline-secondary(ngbButtonLabel)
input(type='radio', ngbButton, [value]='"publicKey"')
i.fas.fa-key
.m-0 Key
label.btn.btn-outline-secondary(ngbButtonLabel)
input(type='radio', ngbButton, [value]='"agent"')
i.fas.fa-user-secret
.m-0 Agent
label.btn.btn-outline-secondary(ngbButtonLabel)
input(type='radio', ngbButton, [value]='"keyboardInteractive"')
i.far.fa-keyboard
.m-0 Interactive
.form-line(*ngIf='!connection.auth || connection.auth === "password"')
.header .header
.title Password .title Password
.description(*ngIf='!hasSavedPassword') Save a password in the keychain .description(*ngIf='!hasSavedPassword') Save a password in the keychain
@@ -53,7 +82,7 @@
i.fas.fa-trash-alt i.fas.fa-trash-alt
span Forget span Forget
.form-line .form-line(*ngIf='!connection.auth || connection.auth === "publicKey"')
.header .header
.title Private key .title Private key
.description Path to the private key file .description Path to the private key file
@@ -74,14 +103,19 @@
.header .header
.title Jump host .title Jump host
select.form-control([(ngModel)]='connection.jumpHost') select.form-control([(ngModel)]='connection.jumpHost')
option([value]='null') None option([ngValue]='null') None
option([value]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}} option([ngValue]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
.form-line .form-line
.header .header
.title X11 forwarding .title X11 forwarding
toggle([(ngModel)]='connection.x11') toggle([(ngModel)]='connection.x11')
.form-line
.header
.title Agent Forwarding
toggle([(ngModel)]='connection.agentForward')
.form-line .form-line
.header .header
.title Tab color .title Tab color

View File

@@ -15,9 +15,9 @@ export class EditConnectionModalComponent {
connection: SSHConnection connection: SSHConnection
hasSavedPassword: boolean hasSavedPassword: boolean
supportedAlgorithms: {[id: string]: string[]} = {} supportedAlgorithms: Record<string, string> = {}
defaultAlgorithms: {[id: string]: string[]} = {} defaultAlgorithms: Record<string, string[]> = {}
algorithms: {[id: string]: {[a: string]: boolean}} = {} algorithms: Record<string, Record<string, boolean>> = {}
constructor ( constructor (
public config: ConfigService, public config: ConfigService,
@@ -49,6 +49,7 @@ export class EditConnectionModalComponent {
this.hasSavedPassword = !!await this.passwordStorage.loadPassword(this.connection) this.hasSavedPassword = !!await this.passwordStorage.loadPassword(this.connection)
this.connection.algorithms = this.connection.algorithms || {} this.connection.algorithms = this.connection.algorithms || {}
this.connection.scripts = this.connection.scripts || [] this.connection.scripts = this.connection.scripts || []
this.connection.auth = this.connection.auth || null
for (const k of Object.values(SSHAlgorithmType)) { for (const k of Object.values(SSHAlgorithmType)) {
if (!this.connection.algorithms[k]) { if (!this.connection.algorithms[k]) {

View File

@@ -6,12 +6,22 @@
.list-group-item.d-flex.align-items-center(*ngFor='let fw of session.forwardedPorts') .list-group-item.d-flex.align-items-center(*ngFor='let fw of session.forwardedPorts')
strong(*ngIf='fw.type === PortForwardType.Local') Local strong(*ngIf='fw.type === PortForwardType.Local') Local
strong(*ngIf='fw.type === PortForwardType.Remote') Remote strong(*ngIf='fw.type === PortForwardType.Remote') Remote
.ml-3 {{fw.host}}:{{fw.port}} &rarr; {{fw.targetAddress}}:{{fw.targetPort}} strong(*ngIf='fw.type === PortForwardType.Dynamic') Dynamic
.ml-3 {{fw.host}}:{{fw.port}}
.ml-2 &rarr;
.ml-2(*ngIf='fw.type !== PortForwardType.Dynamic') {{fw.targetAddress}}:{{fw.targetPort}}
.ml-2(*ngIf='fw.type === PortForwardType.Dynamic') SOCKS proxy
button.btn.btn-link.ml-auto((click)='remove(fw)') button.btn.btn-link.ml-auto((click)='remove(fw)')
i.fas.fa-trash-alt.mr-2 i.fas.fa-trash-alt.mr-2
span Remove span Remove
.input-group.mb-2 .input-group.mb-2(*ngIf='newForward.type === PortForwardType.Dynamic')
input.form-control(type='text', [(ngModel)]='newForward.host')
.input-group-append
.input-group-text :
input.form-control(type='number', [(ngModel)]='newForward.port')
.input-group.mb-2(*ngIf='newForward.type !== PortForwardType.Dynamic')
input.form-control(type='text', [(ngModel)]='newForward.host') input.form-control(type='text', [(ngModel)]='newForward.host')
.input-group-append .input-group-append
.input-group-text : .input-group-text :
@@ -42,6 +52,13 @@
[value]='PortForwardType.Remote' [value]='PortForwardType.Remote'
) )
| Remote | Remote
label.btn.btn-secondary.m-0(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='PortForwardType.Dynamic'
)
| Dynamic
button.btn.btn-primary((click)='addForward()') button.btn.btn-primary((click)='addForward()')
i.fas.fa-check.mr-2 i.fas.fa-check.mr-2

View File

@@ -20,9 +20,32 @@ h3 Connections
.mr-auto .mr-auto
div {{connection.name}} div {{connection.name}}
.text-muted {{connection.host}} .text-muted {{connection.host}}
button.btn.btn-outline-info.ml-1((click)='$event.stopPropagation(); copyConnection(connection)')
i.fas.fa-copy
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteConnection(connection)') button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteConnection(connection)')
i.fas.fa-trash i.fas.fa-trash
button.btn.btn-primary((click)='createConnection()') button.btn.btn-primary((click)='createConnection()')
i.fas.fa-fw.fa-plus i.fas.fa-fw.fa-plus
span.ml-2 Add connection span.ml-2 Add connection
h3.mt-5 Options
.form-line
.header
.title Warn when closing active connections
toggle(
[(ngModel)]='config.store.ssh.warnOnClose',
(ngModelChange)='config.save()',
)
.form-line
.header
.title WinSCP path
.descriptions When WinSCP is detected, you can launch an SCP session from the context menu.
input.form-control(
type='text',
placeholder='Auto-detect',
[(ngModel)]='config.store.ssh.winSCPPath',
(ngModelChange)='config.save()',
)

View File

@@ -14,7 +14,7 @@ import { PromptModalComponent } from './promptModal.component'
export class SSHSettingsTabComponent { export class SSHSettingsTabComponent {
connections: SSHConnection[] connections: SSHConnection[]
childGroups: SSHConnectionGroup[] childGroups: SSHConnectionGroup[]
groupCollapsed: {[id: string]: boolean} = {} groupCollapsed: Record<string, boolean> = {}
constructor ( constructor (
public config: ConfigService, public config: ConfigService,
@@ -46,6 +46,19 @@ export class SSHSettingsTabComponent {
}) })
} }
copyConnection (connection: SSHConnection) {
const modal = this.ngbModal.open(EditConnectionModalComponent)
modal.componentInstance.connection = Object.assign({
name: `${name} Copy`,
}, connection)
modal.result.then(result => {
this.connections.push(result)
this.config.store.ssh.connections = this.connections
this.config.save()
this.refresh()
})
}
editConnection (connection: SSHConnection) { editConnection (connection: SSHConnection) {
const modal = this.ngbModal.open(EditConnectionModalComponent, { size: 'lg' }) const modal = this.ngbModal.open(EditConnectionModalComponent, { size: 'lg' })
modal.componentInstance.connection = Object.assign({}, connection) modal.componentInstance.connection = Object.assign({}, connection)

View File

@@ -6,9 +6,9 @@
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open') i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open')
strong.mr-auto(*ngIf='session') {{session.connection.user}}@{{session.connection.host}}:{{session.connection.port}} strong.mr-auto(*ngIf='session') {{session.connection.user}}@{{session.connection.host}}:{{session.connection.port}}
button.btn.btn-secondary.mr-2((click)='reconnect()', [class.btn-info]='!session.open')
span Reconnect
button.btn.btn-secondary((click)='showPortForwarding()', *ngIf='session.open') button.btn.btn-secondary((click)='showPortForwarding()', *ngIf='session.open')
i.fas.fa-plug i.fas.fa-plug
span Ports span Ports
button.btn.btn-info((click)='reconnect()', *ngIf='!session.open')
span Reconnect

View File

@@ -14,7 +14,7 @@ import { Subscription } from 'rxjs'
/** @hidden */ /** @hidden */
@Component({ @Component({
selector: 'ssh-tab', selector: 'ssh-tab',
template: BaseTerminalTabComponent.template + require<string>('./sshTab.component.pug'), template: BaseTerminalTabComponent.template + (require('./sshTab.component.pug') as string),
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles], styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
animations: BaseTerminalTabComponent.animations, animations: BaseTerminalTabComponent.animations,
}) })
@@ -91,10 +91,14 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
session.serviceMessage$.subscribe(msg => { session.serviceMessage$.subscribe(msg => {
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ' ' + msg + '\r\n') this.write(`\r\n${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
session.resize(this.size.columns, this.size.rows) session.resize(this.size.columns, this.size.rows)
}) })
session.destroyed$.subscribe(() => {
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
})
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`) this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
const spinner = new Spinner({ const spinner = new Spinner({
@@ -149,8 +153,28 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
modal.session = this.session modal.session = this.session
} }
reconnect (): void { async reconnect (): Promise<void> {
this.initializeSession() this.session?.destroy()
await this.initializeSession()
this.session.releaseInitialDataBuffer()
}
async canClose (): Promise<boolean> {
if (!this.session?.open) {
return true
}
if (!(this.connection.warnOnClose ?? this.config.store.ssh.warnOnClose)) {
return true
}
return (await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
message: `Disconnect from ${this.connection.host}?`,
buttons: ['Cancel', 'Disconnect'],
defaultId: 1,
}
)).response === 1
} }
ngOnDestroy (): void { ngOnDestroy (): void {

View File

@@ -6,8 +6,8 @@ export class SSHConfigProvider extends ConfigProvider {
ssh: { ssh: {
connections: [], connections: [],
recentConnections: [], recentConnections: [],
options: { warnOnClose: false,
}, winSCPPath: null,
}, },
hotkeys: { hotkeys: {
ssh: [ ssh: [

View File

@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms' import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { ToastrModule } from 'ngx-toastr' import { ToastrModule } from 'ngx-toastr'
import TerminusCoreModule, { ToolbarButtonProvider, ConfigProvider, TabRecoveryProvider, HotkeyProvider } from 'terminus-core' import TerminusCoreModule, { ToolbarButtonProvider, ConfigProvider, TabRecoveryProvider, HotkeyProvider, TabContextMenuItemProvider } from 'terminus-core'
import { SettingsTabProvider } from 'terminus-settings' import { SettingsTabProvider } from 'terminus-settings'
import TerminusTerminalModule from 'terminus-terminal' import TerminusTerminalModule from 'terminus-terminal'
@@ -18,6 +18,7 @@ import { SSHConfigProvider } from './config'
import { SSHSettingsTabProvider } from './settings' import { SSHSettingsTabProvider } from './settings'
import { RecoveryProvider } from './recoveryProvider' import { RecoveryProvider } from './recoveryProvider'
import { SSHHotkeyProvider } from './hotkeys' import { SSHHotkeyProvider } from './hotkeys'
import { WinSCPContextMenu } from './winSCPIntegration'
/** @hidden */ /** @hidden */
@NgModule({ @NgModule({
@@ -35,6 +36,7 @@ import { SSHHotkeyProvider } from './hotkeys'
{ provide: SettingsTabProvider, useClass: SSHSettingsTabProvider, multi: true }, { provide: SettingsTabProvider, useClass: SSHSettingsTabProvider, multi: true },
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true }, { provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
{ provide: HotkeyProvider, useClass: SSHHotkeyProvider, multi: true }, { provide: HotkeyProvider, useClass: SSHHotkeyProvider, multi: true },
{ provide: TabContextMenuItemProvider, useClass: WinSCPContextMenu, multi: true },
], ],
entryComponents: [ entryComponents: [
EditConnectionModalComponent, EditConnectionModalComponent,

View File

@@ -1,4 +1,5 @@
import colors from 'ansi-colors' import colors from 'ansi-colors'
import stripAnsi from 'strip-ansi'
import { open as openTemp } from 'temp' import { open as openTemp } from 'temp'
import { Injectable, NgZone } from '@angular/core' import { Injectable, NgZone } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@@ -16,10 +17,17 @@ import { PromptModalComponent } from '../components/promptModal.component'
import { PasswordStorageService } from './passwordStorage.service' import { PasswordStorageService } from './passwordStorage.service'
import { SSHTabComponent } from '../components/sshTab.component' import { SSHTabComponent } from '../components/sshTab.component'
const WINDOWS_OPENSSH_AGENT_PIPE = '\\\\.\\pipe\\openssh-ssh-agent'
try { try {
var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
} catch { } } catch { }
// eslint-disable-next-line @typescript-eslint/no-type-alias
export type SSHLogCallback = (message: string) => void
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class SSHService { export class SSHService {
private logger: Logger private logger: Logger
@@ -44,33 +52,24 @@ export class SSHService {
return session return session
} }
async connectSession (session: SSHSession, logCallback?: (s: any) => void): Promise<void> { async loadPrivateKeyForSession (session: SSHSession, logCallback?: SSHLogCallback): Promise<string|null> {
let privateKey: string|null = null let privateKey: string|null = null
let privateKeyPath = session.connection.privateKey let privateKeyPath = session.connection.privateKey
if (!logCallback) {
logCallback = () => null
}
const log = (s: any) => {
logCallback!(s)
this.logger.info(s)
}
if (!privateKeyPath) { if (!privateKeyPath) {
const userKeyPath = path.join(process.env.HOME as string, '.ssh', 'id_rsa') const userKeyPath = path.join(process.env.HOME!, '.ssh', 'id_rsa')
if (await fs.exists(userKeyPath)) { if (await fs.exists(userKeyPath)) {
log('Using user\'s default private key') logCallback?.('Using user\'s default private key')
privateKeyPath = userKeyPath privateKeyPath = userKeyPath
} }
} }
if (privateKeyPath) { if (privateKeyPath) {
log('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' ')) logCallback?.('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' '))
try { try {
privateKey = (await fs.readFile(privateKeyPath)).toString() privateKey = (await fs.readFile(privateKeyPath)).toString()
} catch (error) { } catch (error) {
log(colors.bgRed.black(' X ') + 'Could not read the private key file') logCallback?.(colors.bgRed.black(' X ') + 'Could not read the private key file')
this.toastr.error('Could not read the private key file') this.toastr.error('Could not read the private key file')
} }
@@ -81,14 +80,14 @@ export class SSHService {
} catch (e) { } catch (e) {
if (e instanceof sshpk.KeyEncryptedError) { if (e instanceof sshpk.KeyEncryptedError) {
const modal = this.ngbModal.open(PromptModalComponent) const modal = this.ngbModal.open(PromptModalComponent)
log(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase') logCallback?.(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase')
modal.componentInstance.prompt = 'Private key passphrase' modal.componentInstance.prompt = 'Private key passphrase'
modal.componentInstance.password = true modal.componentInstance.password = true
let passphrase = '' let passphrase = ''
try { try {
const result = await modal.result const result = await modal.result
passphrase = result?.value passphrase = result?.value
} catch (e) { } } catch { }
parsedKey = sshpk.parsePrivateKey( parsedKey = sshpk.parsePrivateKey(
privateKey, privateKey,
'auto', 'auto',
@@ -114,7 +113,10 @@ export class SSHService {
'ssh-keygen.exe', 'ssh-keygen.exe',
) )
await execFile('icacls', [temp.path, '/inheritance:r']) await execFile('icacls', [temp.path, '/inheritance:r'])
await execFile('icacls', [temp.path, '/grant:r', `${process.env.USERNAME}:(R,W)`]) let sid = await execFile('whoami', ['/user', '/nh', '/fo', 'csv'])
sid = sid[0].split(',')[0]
sid = sid.substring(1, sid.length - 1)
await execFile('icacls', [temp.path, '/grant:r', `${sid}:(R,W)`])
} }
await execFile(sshKeygenPath, [ await execFile(sshKeygenPath, [
@@ -126,6 +128,20 @@ export class SSHService {
fs.unlink(temp.path) fs.unlink(temp.path)
} }
} }
return privateKey
}
async connectSession (session: SSHSession, logCallback?: SSHLogCallback): Promise<void> {
if (!logCallback) {
logCallback = () => null
}
const log = (s: any) => {
logCallback!(s)
this.logger.info(stripAnsi(s))
}
let privateKey: string|null = null
const ssh = new Client() const ssh = new Client()
session.ssh = ssh session.ssh = ssh
@@ -165,8 +181,13 @@ export class SSHService {
const modal = this.ngbModal.open(PromptModalComponent) const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = prompt.prompt modal.componentInstance.prompt = prompt.prompt
modal.componentInstance.password = !prompt.echo modal.componentInstance.password = !prompt.echo
try {
const result = await modal.result const result = await modal.result
results.push(result ? result.value : '') results.push(result ? result.value : '')
} catch {
results.push('')
}
} }
finish(results) finish(results)
})) }))
@@ -185,17 +206,45 @@ export class SSHService {
let agent: string|null = null let agent: string|null = null
if (this.hostApp.platform === Platform.Windows) { if (this.hostApp.platform === Platform.Windows) {
const pageantRunning = new Promise<boolean>(resolve => { if (await fs.exists(WINDOWS_OPENSSH_AGENT_PIPE)) {
agent = WINDOWS_OPENSSH_AGENT_PIPE
} else {
const pageantRunning = await new Promise<boolean>(resolve => {
windowsProcessTreeNative.getProcessList(list => { // eslint-disable-line block-scoped-var windowsProcessTreeNative.getProcessList(list => { // eslint-disable-line block-scoped-var
resolve(list.some(x => x.name === 'pageant.exe')) resolve(list.some(x => x.name === 'pageant.exe'))
}, 0) }, 0)
}) })
if (await pageantRunning) { if (pageantRunning) {
agent = 'pageant' agent = 'pageant'
} }
} else {
agent = process.env.SSH_AUTH_SOCK as string
} }
} else {
agent = process.env.SSH_AUTH_SOCK!
}
const authMethodsLeft = ['none']
if (!session.connection.auth || session.connection.auth === 'publicKey') {
privateKey = await this.loadPrivateKeyForSession(session, log)
if (!privateKey) {
log('\r\nPrivate key auth selected, but no key is loaded\r\n')
} else {
authMethodsLeft.push('publickey')
}
}
if (!session.connection.auth || session.connection.auth === 'agent') {
if (!agent) {
log('\r\nAgent auth selected, but no running agent is detected\r\n')
} else {
authMethodsLeft.push('agent')
}
}
if (!session.connection.auth || session.connection.auth === 'password') {
authMethodsLeft.push('password')
}
if (!session.connection.auth || session.connection.auth === 'keyboardInteractive') {
authMethodsLeft.push('keyboard-interactive')
}
authMethodsLeft.push('hostbased')
try { try {
ssh.connect({ ssh.connect({
@@ -206,11 +255,11 @@ export class SSHService {
privateKey: privateKey || undefined, privateKey: privateKey || undefined,
tryKeyboard: true, tryKeyboard: true,
agent: agent || undefined, agent: agent || undefined,
agentForward: !!agent, agentForward: session.connection.agentForward && !!agent,
keepaliveInterval: session.connection.keepaliveInterval, keepaliveInterval: session.connection.keepaliveInterval,
keepaliveCountMax: session.connection.keepaliveCountMax, keepaliveCountMax: session.connection.keepaliveCountMax,
readyTimeout: session.connection.readyTimeout, readyTimeout: session.connection.readyTimeout,
hostVerifier: digest => { hostVerifier: (digest: string) => {
log(colors.bgWhite(' ') + ' Host key fingerprint:') log(colors.bgWhite(' ') + ' Host key fingerprint:')
log(colors.bgWhite(' ') + ' ' + colors.black.bgWhite(' SHA256 ') + colors.bgBlackBright(' ' + digest + ' ')) log(colors.bgWhite(' ') + ' ' + colors.black.bgWhite(' SHA256 ') + colors.bgBlackBright(' ' + digest + ' '))
return true return true
@@ -218,7 +267,21 @@ export class SSHService {
hostHash: 'sha256' as any, hostHash: 'sha256' as any,
algorithms: session.connection.algorithms, algorithms: session.connection.algorithms,
sock: session.jumpStream, sock: session.jumpStream,
}) authHandler: methodsLeft => {
while (true) {
const method = authMethodsLeft.shift()
if (!method) {
return false
}
if (methodsLeft && !methodsLeft.includes(method) && method !== 'agent') {
// Agent can still be used even if not in methodsLeft
this.logger.info('Server does not support auth method', method)
continue
}
return method
}
},
} as any)
} catch (e) { } catch (e) {
this.toastr.error(e.message) this.toastr.error(e.message)
reject(e) reject(e)
@@ -285,8 +348,8 @@ export class SSHService {
}) })
} }
let groups: { name: string, connections: SSHConnection[] }[] = [] const groups: { name: string, connections: SSHConnection[] }[] = []
let connections = this.config.store.ssh.connections const connections = this.config.store.ssh.connections
for (const connection of connections) { for (const connection of connections) {
connection.group = connection.group || null connection.group = connection.group || null
let group = groups.find(x => x.name === connection.group) let group = groups.find(x => x.name === connection.group)

View File

@@ -0,0 +1,86 @@
import type { MenuItemConstructorOptions } from 'electron'
import { execFile } from 'child_process'
import { Injectable } from '@angular/core'
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, HostAppService, Platform } from 'terminus-core'
import { SSHTabComponent } from './components/sshTab.component'
import { PasswordStorageService } from './services/passwordStorage.service'
import { SSHConnection } from './api'
/* eslint-disable block-scoped-var */
try {
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
} catch { }
/** @hidden */
@Injectable()
export class WinSCPContextMenu extends TabContextMenuItemProvider {
weight = 10
private detectedPath?: string
constructor (
private hostApp: HostAppService,
private config: ConfigService,
private passwordStorage: PasswordStorageService,
) {
super()
if (hostApp.platform !== Platform.Windows) {
return
}
const key = wnr.getRegistryKey(wnr.HK.CR, 'WinSCP.Url\\DefaultIcon')
if (key?.['']) {
this.detectedPath = key[''].value?.split(',')[0]
this.detectedPath = this.detectedPath?.substring(1, this.detectedPath.length - 1)
}
}
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
if (this.hostApp.platform !== Platform.Windows || tabHeader) {
return []
}
if (!this.getPath()) {
return []
}
if (!(tab instanceof SSHTabComponent)) {
return []
}
return [
{
label: 'Launch WinSCP',
click: (): void => {
this.launchWinSCP(tab.connection)
},
},
]
}
getPath (): string|undefined {
return this.detectedPath ?? this.config.store.ssh.winSCPPath
}
async getURI (connection: SSHConnection): Promise<string> {
let uri = `scp://${connection.user}`
const password = await this.passwordStorage.loadPassword(connection)
if (password) {
uri += ':' + encodeURIComponent(password)
}
uri += `@${connection.host}:${connection.port}/`
return uri
}
async launchWinSCP (connection: SSHConnection): Promise<void> {
const path = this.getPath()
if (!path) {
return
}
const args = [await this.getURI(connection)]
if ((!connection.auth || connection.auth === 'publicKey') && connection.privateKey) {
args.push('/privatekey')
args.push(connection.privateKey)
}
execFile(path, args)
}
}

View File

@@ -4,7 +4,7 @@ module.exports = {
target: 'node', target: 'node',
entry: 'src/index.ts', entry: 'src/index.ts',
context: __dirname, context: __dirname,
devtool: 'eval-cheap-module-source-map', devtool: 'cheap-module-source-map',
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'index.js', filename: 'index.js',
@@ -45,10 +45,13 @@ module.exports = {
], ],
}, },
externals: [ externals: [
'child_process',
'fs', 'fs',
'keytar', 'keytar',
'path', 'path',
'ngx-toastr', 'ngx-toastr',
'socksv5',
'windows-native-registry',
'windows-process-tree/build/Release/windows_process_tree.node', 'windows-process-tree/build/Release/windows_process_tree.node',
/^rxjs/, /^rxjs/,
/^@angular/, /^@angular/,

View File

@@ -3,26 +3,26 @@
"@types/node@*": "@types/node@*":
version "12.7.12" version "14.14.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.12.tgz#7c6c571cc2f3f3ac4a59a5f2bd48f5bdbc8653cc" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
integrity sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ== integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
"@types/node@12.7.3": "@types/node@14.14.14":
version "12.7.3" version "14.14.14"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.3.tgz#27b3f40addaf2f580459fdb405222685542f907a" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
integrity sha512-3SiLAIBkDWDg6vFo0+5YJyHPWU9uwu40Qe+v+0MH8wRKYBimHvvAOyk3EzMrD/TrIlLYfXrqDqrg913PynrMJQ== integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
"@types/ssh2-streams@*": "@types/ssh2-streams@*":
version "0.1.2" version "0.1.7"
resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.2.tgz#7aa18b8c2450f17699e9ea18a76efc838188d58d" resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.7.tgz#bf79349ec85a4dfb5b3fd9f4a05af729121f07e6"
integrity sha1-eqGLjCRQ8XaZ6eoYp278g4GI1Y0= integrity sha512-cQNV72C+BOG7G8WNGarTQdB2Ii37cJlWatSpx5zTYxtI2ZvUt2lbq6Nc2XZ4kbge28V7Xe5KYYr82d96/rDMnQ==
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/ssh2@^0.5.35": "@types/ssh2@^0.5.35":
version "0.5.43" version "0.5.45"
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.43.tgz#a4b8fc0288ef79a0d2d89363644d0b4448fe9532" resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.45.tgz#14e293ec2a4d4c8a5434a7989a676b87340aa870"
integrity sha512-rVEwm6fEmy9RJg1nTK3qhCKoviKtLg+axE1RXzAWuKz3QuZIZDxCKP38/tzhxkQ8I8FDVXgRoWtvltzQKtDaBg== integrity sha512-SAQITTyO/jOoskSAw2T/9sveX4lhTzx7zdeYR0t04RMhZQrEIzvrAoCStSxYwvwZ5ofek1JWeW9x2yOK3GOUlg==
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/ssh2-streams" "*" "@types/ssh2-streams" "*"
@@ -32,6 +32,11 @@ ansi-colors@^4.1.1:
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
ansi-regex@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
asn1@~0.2.0, asn1@~0.2.3: asn1@~0.2.0, asn1@~0.2.3:
version "0.2.4" version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
@@ -44,6 +49,11 @@ assert-plus@^1.0.0:
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
async@0.2.x:
version "0.2.10"
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E=
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -69,11 +79,42 @@ cli-spinner@^0.2.10:
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47" resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
integrity sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q== integrity sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==
cli@0.4.x:
version "0.4.5"
resolved "https://registry.yarnpkg.com/cli/-/cli-0.4.5.tgz#78f9485cd161b566e9a6c72d7170c4270e81db61"
integrity sha1-ePlIXNFhtWbppsctcXDEJw6B22E=
dependencies:
glob ">= 3.1.4"
cliff@0.1.x:
version "0.1.10"
resolved "https://registry.yarnpkg.com/cliff/-/cliff-0.1.10.tgz#53be33ea9f59bec85609ee300ac4207603e52013"
integrity sha1-U74z6p9ZvshWCe4wCsQgdgPlIBM=
dependencies:
colors "~1.0.3"
eyes "~0.1.8"
winston "0.8.x"
colors@0.6.x:
version "0.6.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc"
integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=
colors@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
cycle@1.0.x:
version "1.0.3"
resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI=
dashdash@^1.12.0: dashdash@^1.12.0:
version "1.14.1" version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -89,6 +130,11 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0" jsbn "~0.1.0"
safer-buffer "^2.1.0" safer-buffer "^2.1.0"
eyes@0.1.x, eyes@~0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=
fs.realpath@^1.0.0: fs.realpath@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -101,7 +147,7 @@ getpass@^0.1.1:
dependencies: dependencies:
assert-plus "^1.0.0" assert-plus "^1.0.0"
glob@^7.1.3: "glob@>= 3.1.4", glob@^7.1.3:
version "7.1.6" version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -126,6 +172,20 @@ inherits@2:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ipv6@*:
version "3.1.3"
resolved "https://registry.yarnpkg.com/ipv6/-/ipv6-3.1.3.tgz#4d9064f9c2dafa0dd10b8b7d76ffca4aad31b3b9"
integrity sha1-TZBk+cLa+g3RC4t9dv/KSq0xs7k=
dependencies:
cli "0.4.x"
cliff "0.1.x"
sprintf "0.1.x"
isstream@0.1.x:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jsbn@~0.1.0: jsbn@~0.1.0:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -138,6 +198,18 @@ minimatch@^3.0.4:
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
mkdirp@^0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"
once@^1.3.0: once@^1.3.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -150,6 +222,11 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
pkginfo@0.3.x:
version "0.3.1"
resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21"
integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=
rimraf@~2.6.2: rimraf@~2.6.2:
version "2.6.3" version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
@@ -157,12 +234,37 @@ rimraf@~2.6.2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
run-script-os@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/run-script-os/-/run-script-os-1.1.3.tgz#1069b418307f4fd36ff056b5eda309c273fca8b0"
integrity sha512-xPlzE6533nvWVea5z7e5J7+JAIepfpxTu/HLGxcjJYlemVukOCWJBaRCod/DWXJFRIWEFOgSGbjd2m1QWTJi5w==
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
ssh2-streams@^0.4.2, ssh2-streams@~0.4.10: socksv5@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/socksv5/-/socksv5-0.0.6.tgz#1327235ff7e8de21ac434a0a579dc69c3f071061"
integrity sha1-EycjX/fo3iGsQ0oKV53GnD8HEGE=
dependencies:
ipv6 "*"
sprintf@0.1.x:
version "0.1.5"
resolved "https://registry.yarnpkg.com/sprintf/-/sprintf-0.1.5.tgz#8f83e39a9317c1a502cb7db8050e51c679f6edcf"
integrity sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=
ssh2-streams@Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5:
version "0.4.10"
resolved "https://codeload.github.com/Eugeny/ssh2-streams/tar.gz/75f6d3425d071ac73a18fd46e2f5e738bfe897c5"
dependencies:
asn1 "~0.2.0"
bcrypt-pbkdf "^1.0.2"
streamsearch "~0.1.2"
ssh2-streams@~0.4.10:
version "0.4.10" version "0.4.10"
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.10.tgz#48ef7e8a0e39d8f2921c30521d56dacb31d23a34" resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.10.tgz#48ef7e8a0e39d8f2921c30521d56dacb31d23a34"
integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ== integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==
@@ -171,7 +273,7 @@ ssh2-streams@^0.4.2, ssh2-streams@~0.4.10:
bcrypt-pbkdf "^1.0.2" bcrypt-pbkdf "^1.0.2"
streamsearch "~0.1.2" streamsearch "~0.1.2"
ssh2@^0.8.2: ssh2@^0.8.9:
version "0.8.9" version "0.8.9"
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3" resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3"
integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw== integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==
@@ -193,28 +295,49 @@ sshpk@^1.16.1:
safer-buffer "^2.0.2" safer-buffer "^2.0.2"
tweetnacl "~0.14.0" tweetnacl "~0.14.0"
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
streamsearch@~0.1.2: streamsearch@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
temp@^0.9.1: strip-ansi@^6.0.0:
version "0.9.1" version "6.0.0"
resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.1.tgz#2d666114fafa26966cd4065996d7ceedd4dd4697" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
integrity sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA== integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
dependencies: dependencies:
rimraf "~2.6.2" ansi-regex "^5.0.0"
terminus-terminal@^1.0.98-nightly.0: temp@^0.9.1:
version "1.0.98-nightly.0" version "0.9.4"
resolved "https://registry.yarnpkg.com/terminus-terminal/-/terminus-terminal-1.0.98-nightly.0.tgz#10df71b0a81adf76a076fb21a91c859dd2f8bef7" resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620"
integrity sha512-JLxkeoQkORcfe6cRW6BJF5ZPSbvKA8IWUAb7fzBONVmNfRKj2Mq/uYPy76UXsdmb9F1n+rYIg+DShNp57asMKA== integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==
dependencies:
mkdirp "^0.5.1"
rimraf "~2.6.2"
tweetnacl@^0.14.3, tweetnacl@~0.14.0: tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5" version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
winston@0.8.x:
version "0.8.3"
resolved "https://registry.yarnpkg.com/winston/-/winston-0.8.3.tgz#64b6abf4cd01adcaefd5009393b1d8e8bec19db0"
integrity sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=
dependencies:
async "0.2.x"
colors "0.6.x"
cycle "1.0.x"
eyes "0.1.x"
isstream "0.1.x"
pkginfo "0.3.x"
stack-trace "0.0.x"
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

View File

@@ -9,7 +9,7 @@ Terminus Terminal Plugin
Using the API: Using the API:
```ts ```ts
import { TerminalContextMenuItemProvider } from 'terminus-terminal' import { ShellProvider } from 'terminus-terminal'
``` ```
Exporting your subclasses: Exporting your subclasses:
@@ -19,7 +19,7 @@ Exporting your subclasses:
... ...
providers: [ providers: [
... ...
{ provide: TerminalContextMenuItemProvider, useClass: MyContextMenu, multi: true }, { provide: ShellProvider, useClass: MyShellPlugin, multi: true },
... ...
] ]
}) })

View File

@@ -1,6 +1,6 @@
{ {
"name": "terminus-terminal", "name": "terminus-terminal",
"version": "1.0.104-nightly.0", "version": "1.0.123-nightly.0",
"description": "Terminus' terminal emulation core", "description": "Terminus' terminal emulation core",
"keywords": [ "keywords": [
"terminus-builtin-plugin" "terminus-builtin-plugin"
@@ -26,24 +26,23 @@
"ps-node": "^0.1.6", "ps-node": "^0.1.6",
"runes": "^0.4.2", "runes": "^0.4.2",
"slugify": "^1.4.0", "slugify": "^1.4.0",
"uuid": "^8.0.0", "xterm": "^4.9.0-beta.7",
"xterm": "^4.6.0-beta.33",
"xterm-addon-fit": "^0.4.0-beta.8", "xterm-addon-fit": "^0.4.0-beta.8",
"xterm-addon-ligatures": "^0.3.0-beta.1", "xterm-addon-ligatures": "^0.4.0-beta.5",
"xterm-addon-search": "^0.7.0-beta.1", "xterm-addon-search": "^0.7.0-beta.2",
"xterm-addon-serialize": "^0.3.0-beta.3", "xterm-addon-serialize": "^0.3.0",
"xterm-addon-unicode11": "^0.2.0-beta.5", "xterm-addon-unicode11": "^0.2.0",
"xterm-addon-webgl": "^0.7.0-beta.5", "xterm-addon-webgl": "^0.8.0",
"zmodem.js": "^0.1.9" "zmodem.js": "^0.1.9"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/animations": "^7", "@angular/animations": "^9.1.9",
"@angular/common": "^7", "@angular/common": "^9.1.11",
"@angular/core": "^7", "@angular/core": "^9.1.9",
"@angular/forms": "^7", "@angular/forms": "^9.1.11",
"@angular/platform-browser": "^7", "@angular/platform-browser": "^9.1.11",
"@ng-bootstrap/ng-bootstrap": "^1", "@ng-bootstrap/ng-bootstrap": "^6.1.0",
"rxjs": "^5", "rxjs": "^6.5.5",
"terminus-core": "*", "terminus-core": "*",
"terminus-settings": "*" "terminus-settings": "*"
} }

View File

@@ -1,10 +1,11 @@
import type { MenuItemConstructorOptions } from 'electron'
import { Observable, Subject, Subscription } from 'rxjs' import { Observable, Subject, Subscription } from 'rxjs'
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { ToastrService } from 'ngx-toastr' import { ToastrService } from 'ngx-toastr'
import colors from 'ansi-colors' import colors from 'ansi-colors'
import { NgZone, OnInit, OnDestroy, Injector, ViewChild, HostBinding, Input, ElementRef, InjectFlags } from '@angular/core' import { NgZone, OnInit, OnDestroy, Injector, ViewChild, HostBinding, Input, ElementRef, InjectFlags } from '@angular/core'
import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations' import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger, TabContextMenuItemProvider } from 'terminus-core' import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger, TabContextMenuItemProvider, SplitTabComponent } from 'terminus-core'
import { BaseSession, SessionsService } from '../services/sessions.service' import { BaseSession, SessionsService } from '../services/sessions.service'
import { TerminalFrontendService } from '../services/terminalFrontend.service' import { TerminalFrontendService } from '../services/terminalFrontend.service'
@@ -16,14 +17,14 @@ import { TerminalDecorator } from './decorator'
/** @hidden */ /** @hidden */
export interface ToastrServiceProxy { export interface ToastrServiceProxy {
info (_: string) info: (_: string) => void
} }
/** /**
* A class to base your custom terminal tabs on * A class to base your custom terminal tabs on
*/ */
export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy { export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
static template = require<string>('../components/baseTerminalTab.component.pug') static template: string = require<string>('../components/baseTerminalTab.component.pug')
static styles = [require<string>('../components/terminalTab.component.scss')] static styles: string[] = [require<string>('../components/terminalTab.component.scss')]
static animations: AnimationTriggerMetadata[] = [trigger('slideInOut', [ static animations: AnimationTriggerMetadata[] = [trigger('slideInOut', [
transition(':enter', [ transition(':enter', [
style({ transform: 'translateY(-25%)' }), style({ transform: 'translateY(-25%)' }),
@@ -92,6 +93,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
private hotkeysSubscription: Subscription private hotkeysSubscription: Subscription
private bellPlayer: HTMLAudioElement private bellPlayer: HTMLAudioElement
private termContainerSubscriptions: Subscription[] = [] private termContainerSubscriptions: Subscription[] = []
private allFocusModeSubscription: Subscription|null = null
get input$ (): Observable<Buffer> { return this.frontend.input$ } get input$ (): Observable<Buffer> { return this.frontend.input$ }
get output$ (): Observable<string> { return this.output } get output$ (): Observable<string> { return this.output }
@@ -155,16 +157,28 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.resetZoom() this.resetZoom()
break break
case 'previous-word': case 'previous-word':
this.sendInput('\x1bb') this.sendInput({
[Platform.Windows]: '\x1b[1;5D',
[Platform.macOS]: '\x1bb',
[Platform.Linux]: '\x1bb',
}[this.hostApp.platform])
break break
case 'next-word': case 'next-word':
this.sendInput('\x1bf') this.sendInput({
[Platform.Windows]: '\x1b[1;5C',
[Platform.macOS]: '\x1bf',
[Platform.Linux]: '\x1bf',
}[this.hostApp.platform])
break break
case 'delete-previous-word': case 'delete-previous-word':
this.sendInput('\x1b\x7f') this.sendInput('\x1b\x7f')
break break
case 'delete-next-word': case 'delete-next-word':
this.sendInput('\x1bd') this.sendInput({
[Platform.Windows]: '\x1bd\x1b[3;5~',
[Platform.macOS]: '\x1bd',
[Platform.Linux]: '\x1bd',
}[this.hostApp.platform])
break break
case 'search': case 'search':
this.showSearchPanel = true this.showSearchPanel = true
@@ -172,6 +186,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.element.nativeElement.querySelector('.search-input').focus() this.element.nativeElement.querySelector('.search-input').focus()
}) })
break break
case 'pane-focus-all':
this.focusAllPanes()
break
} }
}) })
this.bellPlayer = document.createElement('audio') this.bellPlayer = document.createElement('audio')
@@ -255,10 +272,14 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
}) })
this.frontend.focus() this.frontend.focus()
this.blurred$.subscribe(() => {
this.cancelFocusAllPanes()
})
} }
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> { async buildContextMenu (): Promise<MenuItemConstructorOptions[]> {
let items: Electron.MenuItemConstructorOptions[] = [] let items: MenuItemConstructorOptions[] = []
for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this)))) { for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this)))) {
items = items.concat(section) items = items.concat(section)
items.push({ type: 'separator' }) items.push({ type: 'separator' })
@@ -298,7 +319,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
} }
async paste (): Promise<void> { async paste (): Promise<void> {
let data = this.electron.clipboard.readText() as string let data = this.electron.clipboard.readText()
if (this.config.store.terminal.bracketedPaste) { if (this.config.store.terminal.bracketedPaste) {
data = '\x1b[200~' + data + '\x1b[201~' data = '\x1b[200~' + data + '\x1b[201~'
} }
@@ -308,9 +329,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
data = data.replace(/\n/g, '\r') data = data.replace(/\n/g, '\r')
} }
if (!this.alternateScreenActive && data.includes('\r') && this.config.store.terminal.warnOnMultilinePaste) { if (!this.alternateScreenActive) {
const canTrim = !data.trim().includes('\r') data = data.trim()
const buttons = canTrim ? ['Paste', 'Trim whitespace and paste', 'Cancel'] : ['Paste', 'Cancel']
if (data.includes('\r') && this.config.store.terminal.warnOnMultilinePaste) {
const buttons = ['Paste', 'Cancel']
const result = (await this.electron.showMessageBox( const result = (await this.electron.showMessageBox(
this.hostApp.getWindow(), this.hostApp.getWindow(),
{ {
@@ -319,14 +342,12 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
message: `Paste multiple lines?`, message: `Paste multiple lines?`,
buttons, buttons,
defaultId: 0, defaultId: 0,
cancelId: buttons.length - 1, cancelId: 1,
} }
)).response )).response
if (result === buttons.length - 1) { if (result === 1) {
return return
} }
if (result === 1) {
data = data.trim()
} }
} }
this.sendInput(data) this.sendInput(data)
@@ -340,7 +361,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.topPadded = this.hostApp.platform === Platform.macOS this.topPadded = this.hostApp.platform === Platform.macOS
&& this.config.store.appearance.frame === 'thin' && this.config.store.appearance.frame === 'thin'
&& this.config.store.appearance.tabsLocation === 'bottom' && this.config.store.appearance.tabsLocation !== 'top'
if (this.config.store.terminal.background === 'colorScheme') { if (this.config.store.terminal.background === 'colorScheme') {
if (this.config.store.terminal.colorScheme.background) { if (this.config.store.terminal.colorScheme.background) {
@@ -366,6 +387,35 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.frontend.setZoom(this.zoom) this.frontend.setZoom(this.zoom)
} }
focusAllPanes (): void {
if (this.allFocusModeSubscription) {
return
}
if (this.parent instanceof SplitTabComponent) {
this.parent._allFocusMode = true
this.parent.layout()
this.allFocusModeSubscription = this.frontend.input$.subscribe(data => {
for (const tab of (this.parent as SplitTabComponent).getAllTabs()) {
if (tab !== this && tab instanceof BaseTerminalTabComponent) {
tab.sendInput(data)
}
}
})
}
}
cancelFocusAllPanes (): void {
if (!this.allFocusModeSubscription) {
return
}
if (this.parent instanceof SplitTabComponent) {
this.allFocusModeSubscription?.unsubscribe?.()
this.allFocusModeSubscription = null
this.parent._allFocusMode = false
this.parent.layout()
}
}
/** @hidden */ /** @hidden */
ngOnDestroy (): void { ngOnDestroy (): void {
this.frontend.detach(this.content.nativeElement) this.frontend.detach(this.content.nativeElement)
@@ -386,7 +436,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
async destroy (): Promise<void> { async destroy (): Promise<void> {
super.destroy() super.destroy()
if (this.session && this.session.open) { if (this.session?.open) {
await this.session.destroy() await this.session.destroy()
} }
} }
@@ -463,7 +513,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.logger.debug(`Resizing to ${columns}x${rows}`) this.logger.debug(`Resizing to ${columns}x${rows}`)
this.size = { columns, rows } this.size = { columns, rows }
this.zone.run(() => { this.zone.run(() => {
if (this.session && this.session.open) { if (this.session?.open) {
this.session.resize(columns, rows) this.session.resize(columns, rows)
} }
}) })
@@ -474,7 +524,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
] ]
} }
protected attachSessionHandlers (): void { protected attachSessionHandlers (destroyOnSessionClose = false): void {
// this.session.output$.bufferTime(10).subscribe((datas) => { // this.session.output$.bufferTime(10).subscribe((datas) => {
this.session.output$.subscribe(data => { this.session.output$.subscribe(data => {
if (this.enablePassthrough) { if (this.enablePassthrough) {
@@ -485,9 +535,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
} }
}) })
if (destroyOnSessionClose) {
this.sessionCloseSubscription = this.session.closed$.subscribe(() => { this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
this.frontend.destroy() this.frontend.destroy()
this.destroy() this.destroy()
}) })
} }
} }
}

View File

@@ -1,3 +1,4 @@
import type { MenuItemConstructorOptions } from 'electron'
import { BaseTerminalTabComponent } from './baseTerminalTab.component' import { BaseTerminalTabComponent } from './baseTerminalTab.component'
/** /**
@@ -7,5 +8,5 @@ import { BaseTerminalTabComponent } from './baseTerminalTab.component'
export abstract class TerminalContextMenuItemProvider { export abstract class TerminalContextMenuItemProvider {
weight: number weight: number
abstract async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> abstract async getItems (tab: BaseTerminalTabComponent): Promise<MenuItemConstructorOptions[]>
} }

Some files were not shown because too many files have changed in this diff Show More