Compare commits

...

155 Commits

Author SHA1 Message Date
Eugene Pankov
0d65fe348b lint 2020-03-01 17:07:11 +01:00
Eugene Pankov
e4b7693685 dropped slug 2020-03-01 17:02:49 +01:00
Eugene Pankov
566aa83fa9 bumped plugin versions 2020-03-01 16:40:43 +01:00
Eugene Pankov
eb2d88eac2 added a build-typings script 2020-03-01 16:40:26 +01:00
Eugene Pankov
316b77ec7b lint 2020-03-01 16:33:24 +01:00
Eugene Pankov
a4dc6832f3 Merge branch 'master' of github.com:Eugeny/terminus 2020-03-01 16:16:26 +01:00
Eugene Pankov
7a895dda1a fixes 2020-03-01 16:16:03 +01:00
Eugene Pankov
b2fc016aa8 bumped sentry 2020-03-01 16:13:12 +01:00
Eugene
32096ea4fd Merge pull request #2170 from Eugeny/dependabot/npm_and_yarn/sentry/cli-1.51.1
Bump @sentry/cli from 1.49.0 to 1.51.1
2020-03-01 16:12:18 +01:00
Eugene
30fd36ed26 Merge pull request #2189 from Eugeny/dependabot/npm_and_yarn/typescript-3.8.2
Bump typescript from 3.7.5 to 3.8.2
2020-03-01 16:11:47 +01:00
dependabot-preview[bot]
afdf09076a Bump tslib from 1.10.0 to 1.11.1 (#2196)
Bumps [tslib](https://github.com/Microsoft/tslib) from 1.10.0 to 1.11.1.
- [Release notes](https://github.com/Microsoft/tslib/releases)
- [Commits](https://github.com/Microsoft/tslib/compare/1.10.0...1.11.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-01 16:11:30 +01:00
Eugene Pankov
04a0a0cc64 lint 2020-03-01 16:10:45 +01:00
Eugene Pankov
fda4d2dcef Merge branch 'dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-2.21.0' 2020-03-01 15:23:05 +01:00
Eugene Pankov
2c341e23b5 Merge branch 'dependabot/npm_and_yarn/typescript-eslint/parser-2.21.0' 2020-03-01 15:21:59 +01:00
Eugene Pankov
953b06f43f skip invalid hotkey config (fixes #817) 2020-03-01 15:20:16 +01:00
Eugene Pankov
e1cc1d56ea fixes 2020-03-01 15:12:24 +01:00
Eugene Pankov
df2f4d4a6c angular 9 fixes 2020-03-01 14:26:55 +01:00
Eugene Pankov
092820173f fixed #2111 2020-03-01 14:08:54 +01:00
Eugene Pankov
58c7c23bd8 Merge branch 'master' of github.com:Eugeny/terminus 2020-03-01 14:07:07 +01:00
Eugene Pankov
920afe450a bumped angular 2020-03-01 14:07:02 +01:00
dependabot-preview[bot]
3edcce29fa Bump keytar from 5.2.0 to 5.4.0 in /app (#2188)
Bumps [keytar](https://github.com/atom/node-keytar) from 5.2.0 to 5.4.0.
- [Release notes](https://github.com/atom/node-keytar/releases)
- [Commits](https://github.com/atom/node-keytar/compare/v5.2.0...v5.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-01 13:45:29 +01:00
Eugene Pankov
e14c7fec10 Revert "Update linux.yml"
This reverts commit b3ed62244d.
2020-03-01 13:30:14 +01:00
Eugene Pankov
b3ed62244d Update linux.yml 2020-03-01 13:29:10 +01:00
Eugene Pankov
ff1bfa990c node-version prop 2020-03-01 13:26:40 +01:00
Eugene Pankov
bd3463880e Update linux.yml 2020-03-01 13:25:02 +01:00
Eugene Pankov
95a61ec369 Update linux.yml 2020-03-01 13:15:58 +01:00
Eugene Pankov
1b29797a81 serial plugin ui improv 2020-03-01 13:08:16 +01:00
Eugene Pankov
10b21ee085 added serial port detection 2020-03-01 12:15:02 +01:00
Eugene
f5ffdc1707 Use ssh-keygen to convert ssh keys (#2197)
* use ssh-keygen to convert keys

* drop incorrect typings

* .

* Update ssh.service.ts

* Update ssh.service.ts

* Update ssh.service.ts
2020-03-01 11:17:11 +01:00
Eugene Pankov
b3f17b84ff added hotkeys to save session output 2020-02-29 15:05:58 +01:00
dependabot-preview[bot]
1a332128e3 Bump @typescript-eslint/parser from 2.19.2 to 2.21.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.19.2 to 2.21.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.21.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-27 04:21:13 +00:00
dependabot-preview[bot]
b5db7e80d0 Bump typescript from 3.7.5 to 3.8.2
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.7.5 to 3.8.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.7.5...v3.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-27 04:20:22 +00:00
dependabot-preview[bot]
5bba719624 Bump @sentry/cli from 1.49.0 to 1.51.1
Bumps [@sentry/cli](https://github.com/getsentry/sentry-cli) from 1.49.0 to 1.51.1.
- [Release notes](https://github.com/getsentry/sentry-cli/releases)
- [Changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-cli/compare/1.49.0...1.51.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-26 10:07:21 +00:00
Eugene
09d6838b08 Merge pull request #2060 from Eugeny/dependabot/npm_and_yarn/terminus-core/types/js-yaml-3.12.2
Bump @types/js-yaml from 3.12.1 to 3.12.2 in /terminus-core
2020-02-26 11:06:10 +01:00
Eugene
325d2dc2a4 Merge pull request #2065 from Eugeny/dependabot/npm_and_yarn/terminus-plugin-manager/types/semver-7.1.0
Bump @types/semver from 6.2.0 to 7.1.0 in /terminus-plugin-manager
2020-02-26 11:06:01 +01:00
dependabot-preview[bot]
94c7e2b5c3 Bump @types/js-yaml from 3.12.1 to 3.12.2 in /terminus-core
Bumps [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) from 3.12.1 to 3.12.2.
- [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-02-26 10:05:48 +00:00
dependabot-preview[bot]
9da2e8d489 Bump @types/semver from 6.2.0 to 7.1.0 in /terminus-plugin-manager
Bumps [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) from 6.2.0 to 7.1.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-26 10:05:42 +00:00
Eugene
ff1c5df30b Merge pull request #1974 from Eugeny/dependabot/npm_and_yarn/sentry/electron-1.2.0
Bump @sentry/electron from 1.0.0 to 1.2.0
2020-02-26 11:05:22 +01:00
Eugene
159adf9911 Merge pull request #2140 from Eugeny/dependabot/npm_and_yarn/app/electron-updater-4.2.2
Bump electron-updater from 4.2.0 to 4.2.2 in /app
2020-02-26 11:04:25 +01:00
Eugene
994a94f8f1 Merge pull request #2141 from Eugeny/dependabot/npm_and_yarn/terminus-core/electron-updater-4.2.2
Bump electron-updater from 4.2.0 to 4.2.2 in /terminus-core
2020-02-26 11:04:14 +01:00
Eugene
571db20523 Merge pull request #2179 from Eugeny/all-contributors/add-nstefanou
docs: add nstefanou as a contributor
2020-02-26 11:02:57 +01:00
Eugene
a422d62db0 Merge pull request #2175 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/uuid-7.0.1
Bump uuid from 3.4.0 to 7.0.1 in /terminus-terminal
2020-02-26 11:02:35 +01:00
Eugene
feb2a52b37 Merge pull request #2178 from Eugeny/dependabot/npm_and_yarn/terminus-core/uuid-7.0.1
Bump uuid from 3.4.0 to 7.0.1 in /terminus-core
2020-02-26 11:02:17 +01:00
allcontributors[bot]
267ca2e95c docs: update .all-contributorsrc [skip ci] 2020-02-26 10:01:51 +00:00
allcontributors[bot]
9691a932ac docs: update README.md [skip ci] 2020-02-26 10:01:50 +00:00
Eugene Pankov
94d51c029e serial fixes 2020-02-26 11:01:05 +01:00
Eugene Pankov
efd7b2ca2b Merge branch 'master' into pr/2173 2020-02-26 10:18:49 +01:00
Eugene Pankov
ed88784431 Merge branch 'master' of github.com:Eugeny/terminus 2020-02-26 10:18:32 +01:00
Eugene Pankov
e48f844ea0 lint 2020-02-26 10:16:45 +01:00
Eugene
fd21be5408 Merge pull request #2134 from Eugeny/dependabot/npm_and_yarn/typedoc-0.16.10
Bump typedoc from 0.16.7 to 0.16.10
2020-02-26 10:16:39 +01:00
Eugene
f4c2d01df8 Merge pull request #2136 from Eugeny/dependabot/npm_and_yarn/eslint-plugin-import-2.20.1
Bump eslint-plugin-import from 2.20.0 to 2.20.1
2020-02-26 10:16:29 +01:00
Eugene
4828bb4df7 Merge pull request #2137 from Eugeny/dependabot/npm_and_yarn/webpack-5.0.0-beta.13
Bump webpack from 5.0.0-beta.12 to 5.0.0-beta.13
2020-02-26 10:16:21 +01:00
Eugene
037e91508b Merge pull request #2166 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/ssh2-0.8.8
Bump ssh2 from 0.8.7 to 0.8.8 in /terminus-ssh
2020-02-26 10:15:06 +01:00
dependabot-preview[bot]
735010dd1f Bump uuid from 3.4.0 to 7.0.1 in /terminus-core
Bumps [uuid](https://github.com/uuidjs/uuid) from 3.4.0 to 7.0.1.
- [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/v3.4.0...v7.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-26 09:15:05 +00:00
dependabot-preview[bot]
11364dd788 Bump uuid from 3.4.0 to 7.0.1 in /terminus-terminal
Bumps [uuid](https://github.com/uuidjs/uuid) from 3.4.0 to 7.0.1.
- [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/v3.4.0...v7.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-26 09:14:59 +00:00
Eugene Pankov
0eced6f4a9 bumped xterm (fixes #2153) 2020-02-26 10:13:22 +01:00
Eugene
3157c89be3 Merge pull request #2132 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-webgl-0.6.0-beta.3
Bump xterm-addon-webgl from 0.6.0-beta.2 to 0.6.0-beta.3 in /terminus-terminal
2020-02-26 10:10:14 +01:00
Eugene
a7f909d06a Merge pull request #2177 from Eugeny/dependabot/npm_and_yarn/electron-8.0.2
Bump electron from 8.0.0 to 8.0.2
2020-02-26 10:09:35 +01:00
dependabot-preview[bot]
527b55a46e Bump electron from 8.0.0 to 8.0.2
Bumps [electron](https://github.com/electron/electron) from 8.0.0 to 8.0.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.0.0...v8.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-26 04:23:29 +00:00
Nikolaos Stefanou
a610306f29 unused parameters 2020-02-25 20:08:43 +00:00
Nikolaos Stefanou
3daf0b394e lint fixes 2020-02-25 19:54:36 +00:00
Nikolaos Stefanou
f151928b6b make serialport native bindings work 2020-02-25 19:49:25 +00:00
Nikolaos Stefanou
041a3ce2b6 fix lint errors 2020-02-25 17:00:41 +00:00
Nikolaos Stefanou
6348e7b8f0 first working version of serial port integration 2020-02-25 16:31:42 +00:00
dependabot-preview[bot]
8be72618e6 Bump @typescript-eslint/eslint-plugin from 2.13.0 to 2.21.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.13.0 to 2.21.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v2.21.0/packages/eslint-plugin)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-25 04:24:16 +00:00
dependabot-preview[bot]
a50c7cb474 Bump ssh2 from 0.8.7 to 0.8.8 in /terminus-ssh
Bumps [ssh2](https://github.com/mscdex/ssh2) from 0.8.7 to 0.8.8.
- [Release notes](https://github.com/mscdex/ssh2/releases)
- [Commits](https://github.com/mscdex/ssh2/compare/v0.8.7...v0.8.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-25 04:21:05 +00:00
Eugene
8cef4e5cf9 Merge pull request #2148 from nstefanou/master
resolves #1988
2020-02-24 11:56:29 +01:00
Nikolaos Stefanou
9705a1b5b5 resolves #1988 2020-02-19 12:45:18 +00:00
Eugene Pankov
d0ddd82906 fixed wsl crash when default distro is not available (fixes #2130) 2020-02-18 10:52:17 +01:00
dependabot-preview[bot]
dfa17948e2 Bump electron-updater from 4.2.0 to 4.2.2 in /terminus-core
Bumps [electron-updater](https://github.com/electron-userland/electron-builder) from 4.2.0 to 4.2.2.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/compare/v4.2.0...v4.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-18 04:21:41 +00:00
dependabot-preview[bot]
3607391d55 Bump electron-updater from 4.2.0 to 4.2.2 in /app
Bumps [electron-updater](https://github.com/electron-userland/electron-builder) from 4.2.0 to 4.2.2.
- [Release notes](https://github.com/electron-userland/electron-builder/releases)
- [Changelog](https://github.com/electron-userland/electron-builder/blob/master/CHANGELOG.md)
- [Commits](https://github.com/electron-userland/electron-builder/compare/v4.2.0...v4.2.2)

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

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-17 04:25:03 +00:00
dependabot-preview[bot]
b467c7de65 Bump eslint-plugin-import from 2.20.0 to 2.20.1
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.20.0 to 2.20.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.0...v2.20.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-17 04:24:30 +00:00
dependabot-preview[bot]
c3e793229d Bump typedoc from 0.16.7 to 0.16.10
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.16.7 to 0.16.10.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.16.7...v0.16.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-17 04:23:23 +00:00
dependabot-preview[bot]
14bcfb01c2 Bump xterm-addon-webgl in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.6.0-beta.2 to 0.6.0-beta.3.
- [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-02-17 04:22:05 +00:00
Eugene Pankov
8a5846ff81 dropped local fsevents 2020-02-16 23:07:12 +01:00
Eugene Pankov
298209b03a option to skip the ssh banner (fixes #2121) 2020-02-16 23:04:26 +01:00
Eugene Pankov
dc03a7f135 fixed #1629 2020-02-16 23:00:02 +01:00
Eugene Pankov
2d357d0ed2 made zmodem xfers cancelable 2020-02-16 22:57:54 +01:00
Eugene Pankov
58d2590495 moved decorators in to features/ 2020-02-16 21:34:49 +01:00
Eugene Pankov
0c892225f3 nicer terminal messages for SSH 2020-02-16 21:26:01 +01:00
Eugene Pankov
851d92a140 fixed private key handling (fixed #2018, fixed #2053, fixed #1966) 2020-02-16 21:25:52 +01:00
Eugene Pankov
665ce2f022 limited xterm serialization length 2020-02-16 16:59:59 +01:00
Eugene Pankov
5ea1ff1ea5 added fsevents 2020-02-16 16:59:40 +01:00
dependabot-preview[bot]
5d28369b8b Bump @sentry/electron from 1.0.0 to 1.2.0
Bumps [@sentry/electron](https://github.com/getsentry/sentry-electron) from 1.0.0 to 1.2.0.
- [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.0.0...v1.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-16 15:46:16 +00:00
Eugene
5ed92342ea Merge pull request #2104 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/types/ssh2-0.5.40
Bump @types/ssh2 from 0.5.39 to 0.5.40 in /terminus-ssh
2020-02-16 16:44:49 +01:00
Eugene
d9843c4ff0 Merge pull request #2106 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-2.19.2
Bump @typescript-eslint/parser from 2.17.0 to 2.19.2
2020-02-16 16:44:40 +01:00
Eugene
448371dffa Merge pull request #2126 from Eugeny/dependabot/npm_and_yarn/app/node-abi-2.15.0
Bump node-abi from 2.14.0 to 2.15.0 in /app
2020-02-16 16:44:20 +01:00
Eugene
425c288aa0 Merge pull request #2125 from Eugeny/dependabot/npm_and_yarn/node-abi-2.15.0
Bump node-abi from 2.14.0 to 2.15.0
2020-02-16 16:44:09 +01:00
Eugene
09b118987e Merge pull request #2119 from Eugeny/dependabot/npm_and_yarn/fortawesome/fontawesome-free-5.12.1
Bump @fortawesome/fontawesome-free from 5.12.0 to 5.12.1
2020-02-16 16:43:43 +01:00
dependabot-preview[bot]
70dbb6bfcc Bump node-abi from 2.14.0 to 2.15.0 in /app
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.14.0 to 2.15.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.14.0...v2.15.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-14 04:22:48 +00:00
dependabot-preview[bot]
4b55f9cd97 Bump node-abi from 2.14.0 to 2.15.0
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.14.0 to 2.15.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.14.0...v2.15.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-14 04:22:32 +00:00
Eugene Pankov
fbb6614553 fixed #185 2020-02-13 12:32:04 +01:00
dependabot-preview[bot]
8d849b40a2 Bump @fortawesome/fontawesome-free from 5.12.0 to 5.12.1
Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 5.12.0 to 5.12.1.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/5.12.0...5.12.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-13 10:00:56 +00:00
Eugene
5e678c15f3 Merge pull request #2113 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-webgl-0.6.0-beta.2
Bump xterm-addon-webgl from 0.5.0 to 0.6.0-beta.2 in /terminus-terminal
2020-02-13 10:56:30 +01:00
Eugene
6642be3050 Merge pull request #2090 from Eugeny/dependabot/npm_and_yarn/app/node-abi-2.14.0
Bump node-abi from 2.13.0 to 2.14.0 in /app
2020-02-13 10:55:21 +01:00
Eugene
9998fa97f7 Merge pull request #2069 from Eugeny/dependabot/npm_and_yarn/cross-env-7.0.0
Bump cross-env from 6.0.3 to 7.0.0
2020-02-13 10:54:49 +01:00
dependabot-preview[bot]
2b3113b67d Bump xterm-addon-webgl from 0.5.0 to 0.6.0-beta.2 in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.5.0 to 0.6.0-beta.2.
- [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-02-13 09:49:55 +00:00
Eugene
f933c29e5e Merge pull request #2102 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-serialize-0.1.2
Bump xterm-addon-serialize from 0.1.1 to 0.1.2 in /terminus-terminal
2020-02-13 10:48:35 +01:00
Eugene
a908d737a4 Merge pull request #2040 from Eugeny/dependabot/npm_and_yarn/typescript-3.7.5
Bump typescript from 3.7.4 to 3.7.5
2020-02-13 10:48:27 +01:00
Eugene
469b4e4f44 Merge pull request #2103 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-search-0.5.0
Bump xterm-addon-search from 0.4.0 to 0.5.0 in /terminus-terminal
2020-02-13 10:48:11 +01:00
Eugene
13b31d16e8 Merge pull request #2036 from Eugeny/dependabot/npm_and_yarn/style-loader-1.1.3
Bump style-loader from 1.1.2 to 1.1.3
2020-02-13 10:46:26 +01:00
Eugene
afa2eb3a6e Merge pull request #2045 from Eugeny/dependabot/npm_and_yarn/terminus-plugin-manager/axios-0.19.2
Bump axios from 0.19.1 to 0.19.2 in /terminus-plugin-manager
2020-02-13 10:46:06 +01:00
Eugene
01eb26e5c1 Merge pull request #2042 from Eugeny/dependabot/npm_and_yarn/terminus-core/axios-0.19.2
Bump axios from 0.19.1 to 0.19.2 in /terminus-core
2020-02-13 10:45:56 +01:00
Eugene
b967a1ecfa Merge pull request #2110 from Eugeny/dependabot/npm_and_yarn/app/keytar-5.2.0
Bump keytar from 5.1.0 to 5.2.0 in /app
2020-02-13 10:44:52 +01:00
Eugene Pankov
dfe91e98c3 Update windows.yml 2020-02-13 10:42:47 +01:00
Eugene Pankov
6706aa67eb portable build artifact name 2020-02-13 10:42:26 +01:00
Eugene
15fe4f34f9 Merge pull request #2112 from CyrilTaylor/dev/portable_performance
improve the launch performance of portable
2020-02-13 10:41:22 +01:00
Cyril Taylor
9b7c446fd7 improve the launch performance of portable 2020-02-13 10:36:08 +08:00
dependabot-preview[bot]
9225239433 Bump keytar from 5.1.0 to 5.2.0 in /app
Bumps [keytar](https://github.com/atom/node-keytar) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/atom/node-keytar/releases)
- [Commits](https://github.com/atom/node-keytar/compare/v5.1.0...v5.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-12 04:23:08 +00:00
Eugene Pankov
e764b22698 updater 2020-02-11 15:34:56 +01:00
dependabot-preview[bot]
a4d88e4631 Bump @typescript-eslint/parser from 2.17.0 to 2.19.2
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.17.0 to 2.19.2.
- [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.19.2/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-11 04:23:30 +00:00
dependabot-preview[bot]
20da700ad4 Bump @types/ssh2 from 0.5.39 to 0.5.40 in /terminus-ssh
Bumps [@types/ssh2](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ssh2) from 0.5.39 to 0.5.40.
- [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-02-11 04:21:22 +00:00
dependabot-preview[bot]
e4a4937023 Bump xterm-addon-search from 0.4.0 to 0.5.0 in /terminus-terminal
Bumps [xterm-addon-search](https://github.com/xtermjs/xterm.js) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/compare/0.4...0.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-11 04:20:14 +00:00
dependabot-preview[bot]
822b60b454 Bump xterm-addon-serialize from 0.1.1 to 0.1.2 in /terminus-terminal
Bumps xterm-addon-serialize from 0.1.1 to 0.1.2.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 04:20:58 +00:00
Eugene Pankov
72a024c713 fixed wsl shell provider 2020-02-09 18:01:57 +01:00
Eugene Pankov
6132881b8a allow saving terminal state for debugging 2020-02-06 14:52:39 +03:00
Eugene Pankov
1ac22ec563 disable vibrancy while dragging window on buggy windows 10 builds (fixes #949) 2020-02-05 16:02:58 +03:00
Eugene Pankov
ca68905b05 disable background throttling 2020-02-05 15:22:35 +03:00
Eugene Pankov
2470f5f941 LRU fix 2020-02-05 15:22:28 +03:00
Eugene Pankov
fd1ea4fc49 delete saved password when deleting and ssh connection (fixes #1999) 2020-02-05 15:16:51 +03:00
Eugene Pankov
3f8b933d05 lint 2020-02-05 15:16:31 +03:00
dependabot-preview[bot]
3b13f0d73f Bump cross-env from 6.0.3 to 7.0.0
Bumps [cross-env](https://github.com/kentcdodds/cross-env) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/kentcdodds/cross-env/releases)
- [Changelog](https://github.com/kentcdodds/cross-env/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kentcdodds/cross-env/compare/v6.0.3...v7.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-05 11:55:37 +00:00
dependabot-preview[bot]
a261efbc01 Bump node-abi from 2.13.0 to 2.14.0 in /app
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.13.0 to 2.14.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.13.0...v2.14.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-05 11:55:18 +00:00
Eugene Pankov
04d4474648 Update app.ts 2020-02-05 14:54:10 +03:00
Eugene Pankov
4a50c84cfe hotkeys to move tabs around (fixes #2079) 2020-02-05 14:53:26 +03:00
Eugene Pankov
9ca091e592 bumped electron 2020-02-05 14:53:04 +03:00
Eugene Pankov
fa56f30f63 lint 2020-02-05 14:52:53 +03:00
Eugene Pankov
9c19307181 more tab saving fixes 2020-02-05 14:52:33 +03:00
Eugene Pankov
bfd34df41e fixed crash for unknown wsl distros (fixes #2083, fixes #2021) 2020-02-05 14:25:14 +03:00
Eugene Pankov
26ee36458d don't even think about updating if not enabled (fixes #2088) 2020-02-05 14:16:15 +03:00
Eugene Pankov
e99b83dfdc recovery fixes 2020-02-05 14:15:51 +03:00
Eugene Pankov
ceb75323fe restore tab colors during recovery (fixes #1713) 2020-02-05 13:58:18 +03:00
Eugene Pankov
bfb6417865 Merge branch 'master' of github.com:Eugeny/terminus 2020-02-05 13:37:07 +03:00
Eugene Pankov
498564be9a added scrollback saving 2020-02-05 13:37:04 +03:00
Eugene
6c38aa4008 Merge pull request #2064 from Eugeny/dependabot/npm_and_yarn/app/keytar-5.1.0
Bump keytar from 5.0.0 to 5.1.0 in /app
2020-02-05 12:59:38 +03:00
Eugene Pankov
32aaa3d0ff Merge branch 'master' of github.com:Eugeny/terminus 2020-02-05 12:58:41 +03:00
Eugene
7ce5d647da Merge pull request #2067 from Eugeny/dependabot/npm_and_yarn/electron-builder-22.3.2
Bump electron-builder from 22.1.0 to 22.3.2
2020-02-05 12:58:09 +03:00
Eugene Pankov
bf0be7fa0e split electron-builder configuration 2020-02-05 12:57:24 +03:00
Eugene Pankov
a10eb5ff90 set executableArgs for linux 2020-02-05 12:54:21 +03:00
Eugene
c6a27d8893 Merge pull request #2089 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-addon-webgl-0.5.0
Bump xterm-addon-webgl from 0.5.0-beta.7 to 0.5.0 in /terminus-terminal
2020-02-05 12:48:43 +03:00
Eugene
7ee1fb4b76 Merge pull request #2091 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/xterm-4.4.0
Bump xterm from 4.4.0-beta.15 to 4.4.0 in /terminus-terminal
2020-02-05 12:48:10 +03:00
dependabot-preview[bot]
e0f9f558f1 Bump xterm from 4.4.0-beta.15 to 4.4.0 in /terminus-terminal
Bumps [xterm](https://github.com/xtermjs/xterm.js) from 4.4.0-beta.15 to 4.4.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/4.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-05 04:20:35 +00:00
dependabot-preview[bot]
d511bb9fc0 Bump xterm-addon-webgl from 0.5.0-beta.7 to 0.5.0 in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.5.0-beta.7 to 0.5.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-05 04:20:11 +00:00
Eugene
15f99c8ae8 Merge pull request #2081 from CyrilTaylor/dev/portable_for_plugins
Fix: save plugins to path `UserData` for fit portable mode
2020-02-03 16:18:29 +03:00
Cyril Taylor
1027fbfb60 Fix: sentry will use userData before redirect it, ahead of the time 2020-02-03 20:59:46 +08:00
Cyril Taylor
d89abde860 Fix: save plugins to UserData path for fit portable mode 2020-02-02 16:45:06 +08:00
Eugene Pankov
1d76f6b056 re-fixed #2054 2020-02-01 12:15:24 +03:00
Eugene Pankov
f09fb735a7 Update splitTab.component.ts 2020-01-30 19:17:11 +03:00
dependabot-preview[bot]
9ae92ef88c Bump electron-builder from 22.1.0 to 22.3.2
Bumps [electron-builder](https://github.com/electron-userland/electron-builder) from 22.1.0 to 22.3.2.
- [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.1.0...v22.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-29 04:24:32 +00:00
dependabot-preview[bot]
b58d6e1bfd Bump keytar from 5.0.0 to 5.1.0 in /app
Bumps [keytar](https://github.com/atom/node-keytar) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/atom/node-keytar/releases)
- [Commits](https://github.com/atom/node-keytar/compare/v5.0.0...v5.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-28 04:20:25 +00:00
dependabot-preview[bot]
a3a5da8550 Bump axios from 0.19.1 to 0.19.2 in /terminus-plugin-manager
Bumps [axios](https://github.com/axios/axios) from 0.19.1 to 0.19.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/0.19.1...v0.19.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-23 04:22:03 +00:00
dependabot-preview[bot]
178a2e34c6 Bump axios from 0.19.1 to 0.19.2 in /terminus-core
Bumps [axios](https://github.com/axios/axios) from 0.19.1 to 0.19.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/0.19.1...v0.19.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-22 04:28:24 +00:00
dependabot-preview[bot]
b39276feca Bump typescript from 3.7.4 to 3.7.5
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.7.4 to 3.7.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.7.4...v3.7.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-22 04:27:21 +00:00
dependabot-preview[bot]
2c40f0dddc Bump style-loader from 1.1.2 to 1.1.3
Bumps [style-loader](https://github.com/webpack-contrib/style-loader) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/webpack-contrib/style-loader/releases)
- [Changelog](https://github.com/webpack-contrib/style-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/style-loader/compare/v1.1.2...v1.1.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-22 04:25:18 +00:00
158 changed files with 4543 additions and 1382 deletions

View File

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

View File

@@ -79,6 +79,7 @@ rules:
args: after-used
argsIgnorePattern: ^_
no-undef: error
no-var: error
object-curly-spacing:
- error
- always

View File

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

View File

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

View File

@@ -11,7 +11,7 @@ jobs:
- name: Install Node
uses: actions/setup-node@v1
with:
version: 10
node-version: 10
- name: Install deps
run: |
@@ -25,9 +25,6 @@ jobs:
- name: Build native deps
run: scripts/build-native.js
- name: Build typings
run: yarn run build:typings
- name: Webpack
run: yarn run build

View File

@@ -11,7 +11,7 @@ jobs:
- name: Installing Node
uses: actions/setup-node@v1
with:
version: 10
node-version: 10
- name: Install deps
run: |
@@ -25,9 +25,6 @@ jobs:
- name: Build native deps
run: scripts/build-native.js
- name: Build typings
run: yarn run build:typings
- name: Webpack
run: yarn run build
@@ -38,7 +35,7 @@ jobs:
run: scripts/build-macos.js
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
env:
DEBUG: electron-builder,electron-builder:*
#DEBUG: electron-builder,electron-builder:*
GH_TOKEN: ${{ secrets.GH_TOKEN }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}

View File

@@ -11,7 +11,7 @@ jobs:
- name: Installing Node
uses: actions/setup-node@v1
with:
version: 10
node-version: 10
- name: Build
shell: powershell
@@ -39,7 +39,7 @@ jobs:
mkdir artifact-setup
mv dist/*-setup.exe artifact-setup/
mkdir artifact-portable
mv dist/*-portable.exe artifact-portable/
mv dist/*-portable.zip artifact-portable/
- uses: actions/upload-artifact@master
name: Upload installer

View File

@@ -35,6 +35,10 @@
---
# Portable
For portable in windows, user can create folder `data` at the same directory as `Terminal.exe` to save the settings.
# Plugins
Plugins and themes can be installed directly from the Settings view inside Terminus.
@@ -102,6 +106,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
</tr>
</table>

View File

@@ -1,4 +1,5 @@
import { app, ipcMain, Menu, Tray, shell } from 'electron'
// eslint-disable-next-line no-duplicate-imports
import * as electron from 'electron'
import { loadConfig } from './config'
import { Window, WindowOptions } from './window'
@@ -23,13 +24,14 @@ export class Application {
app.commandLine.appendSwitch('disable-http-cache')
app.commandLine.appendSwitch('lang', 'EN')
app.allowRendererProcessReuse = false
for (const flag of configData.flags || [['force_discrete_gpu', '0']]) {
app.commandLine.appendSwitch(flag[0], flag[1])
}
}
init () {
init (): void {
electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
}
@@ -50,20 +52,20 @@ export class Application {
return window
}
broadcast (event, ...args) {
for (let window of this.windows) {
broadcast (event: string, ...args): void {
for (const window of this.windows) {
window.send(event, ...args)
}
}
async send (event, ...args) {
async send (event: string, ...args): Promise<void> {
if (!this.hasWindows()) {
await this.newWindow()
}
this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args)
}
enableTray () {
enableTray (): void {
if (this.tray) {
return
}
@@ -74,7 +76,7 @@ export class Application {
this.tray = new Tray(`${app.getAppPath()}/assets/tray.png`)
}
this.tray.on('click', () => setTimeout(() => this.focus()));
this.tray.on('click', () => setTimeout(() => this.focus()))
const contextMenu = Menu.buildFromTemplate([{
label: 'Show',
@@ -88,18 +90,18 @@ export class Application {
this.tray.setToolTip(`Terminus ${app.getVersion()}`)
}
disableTray () {
disableTray (): void {
if (this.tray) {
this.tray.destroy()
this.tray = null
}
}
hasWindows () {
hasWindows (): boolean {
return !!this.windows.length
}
focus () {
focus (): void {
for (let window of this.windows) {
window.show()
}
@@ -185,7 +187,7 @@ export class Application {
},
},
],
}
},
]
Menu.setApplicationMenu(Menu.buildFromTemplate(template))

View File

@@ -1,6 +1,6 @@
import { app } from 'electron'
export function parseArgs (argv, cwd) {
export function parseArgs (argv: string[], cwd: string): any {
if (argv[0].includes('node')) {
argv = argv.slice(1)
}
@@ -20,25 +20,25 @@ export function parseArgs (argv, cwd) {
return yargs.option('escape', {
alias: 'e',
type: 'boolean',
describe: 'Perform shell escaping'
describe: 'Perform shell escaping',
}).positional('text', {
type: 'string'
type: 'string',
})
})
.version('version', '', app.getVersion())
.option('debug', {
alias: 'd',
describe: 'Show DevTools on start',
type: 'boolean'
type: 'boolean',
})
.option('hidden', {
describe: 'Start minimized',
type: 'boolean'
type: 'boolean',
})
.option('version', {
alias: 'v',
describe: 'Show version and exit',
type: 'boolean'
type: 'boolean',
})
.help('help')
.parse(argv.slice(1))

View File

@@ -1,11 +1,10 @@
import './portable'
import './sentry'
import './lru'
import { app, ipcMain, Menu } from 'electron'
import { parseArgs } from './cli'
import { Application } from './app'
import electronDebug = require('electron-debug')
import * as path from 'path'
import * as fs from 'fs'
if (!process.env.TERMINUS_PLUGINS) {
process.env.TERMINUS_PLUGINS = ''
@@ -13,14 +12,6 @@ if (!process.env.TERMINUS_PLUGINS) {
const application = new Application()
if (process.env.PORTABLE_EXECUTABLE_DIR) {
const portableData = path.join(process.env.PORTABLE_EXECUTABLE_DIR, 'terminus-data')
if (!fs.existsSync(portableData)) {
fs.mkdirSync(portableData)
}
app.setPath('userData', portableData)
}
ipcMain.on('app:new-window', () => {
application.newWindow()
})
@@ -68,8 +59,8 @@ app.on('ready', () => {
label: 'New window',
click () {
this.app.newWindow()
}
}
},
},
]))
}
application.init()

View File

@@ -1,13 +1,15 @@
let lru = require('lru-cache')({ max: 256, maxAge: 250 })
let fs = require('fs')
let origLstat = fs.realpathSync.bind(fs)
import * as createLRU from 'lru-cache'
import * as fs from 'fs'
const lru = createLRU({ max: 256, maxAge: 250 })
const origLstat = fs.realpathSync.bind(fs)
// NB: The biggest offender of thrashing realpathSync is the node module system
// itself, which we can't get into via any sane means.
require('fs').realpathSync = function (p) {
let r = lru.get(p)
if (r) return r
if (r) {
return r
}
r = origLstat(p)
lru.set(p, r)

24
app/lib/portable.ts Executable file
View File

@@ -0,0 +1,24 @@
import * as path from 'path'
import * as fs from 'fs'
let appPath: string | null = null
try {
appPath = path.dirname(require('electron').app.getPath('exe'))
} catch {
appPath = path.dirname(require('electron').remote.app.getPath('exe'))
}
if (null != appPath) {
if(fs.existsSync(path.join(appPath, 'terminus-data'))) {
fs.renameSync(path.join(appPath, 'terminus-data'), path.join(appPath, 'data'))
}
const portableData = path.join(appPath, 'data')
if (fs.existsSync(portableData)) {
console.log('reset user data to ' + portableData)
try {
require('electron').app.setPath('userData', portableData)
} catch {
require('electron').remote.app.setPath('userData', portableData)
}
}
}

0
app/lib/sentry.ts Normal file → Executable file
View File

View File

@@ -27,6 +27,8 @@ export class Window {
private windowConfig: ElectronConfig
private windowBounds: Rectangle
private closing = false
private lastVibrancy: {enabled: boolean, type?: string} | null = null
private disableVibrancyWhileDragging = false
get visible$ (): Observable<boolean> { return this.visible }
@@ -48,6 +50,7 @@ export class Window {
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'sentry.js'),
backgroundThrottling: false,
},
frame: false,
show: false,
@@ -56,14 +59,14 @@ export class Window {
if (this.windowBounds) {
Object.assign(bwOptions, this.windowBounds)
const closestDisplay = screen.getDisplayNearestPoint( {x: this.windowBounds.x, y: this.windowBounds.y} )
const closestDisplay = screen.getDisplayNearestPoint( { x: this.windowBounds.x, y: this.windowBounds.y } )
const [left1, top1, right1, bottom1] = [this.windowBounds.x, this.windowBounds.y, this.windowBounds.x + this.windowBounds.width, this.windowBounds.y + this.windowBounds.height];
const [left2, top2, right2, bottom2] = [closestDisplay.bounds.x, closestDisplay.bounds.y, closestDisplay.bounds.x + closestDisplay.bounds.width, closestDisplay.bounds.y + closestDisplay.bounds.height];
const [left1, top1, right1, bottom1] = [this.windowBounds.x, this.windowBounds.y, this.windowBounds.x + this.windowBounds.width, this.windowBounds.y + this.windowBounds.height]
const [left2, top2, right2, bottom2] = [closestDisplay.bounds.x, closestDisplay.bounds.y, closestDisplay.bounds.x + closestDisplay.bounds.width, closestDisplay.bounds.y + closestDisplay.bounds.height]
if ((left2 > right1 || right2 < left1 || top2 > bottom1 || bottom2 < top1) && !maximized) {
bwOptions.x = closestDisplay.bounds.width / 2 - bwOptions.width / 2;
bwOptions.y = closestDisplay.bounds.height / 2 - bwOptions.height / 2;
bwOptions.x = closestDisplay.bounds.width / 2 - bwOptions.width / 2
bwOptions.y = closestDisplay.bounds.height / 2 - bwOptions.height / 2
}
}
@@ -116,12 +119,13 @@ export class Window {
})
}
setVibrancy (enabled: boolean, type?: string) {
setVibrancy (enabled: boolean, type?: string): void {
this.lastVibrancy = { enabled, type }
if (process.platform === 'win32') {
if (parseFloat(os.release()) >= 10) {
let attribValue = AccentState.ACCENT_DISABLED
if (enabled) {
if (parseInt(os.release().split('.')[2]) >= 17063 && type === 'fluent') {
if (type === 'fluent') {
attribValue = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND
} else {
attribValue = AccentState.ACCENT_ENABLE_BLURBEHIND
@@ -131,26 +135,28 @@ export class Window {
} else {
DwmEnableBlurBehindWindow(this.window, enabled)
}
} else {
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
}
}
show () {
show (): void {
this.window.show()
}
focus () {
focus (): void {
this.window.focus()
}
send (event, ...args) {
send (event: string, ...args): void {
if (!this.window) {
return
}
this.window.webContents.send(event, ...args)
}
isDestroyed () {
return !this.window || this.window.isDestroyed();
isDestroyed (): boolean {
return !this.window || this.window.isDestroyed()
}
private setupWindowManagement () {
@@ -293,6 +299,29 @@ export class Window {
})
this.window.webContents.on('new-window', event => event.preventDefault())
ipcMain.on('window-set-disable-vibrancy-while-dragging', (_event, value) => {
this.disableVibrancyWhileDragging = value
})
this.window.on('will-move', () => {
if (!this.lastVibrancy?.enabled || !this.disableVibrancyWhileDragging) {
return
}
let timeout: number|null = null
const oldVibrancy = this.lastVibrancy
this.setVibrancy(false)
const onMove = () => {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
this.window.off('move', onMove)
this.setVibrancy(oldVibrancy.enabled, oldVibrancy.type)
}, 500)
}
this.window.on('move', onMove)
})
}
private destroy () {

View File

@@ -13,22 +13,22 @@
"watch": "webpack --progress --color --watch"
},
"dependencies": {
"@angular/animations": "7.2.8",
"@angular/common": "7.2.8",
"@angular/compiler": "7.2.8",
"@angular/core": "7.2.8",
"@angular/forms": "7.2.8",
"@angular/platform-browser": "7.2.8",
"@angular/platform-browser-dynamic": "7.2.8",
"@ng-bootstrap/ng-bootstrap": "^4.2.2",
"@angular/animations": "9.0.4",
"@angular/common": "9.0.4",
"@angular/compiler": "9.0.4",
"@angular/core": "9.0.4",
"@angular/forms": "9.0.4",
"@angular/platform-browser": "9.0.4",
"@angular/platform-browser-dynamic": "9.0.4",
"@ng-bootstrap/ng-bootstrap": "^6.0.0",
"devtron": "1.4.0",
"electron-config": "2.0.0",
"electron-debug": "^3.0.1",
"electron-is-dev": "1.1.0",
"electron-updater": "^4.2.0",
"electron-updater": "^4.2.2",
"fontmanager-redux": "0.4.0",
"js-yaml": "3.13.1",
"keytar": "^5.0.0",
"keytar": "^5.4.0",
"mz": "^2.7.0",
"ngx-toastr": "^10.2.0",
"node-pty": "^0.10.0-beta2",
@@ -37,10 +37,11 @@
"rxjs": "^6.5.4",
"rxjs-compat": "^6.5.4",
"yargs": "^15.1.0",
"zone.js": "^0.8.29"
"zone.js": "^0.10.2"
},
"optionalDependencies": {
"macos-native-processlist": "^1.0.2",
"serialport": "^8.0.7",
"windows-blurbehind": "^1.0.1",
"windows-native-registry": "^1.0.17",
"windows-process-tree": "^0.2.4",
@@ -49,6 +50,6 @@
"devDependencies": {
"@types/mz": "0.0.32",
"@types/node": "12.7.12",
"node-abi": "^2.13.0"
"node-abi": "^2.15.0"
}
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
@@ -7,7 +8,7 @@ export function getRootModule (plugins: any[]) {
const imports = [
BrowserModule,
...plugins,
NgbModule.forRoot(),
NgbModule,
ToastrModule.forRoot({
positionClass: 'toast-bottom-center',
toastClass: 'toast',

View File

@@ -21,8 +21,7 @@ if (process.env.TERMINUS_DEV) {
const builtinPluginsPath = process.env.TERMINUS_DEV ? path.dirname(require('electron').remote.app.getAppPath()) : path.join((process as any).resourcesPath, 'builtin-plugins')
const userPluginsPath = path.join(
require('electron').remote.app.getPath('appData'),
'terminus',
require('electron').remote.app.getPath('userData'),
'plugins',
)

View File

@@ -2,61 +2,111 @@
# yarn lockfile v1
"@angular/animations@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-7.2.8.tgz#0285364c839c660a934ab0f753ec21424bfb292e"
integrity sha512-dJn9koYukyz15TouBc+z5z9fdThDk+bKgdlij25eYSu5Mpmtk04gB4eIMQA97K0UDh1d4YukgSJ5w3ZIk0m8DQ==
dependencies:
tslib "^1.9.0"
"@angular/animations@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.0.4.tgz#c95c601dfb8fc4e96aee577c9c0f6cf18b64e5d7"
integrity sha512-zTCgrIAA9FYPMbqqpQnoNltiLR58q0FMfzP2t96q/1tjyVy/Y/IaNgVQ7eL0HeQ0nG6IAzQ1HVx8Xeneg4Yj5Q==
"@angular/common@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-7.2.8.tgz#660c816b6f08cd2919a6efb7465397e4ff14d265"
integrity sha512-LgOhf68+LPndGZhtnUlGFd2goReXYmHzaFZW8gCEi9aC+H+Io8bjYh0gkH3xDreevEOe3f0z6coXNFLIxSmTuA==
dependencies:
tslib "^1.9.0"
"@angular/common@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.0.4.tgz#7d168b22c5c43e72112d0a19242eca22b62bb4f3"
integrity sha512-F3qoYrceEdCd5SlgObcbSIIdKfRXgyTBO2gbbArQHFe4GvewkH3isTn5uqAF6sfJlb7rXWZGrD6C3d9brw/fEw==
"@angular/compiler@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-7.2.8.tgz#9d9c1515e99914399e6915c1c90484b1d255560b"
integrity sha512-PrU97cTsOdofpaDkxK0rWUA/CGd0u6ESOI6XvFVm5xH9zJInsdY8ShSHklnr1JJnss70e1dGKZbZq32OChxWMw==
dependencies:
tslib "^1.9.0"
"@angular/compiler@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.4.tgz#038c9cdbf76f1cce47bd1b355c7d212cc89b18f9"
integrity sha512-+Ku8RUU00yHaKVkVw6YIfM3c5Gmvas5gJcEleiagkLbc1f/jKk1cY4gaUP6xn4TLypFM7NQglneWd+E+8wh0hQ==
"@angular/core@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-7.2.8.tgz#6586d9b6c6321c80119b3f3e2bd0edbb32d0b649"
integrity sha512-QKwug2kWJC00zm2rvmD9mCJzsOkMVhSu8vqPWf83poWTh8+F9aIVWcy29W0VoGpBkSchOnK8hf9DnKVv28j9nw==
dependencies:
tslib "^1.9.0"
"@angular/core@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.4.tgz#6baa5ec6c594b47de541e47f4aa37241adec393a"
integrity sha512-6RqQb1GO2uglSlgiGbxhvy8plztZtABCWLRn0X+T1PnrxoqgxqA5WkKJjGxao+1M/ECW1V0fw4Xy7DE6KvAJwQ==
"@angular/forms@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-7.2.8.tgz#adf194088495822d55dcf3e5bf69196dcf19465d"
integrity sha512-lbSX4IHFHz/c4e2RHiPpL8MJlzDkCuQEHnqsujDaV2X9o9fApS6+C1X4x7Z2XDKqonmeX+aHQwv9+SLejX6OyQ==
dependencies:
tslib "^1.9.0"
"@angular/forms@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.0.4.tgz#31edac9917e592695a5c12b846e93dbda6afc510"
integrity sha512-WyfZ2u2JzGrwkxQmfxHvZMoYHEGfoUL+JlSXa2Sy3T/FPGNckHzIzggqweJij/qGjabWLabZDla4vak42f+4PA==
"@angular/platform-browser-dynamic@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.8.tgz#e82768900cedfa75bf453263f931a9f90f7aaab2"
integrity sha512-nOJt28A5pRn4mdL8y98V7bA6OOdMRjsQAcWCr/isGYF0l1yDC0ijUGWkHuRtj3z1/9tmERN0BLXx+xs1h4JhCQ==
dependencies:
tslib "^1.9.0"
"@angular/platform-browser-dynamic@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.4.tgz#343bd43fe00a279a737e02c16dd8790dc0da93a8"
integrity sha512-9vAn2QH07khuF4n7kyMJzgE6l30Yxg1AGd8GtOfa/4nbna+EZxFVYOkto9bpv4uEwDr9o7QrFLplko9a8xs7kg==
"@angular/platform-browser@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-7.2.8.tgz#11096727b99bf3d7fd82a00a3a468b933c9713bd"
integrity sha512-SizCRMc7Or27g2CugcqWnaAikRPfgLgRvb9GFFGpcgoq8CRfOVwkyR5dFZuqN39H+uwtwuTMP5OUYhZcrFNKug==
dependencies:
tslib "^1.9.0"
"@angular/platform-browser@9.0.4":
version "9.0.4"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.0.4.tgz#03853b435c3b964660727ac9d7e15912c920cdb8"
integrity sha512-mbiqmw0rDGPxEgKVgDuK7yZvtgjJmzpMGBYAMwkQ9YIE0SoA5XP0NvZiFkHZqDXwLgCv2IJ/kvkhfCBwnBKCXQ==
"@ng-bootstrap/ng-bootstrap@^4.2.2":
version "4.2.2"
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.2.2.tgz#a1c3a9576656cb4f793bbc3df56dfbdeb098f2fb"
integrity sha512-v8QmC17bv9he5Ep6zutaI9aQ2w/2NqySP0fejOKe7cacKpGUqsLIakpyd2FD7mfZu7pSCCtHYpRWR+h6yq+Ngg==
"@ng-bootstrap/ng-bootstrap@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-6.0.0.tgz#03b80acd711dd38a653b34339224d5063c50bd62"
integrity sha512-ho0Ssw+kwpGzc+Rvtu2pRSrcbduECMf9+uekhOMB1nzhUfF2vJQnTDpPfHZQgU/ukTMEJWvby5vcXJoPtHgE+w==
"@serialport/binding-abstract@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-8.0.6.tgz#78e6d7995a95c46d480445303e6f32ca4d53edcd"
integrity sha512-1swwUVoRyQ9ubxrkJ8JPppykohUpTAP4jkGr36e9NjbVocSPfqeX6tFZFwl/IdUlwJwxGdbKDqq7FvXniCQUMw==
dependencies:
tslib "^1.9.0"
debug "^4.1.1"
"@serialport/binding-mock@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/binding-mock/-/binding-mock-8.0.6.tgz#41a8f827269c6a0e58546513a274e12023134155"
integrity sha512-BIbY5/PsDDo0QWDNCCxDgpowAdks+aZR8BOsEtK2GoASTTcJCy1fBwPIfH870o7rnbH901wY3C+yuTfdOvSO9A==
dependencies:
"@serialport/binding-abstract" "^8.0.6"
debug "^4.1.1"
"@serialport/bindings@^8.0.7":
version "8.0.7"
resolved "https://registry.yarnpkg.com/@serialport/bindings/-/bindings-8.0.7.tgz#2a58f60f1e24ee4549be6f9e0e37b3359d038a1c"
integrity sha512-IqudDL8ne2Y2S0W5fKA6wdgHCIA2e2OIaPVYhGy6duE6legNHFY+05CLicHAyAeTocXmHU7rVNxzVQrOG5tM4g==
dependencies:
"@serialport/binding-abstract" "^8.0.6"
"@serialport/parser-readline" "^8.0.6"
bindings "^1.5.0"
debug "^4.1.1"
nan "^2.14.0"
prebuild-install "^5.3.0"
"@serialport/parser-byte-length@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-8.0.6.tgz#efb6195692b1088e6c095fd43bae196fc30674d0"
integrity sha512-92mrFxFEvq3gRvSM7ANK/jfbmHslz91a5oYJy/nbSn4H/MCRXjxR2YOkQgVXuN+zLt+iyDoW3pcOP4Sc1nWdqQ==
"@serialport/parser-cctalk@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-8.0.6.tgz#4134a3c479d465df3b152a21e16b8ecf1bc818c3"
integrity sha512-pqtCYQPgxnxHygiXUPCfgX7sEx+fdR/ObjpscidynEULUq2fFrC5kBkrxRbTfHRtTaU2ii9DyjFq0JVRCbhI0Q==
"@serialport/parser-delimiter@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-8.0.6.tgz#0e467cb07a40bd3006835c48e488666bd7de22cc"
integrity sha512-ogKOcPisPMlVtirkuDu3SFTF0+xT0ijxoH7XjpZiYL41EVi367MwuCnEmXG+dEKKnF0j9EPqOyD2LGSJxaFmhQ==
"@serialport/parser-readline@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-8.0.6.tgz#8a6a296a1bec08a4855bf7a62bc6335d52972e4a"
integrity sha512-OYBT2mpczh9QUI3MTw8j0A0tIlPVjpVipvuVnjRkYwxrxPeq04RaLFhaDpuRzua5rTKMt89c1y3btYeoDXMjAA==
dependencies:
"@serialport/parser-delimiter" "^8.0.6"
"@serialport/parser-ready@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-8.0.6.tgz#d6e95e53ee70d298ae0b4147995007f4ba62651c"
integrity sha512-xcEqv4rc119WR5JzAuu8UeJOlAwET2PTdNb6aIrrLlmTxhvuBbuRFcsnF3BpH9jUL30Kh7a6QiNXIwVG+WR/1Q==
"@serialport/parser-regex@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-8.0.6.tgz#70aa1abe31899d1b986f44cfb6777a76e26755bf"
integrity sha512-J8KY75Azz5ZyExmyM5YfUxbXOWBkZCytKgCCmZ966ttwZS0bUZOuoCaZj2Zp4VILJAiLuxHoqc0foi67Fri5+g==
"@serialport/stream@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-8.0.6.tgz#3395dbac788c00797c2435c61c2ecb4e99fbf41d"
integrity sha512-ym1PwM0rwLrj90vRBB66I1hwMXbuMw9wGTxqns75U3N/tuNFOH85mxXaYVF2TpI66aM849NoI1jMm50fl9equg==
dependencies:
debug "^4.1.1"
"@types/color-name@^1.1.1":
version "1.1.1"
@@ -80,10 +130,12 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==
"@types/semver@^6.0.2":
version "6.2.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
"@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:
"@types/node" "*"
JSONStream@^1.3.4, JSONStream@^1.3.5:
version "1.3.5"
@@ -271,6 +323,13 @@ bin-links@^1.1.2:
graceful-fs "^4.1.11"
write-file-atomic "^2.3.0"
bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
dependencies:
file-uri-to-path "1.0.0"
bl@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
@@ -316,10 +375,10 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
builder-util-runtime@8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz#3163fffc078e6b8f3dd5b6eb12a8345573590682"
integrity sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==
builder-util-runtime@8.6.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.0.tgz#b7007c30126da9a90e99932128d2922c8c178649"
integrity sha512-WTDhTUVrm7zkFyd6Qn7AXgmWifjpZ/fYnEdV3XCOIDMNNb/KPddBTbQ8bUlxxVeuOYlhGpcLUypG+4USdGL1ww==
dependencies:
debug "^4.1.1"
sax "^1.2.4"
@@ -798,19 +857,19 @@ electron-localshortcut@^3.1.0:
keyboardevent-from-electron-accelerator "^1.1.0"
keyboardevents-areequal "^0.2.1"
electron-updater@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.0.tgz#f9ecfc657f65ead737d42b9efecf628d3756b550"
integrity sha512-GuS3g7HDh17x/SaFjxjswlWUaKHczksYkV2Xc5CKj/bZH0YCvTSHtOmnBAdAmCk99u/71p3zP8f0jIqDfGcjww==
electron-updater@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.2.tgz#57e106bffad16f71b1ffa3968a52a1b71c8147e6"
integrity sha512-e/OZhr5tLW0GcgmpR5wD0ImxgKMa8pPoNWRcwRyMzTL9pGej7+ORp0t9DtI5ZBHUbObIoEbrk+6EDGUGtJf+aA==
dependencies:
"@types/semver" "^6.0.2"
builder-util-runtime "8.4.0"
"@types/semver" "^7.1.0"
builder-util-runtime "8.6.0"
fs-extra "^8.1.0"
js-yaml "^3.13.1"
lazy-val "^1.0.4"
lodash.isequal "^4.5.0"
pako "^1.0.10"
semver "^6.3.0"
pako "^1.0.11"
semver "^7.1.3"
emoji-regex@^8.0.0:
version "8.0.0"
@@ -925,6 +984,11 @@ figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
find-npm-prefix@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf"
@@ -1485,10 +1549,10 @@ keyboardevents-areequal@^0.2.1:
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
keytar@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.0.0.tgz#c89b6b7a4608fd7af633d9f8474b1a7eb97cbe6f"
integrity sha512-a5UheK59YOlJf9i+2Osaj/kkH6mK0RCHVMtJ84u6ZfbfRIbOJ/H4b5VlOF/LgNHF6s78dRSBzZnvIuPiBKv6wg==
keytar@^5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.4.0.tgz#71d8209e7dd2fe99008c243791350a6bd6ceab67"
integrity sha512-Ta0RtUmkq7un177SPgXKQ7FGfGDV4xvsV0cGNiWVEzash5U0wyOsXpwfrK2+Oq+hHvsvsbzIZUUuJPimm3avFw==
dependencies:
nan "2.14.0"
prebuild-install "5.3.3"
@@ -1925,10 +1989,10 @@ ngx-toastr@^10.2.0:
dependencies:
tslib "^1.9.0"
node-abi@^2.13.0, node-abi@^2.7.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.13.0.tgz#e2f2ec444d0aca3ea1b3874b6de41d1665828f63"
integrity sha512-9HrZGFVTR5SOu3PZAnAY2hLO36aW1wmA+FDsVkr85BTST32TLCA1H/AEcatVRAsWLyXS3bqUDYCAjq5/QGuSTA==
node-abi@^2.15.0, node-abi@^2.7.0:
version "2.15.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.15.0.tgz#51d55cc711bd9e4a24a572ace13b9231945ccb10"
integrity sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg==
dependencies:
semver "^5.4.1"
@@ -2395,10 +2459,10 @@ pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0:
unique-filename "^1.1.1"
which "^1.3.1"
pako@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
pako@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
parallel-transform@^1.1.0:
version "1.1.0"
@@ -2464,7 +2528,7 @@ pkg-up@^2.0.0:
dependencies:
find-up "^2.1.0"
prebuild-install@5.3.3:
prebuild-install@5.3.3, prebuild-install@^5.3.0:
version "5.3.3"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e"
integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==
@@ -2840,16 +2904,32 @@ semver-diff@^2.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6"
integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==
semver@~5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
serialport@^8.0.7:
version "8.0.7"
resolved "https://registry.yarnpkg.com/serialport/-/serialport-8.0.7.tgz#9f28b1b7c47333a0962f5505a1c3feb1d90f89a9"
integrity sha512-R9bfNebs2dblYf5sD/Aaa7j8+siP4X7TGT02lqHM9DF5fyjlrPGXmsLw9+LKOz1AvjGjkxf2NzBVnDpqRX7clQ==
dependencies:
"@serialport/binding-mock" "^8.0.6"
"@serialport/bindings" "^8.0.7"
"@serialport/parser-byte-length" "^8.0.6"
"@serialport/parser-cctalk" "^8.0.6"
"@serialport/parser-delimiter" "^8.0.6"
"@serialport/parser-readline" "^8.0.6"
"@serialport/parser-ready" "^8.0.6"
"@serialport/parser-regex" "^8.0.6"
"@serialport/stream" "^8.0.6"
debug "^4.1.1"
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -3536,7 +3616,7 @@ yargs@^15.1.0:
y18n "^4.0.0"
yargs-parser "^16.1.0"
zone.js@^0.8.29:
version "0.8.29"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.29.tgz#8dce92aa0dd553b50bc5bfbb90af9986ad845a12"
integrity sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==
zone.js@^0.10.2:
version "0.10.2"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.2.tgz#67ca084b3116fc33fc40435e0d5ea40a207e392e"
integrity sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg==

60
electron-builder.yml Normal file
View File

@@ -0,0 +1,60 @@
---
appId: org.terminus
productName: Terminus
compression: normal
afterSign: "./build/mac/afterSignHook.js"
files:
- "**/*"
- dist
extraResources:
- builtin-plugins
- extras
publish:
- provider: github
win:
icon: "./build/windows/icon.ico"
artifactName: terminus-${version}-portable.${ext}
rfc3161TimeStampServer: http://sha256timestamp.ws.symantec.com/sha256/timestamp
nsis:
oneClick: false
artifactName: terminus-${version}-setup.${ext}
installerIcon: "./build/windows/icon.ico"
mac:
category: public.app-category.video
icon: "./build/mac/icon.icns"
artifactName: terminus-${version}-macos.${ext}
hardenedRuntime: true
entitlements: "./build/mac/entitlements.plist"
entitlementsInherit: "./build/mac/entitlements.plist"
extendInfo:
NSRequiresAquaSystemAppearance: false
pkg:
artifactName: terminus-${version}-macos.pkg
linux:
category: Utilities
icon: "./build/icons"
artifactName: terminus-${version}-linux.${ext}
executableArgs:
- "--no-sandbox"
snap:
plugs:
- default
- system-files
- system-observe
deb:
depends:
- gconf2
- gconf-service
- libnotify4
- libsecret-1-0
- libappindicator1
- libxtst6
- libnss3
afterInstall: build/linux/after-install.tpl
rpm:
depends:
- screen
- gnome-python2-gnomekeyring

Binary file not shown.

Binary file not shown.

View File

@@ -1,33 +1,33 @@
{
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.12.0",
"@sentry/cli": "^1.49.0",
"@sentry/electron": "^1.0.0",
"@fortawesome/fontawesome-free": "^5.12.1",
"@sentry/cli": "^1.51.1",
"@sentry/electron": "^1.2.1",
"@types/electron-config": "^3.2.2",
"@types/electron-debug": "^2.1.0",
"@types/js-yaml": "^3.12.1",
"@types/node": "12.7.12",
"@types/webpack-env": "1.15.0",
"@typescript-eslint/eslint-plugin": "^2.13.0",
"@typescript-eslint/parser": "^2.17.0",
"@typescript-eslint/eslint-plugin": "^2.21.0",
"@typescript-eslint/parser": "^2.21.0",
"apply-loader": "2.0.0",
"awesome-typescript-loader": "^5.0.0",
"core-js": "^3.6.4",
"cross-env": "6.0.3",
"cross-env": "7.0.0",
"css-loader": "3.4.2",
"electron": "^7.1.10",
"electron-builder": "22.1.0",
"electron": "^8.0.2",
"electron-builder": "22.3.2",
"electron-download": "^4.1.1",
"electron-installer-snap": "^5.0.0",
"electron-notarize": "^0.1.1",
"electron-rebuild": "^1.9.0",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-import": "^2.20.1",
"file-loader": "^5.0.2",
"graceful-fs": "^4.2.2",
"html-loader": "0.5.5",
"json-loader": "0.5.7",
"node-abi": "^2.12.0",
"node-abi": "^2.15.0",
"node-gyp": "^6.1.0",
"node-sass": "^4.13.0",
"npmlog": "4.1.2",
@@ -42,101 +42,29 @@
"shelljs": "0.8.3",
"source-code-pro": "^2.30.2",
"source-sans-pro": "3.6.0",
"style-loader": "^1.1.2",
"style-loader": "^1.1.3",
"svg-inline-loader": "^0.8.0",
"to-string-loader": "1.1.6",
"tslib": "^1.10.0",
"typedoc": "^0.16.7",
"typescript": "^3.7.4",
"tslib": "^1.11.1",
"typedoc": "^0.16.10",
"typescript": "^3.8.2",
"url-loader": "^3.0.0",
"val-loader": "2.1.0",
"webpack": "^5.0.0-beta.12",
"webpack": "^5.0.0-beta.13",
"webpack-cli": "^3.3.10",
"yaml-loader": "0.5.0"
},
"resolutions": {
"*/node-abi": "^2.8.0"
},
"build": {
"appId": "org.terminus",
"productName": "Terminus",
"compression": "normal",
"afterSign": "./build/mac/afterSignHook.js",
"files": [
"**/*",
"dist"
],
"extraResources": [
"builtin-plugins",
"extras"
],
"win": {
"icon": "./build/windows/icon.ico",
"artifactName": "terminus-${version}-setup.exe",
"rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp"
},
"nsis": {
"oneClick": false,
"artifactName": "terminus-${version}-setup.${ext}",
"installerIcon": "./build/windows/icon.ico"
},
"publish": [
{
"provider": "github"
}
],
"portable": {
"artifactName": "terminus-${version}-portable.exe"
},
"mac": {
"category": "public.app-category.video",
"icon": "./build/mac/icon.icns",
"artifactName": "terminus-${version}-macos.${ext}",
"hardenedRuntime": true,
"entitlements": "./build/mac/entitlements.plist",
"entitlementsInherit": "./build/mac/entitlements.plist",
"extendInfo": {
"NSRequiresAquaSystemAppearance": false
}
},
"pkg": {
"artifactName": "terminus-${version}-macos.pkg"
},
"linux": {
"category": "Utilities",
"icon": "./build/icons",
"artifactName": "terminus-${version}-linux.${ext}"
},
"snap": {
"plugs": ["default", "system-files", "system-observe"]
},
"deb": {
"depends": [
"gconf2",
"gconf-service",
"libnotify4",
"libsecret-1-0",
"libappindicator1",
"libxtst6",
"libnss3"
],
"afterInstall": "build/linux/after-install.tpl"
},
"rpm": {
"depends": [
"screen",
"gnome-python2-gnomekeyring"
]
}
"*/node-abi": "^2.14.0"
},
"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",
"build:typings": "tsc --project terminus-core/tsconfig.typings.json && tsc --project terminus-settings/tsconfig.typings.json && tsc --project terminus-terminal/tsconfig.typings.json && tsc --project terminus-plugin-manager/tsconfig.typings.json && tsc --project terminus-ssh/tsconfig.typings.json",
"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",
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
"start": "cross-env TERMINUS_DEV=1 electron app --debug",
"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",
"lint": "eslint --ext ts */src",
"lint": "eslint --ext ts */src */lib",
"postinstall": "node ./scripts/install-deps.js"
},
"repository": "eugeny/terminus"

9
scripts/build-typings.js Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env node
const sh = require('shelljs')
const vars = require('./vars')
const log = require('npmlog')
vars.builtinPlugins.forEach(plugin => {
log.info('typings', plugin)
sh.exec(`npx tsc --project ${plugin}/tsconfig.typings.json`)
})

View File

@@ -7,7 +7,7 @@ const isCI = !!process.env.GITHUB_REF
builder({
dir: true,
win: ['nsis', 'portable'],
win: ['nsis', 'zip'],
config: {
extraMetadata: {
version: vars.version,

View File

@@ -21,6 +21,7 @@ exports.builtinPlugins = [
'terminus-community-color-schemes',
'terminus-plugin-manager',
'terminus-ssh',
'terminus-serial',
]
exports.bundledModules = [
'@angular',

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-community-color-schemes",
"version": "1.0.99-nightly.0",
"version": "1.0.104-nightly.0",
"description": "Community color schemes for Terminus",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -0,0 +1,14 @@
{
"extends": "../tsconfig.json",
"exclude": ["node_modules", "dist", "typings"],
"compilerOptions": {
"baseUrl": "src",
"emitDeclarationOnly": true,
"declaration": true,
"declarationDir": "./typings",
"paths": {
"terminus-*": ["../../terminus-*"],
"*": ["../../app/node_modules/*"]
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-core",
"version": "1.0.99-nightly.0",
"version": "1.0.104-nightly.0",
"description": "Terminus core",
"keywords": [
"terminus-builtin-plugin"
@@ -30,7 +30,7 @@
"ng2-dnd": "^5.0.2",
"ngx-perfect-scrollbar": "^8.0.0",
"shell-escape": "^0.2.0",
"uuid": "^3.3.2",
"uuid": "^7.0.1",
"winston": "^3.2.1"
},
"peerDependencies": {

View File

@@ -1,12 +1,13 @@
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
export { TabHeaderComponent } from '../components/tabHeader.component'
export { SplitTabComponent, SplitContainer } from '../components/splitTab.component'
export { TabRecoveryProvider, RecoveredTab } from './tabRecovery'
export { TabRecoveryProvider, RecoveredTab, RecoveryToken } from './tabRecovery'
export { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider'
export { ConfigProvider } from './configProvider'
export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider'
export { Theme } from './theme'
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
export { SelectorOption } from './selector'
export { AppService } from '../services/app.service'
export { ConfigService } from '../services/config.service'
@@ -19,3 +20,4 @@ export { HostAppService, Platform } from '../services/hostApp.service'
export { ShellIntegrationService } from '../services/shellIntegration.service'
export { ThemesService } from '../services/themes.service'
export { TabsService } from '../services/tabs.service'
export * from '../utils'

View File

@@ -0,0 +1,5 @@
export interface SelectorOption<T> {
name: string
description?: string
result: T
}

View File

@@ -12,6 +12,12 @@ export interface RecoveredTab {
options?: any
}
export interface RecoveryToken {
[_: string]: any
type: string
tabColor?: string|null
}
/**
* Extend to enable recovery for your custom tab.
* This works in conjunction with [[getRecoveryToken()]]
@@ -34,5 +40,5 @@ export abstract class TabRecoveryProvider {
* @returns [[RecoveredTab]] descriptor containing tab type and component inputs
* or `null` if this token is from a different tab type or is not supported
*/
abstract async recover (recoveryToken: any): Promise<RecoveredTab|null>
abstract async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null>
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Inject, Input, HostListener, HostBinding } from '@angular/core'
import { trigger, style, animate, transition, state } from '@angular/animations'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@@ -107,6 +108,12 @@ export class AppRootComponent {
if (hotkey === 'previous-tab') {
this.app.previousTab()
}
if (hotkey === 'move-tab-left') {
this.app.moveSelectedTabLeft()
}
if (hotkey === 'move-tab-right') {
this.app.moveSelectedTabRight()
}
}
if (hotkey === 'toggle-fullscreen') {
this.hostApp.toggleFullscreen()
@@ -184,6 +191,7 @@ export class AppRootComponent {
if (this.config.store.appearance.dock === 'off') {
// not docked, visible
setTimeout(() => {
this.hostApp.getWindow().show()
this.hostApp.getWindow().focus()
})
} else {

View File

@@ -1,5 +1,6 @@
import { Observable, Subject } from 'rxjs'
import { ViewRef } from '@angular/core'
import { RecoveryToken } from '../api/tabRecovery'
/**
* Represents an active "process" inside a tab,
@@ -38,7 +39,7 @@ export abstract class BaseTabComponent {
*/
color: string|null = null
protected hasFocus = false
hasFocus = false
/**
* Ping this if your recovery state has been changed and you want
@@ -71,7 +72,7 @@ export abstract class BaseTabComponent {
})
}
setTitle (title: string) {
setTitle (title: string): void {
this.title = title
if (!this.customTitle) {
this.titleChange.next(title)
@@ -83,7 +84,7 @@ export abstract class BaseTabComponent {
*
* @param {type} progress: value between 0 and 1, or `null` to remove
*/
setProgress (progress: number|null) {
setProgress (progress: number|null): void {
this.progress.next(progress)
if (progress) {
if (this.progressClearTimeout) {
@@ -118,7 +119,7 @@ export abstract class BaseTabComponent {
* @return JSON serializable tab state representation
* for your [[TabRecoveryProvider]] to parse
*/
async getRecoveryToken (): Promise<any> {
async getRecoveryToken (): Promise<RecoveryToken|null> {
return null
}
@@ -136,11 +137,11 @@ export abstract class BaseTabComponent {
return true
}
emitFocused () {
emitFocused (): void {
this.focused.next()
}
emitBlurred () {
emitBlurred (): void {
this.blurred.next()
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { NgZone, Component, Input, HostBinding, HostListener } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, ElementRef, ViewChild } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'

View File

@@ -14,7 +14,7 @@ export class SafeModeModalComponent {
this.error = window['safeModeReason']
}
close () {
close (): void {
this.modalInstance.dismiss()
}
}

View File

@@ -0,0 +1,18 @@
.modal-body
input.form-control(
type='text',
[(ngModel)]='filter',
autofocus,
[placeholder]='name',
(ngModelChange)='onFilterChange()',
(keyup.enter)='onFilterEnter()',
(keyup.escape)='close()'
)
.list-group.mt-3(*ngIf='filteredOptions.length')
a.list-group-item.list-group-item-action.d-flex.align-items-center(
(click)='selectOption(option)',
*ngFor='let option of filteredOptions'
)
.mr-2 {{option.name}}
.text-muted {{option.description}}

View File

@@ -0,0 +1,47 @@
import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { SelectorOption } from '../api/selector'
/** @hidden */
@Component({
template: require('./selectorModal.component.pug'),
// styles: [require('./selectorModal.component.scss')],
})
export class SelectorModalComponent<T> {
@Input() options: SelectorOption<T>[]
@Input() filteredOptions: SelectorOption<T>[]
@Input() filter = ''
@Input() name: string
constructor (
public modalInstance: NgbActiveModal,
) { }
ngOnInit (): void {
this.onFilterChange()
}
onFilterChange (): void {
const f = this.filter.trim().toLowerCase()
if (!f) {
this.filteredOptions = this.options
} else {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
this.filteredOptions = this.options.filter(x => (x.name + (x.description || '')).toLowerCase().includes(f))
}
}
onFilterEnter (): void {
if (this.filteredOptions.length === 1) {
this.selectOption(this.filteredOptions[0])
}
}
selectOption (option: SelectorOption<T>): void {
this.modalInstance.close(option.result)
}
close (): void {
this.modalInstance.dismiss()
}
}

View File

@@ -1,7 +1,7 @@
import { Observable, Subject, Subscription } from 'rxjs'
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, OnInit, OnDestroy } from '@angular/core'
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core'
import { BaseTabComponent, BaseTabProcess } from './baseTab.component'
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery'
import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from '../api/tabRecovery'
import { TabsService } from '../services/tabs.service'
import { HotkeysService } from '../services/hotkeys.service'
import { TabRecoveryService } from '../services/tabRecovery.service'
@@ -48,7 +48,7 @@ export class SplitContainer {
/**
* Remove unnecessarily nested child containers and renormalizes [[ratios]]
*/
normalize () {
normalize (): void {
for (let i = 0; i < this.children.length; i++) {
const child = this.children[i]
@@ -93,7 +93,7 @@ export class SplitContainer {
return s
}
async serialize () {
async serialize (): Promise<RecoveryToken> {
const children: any[] = []
for (const child of this.children) {
if (child instanceof SplitContainer) {
@@ -140,7 +140,7 @@ export interface SplitSpannerInfo {
`,
styles: [require('./splitTab.component.scss')],
})
export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
export class SplitTabComponent extends BaseTabComponent implements AfterViewInit, OnDestroy {
static DIRECTIONS: SplitDirection[] = ['t', 'r', 'b', 'l']
/** @hidden */
@@ -166,6 +166,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
private tabRemoved = new Subject<BaseTabComponent>()
private splitAdjusted = new Subject<SplitSpannerInfo>()
private focusChanged = new Subject<BaseTabComponent>()
private initialized = new Subject<void>()
get tabAdded$ (): Observable<BaseTabComponent> { return this.tabAdded }
get tabRemoved$ (): Observable<BaseTabComponent> { return this.tabRemoved }
@@ -180,6 +181,11 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
*/
get focusChanged$ (): Observable<BaseTabComponent> { return this.focusChanged }
/**
* Fired once tab layout is created and child tabs can be added
*/
get initialized$ (): Observable<void> { return this.initialized }
/** @hidden */
constructor (
private hotkeys: HotkeysService,
@@ -244,7 +250,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
}
/** @hidden */
async ngOnInit () {
async ngAfterViewInit (): Promise<void> {
if (this._recoveredState) {
await this.recoverContainer(this.root, this._recoveredState)
this.layout()
@@ -255,15 +261,17 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
}
})
}
this.initialized.next()
this.initialized.complete()
}
/** @hidden */
ngOnDestroy () {
ngOnDestroy (): void {
this.hotkeysSubscription.unsubscribe()
}
/** @returns Flat list of all sub-tabs */
getAllTabs () {
getAllTabs (): BaseTabComponent[] {
return this.root.getAllTabs()
}
@@ -275,7 +283,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
return this.maximizedTab
}
focus (tab: BaseTabComponent) {
focus (tab: BaseTabComponent): void {
this.focusedTab = tab
for (const x of this.getAllTabs()) {
if (x !== tab) {
@@ -293,7 +301,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
this.layout()
}
maximize (tab: BaseTabComponent|null) {
maximize (tab: BaseTabComponent|null): void {
this.maximizedTab = tab
this.layout()
}
@@ -301,7 +309,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
/**
* Focuses the first available tab inside the given [[SplitContainer]]
*/
focusAnyIn (parent: BaseTabComponent | SplitContainer) {
focusAnyIn (parent: BaseTabComponent | SplitContainer): void {
if (!parent) {
return
}
@@ -315,7 +323,9 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
/**
* Inserts a new `tab` to the `side` of the `relative` tab
*/
addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection) {
async addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection): Promise<void> {
await this.initialized$.toPromise()
let target = (relative ? this.getParentOf(relative) : null) || this.root
let insertIndex = relative ? target.children.indexOf(relative) : -1
@@ -354,7 +364,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
})
}
removeTab (tab: BaseTabComponent) {
removeTab (tab: BaseTabComponent): void {
const parent = this.getParentOf(tab)
if (!parent) {
return
@@ -379,7 +389,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
/**
* Moves focus in the given direction
*/
navigate (dir: SplitDirection) {
navigate (dir: SplitDirection): void {
let rel: BaseTabComponent | SplitContainer = this.focusedTab
let parent = this.getParentOf(rel)
if (!parent) {
@@ -412,11 +422,12 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
}
}
async splitTab (tab: BaseTabComponent, dir: SplitDirection) {
async splitTab (tab: BaseTabComponent, dir: SplitDirection): Promise<BaseTabComponent|null> {
const newTab = await this.tabsService.duplicate(tab)
if (newTab) {
this.addTab(newTab, tab, dir)
}
return newTab
}
/**
@@ -454,12 +465,12 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
}
/** @hidden */
onSpannerAdjusted (spanner: SplitSpannerInfo) {
onSpannerAdjusted (spanner: SplitSpannerInfo): void {
this.layout()
this.splitAdjusted.next(spanner)
}
destroy () {
destroy (): void {
super.destroy()
for (const x of this.getAllTabs()) {
x.destroy()
@@ -564,13 +575,17 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
}
}
}
while (root.ratios.length < root.children.length) {
root.ratios.push(1)
}
root.normalize()
}
}
/** @hidden */
@Injectable()
export class SplitTabRecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> {
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
if (recoveryToken && recoveryToken.type === 'app:split-tab') {
return {
type: SplitTabComponent,

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, HostBinding, ElementRef, Output, EventEmitter } from '@angular/core'
import { SplitContainer } from './splitTab.component'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, ViewChild, HostBinding, ViewContainerRef, OnChanges } from '@angular/core'
import { BaseTabComponent } from '../components/baseTab.component'

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core'
import { SortableComponent } from 'ng2-dnd'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@@ -48,14 +49,17 @@ export class TabHeaderComponent {
}
ngOnInit () {
if (this.hostApp.platform === Platform.macOS) {
this.parentDraggable.setDragHandle(this.handle.nativeElement)
}
this.tab.progress$.subscribe(progress => {
this.progress = progress
})
}
ngAfterViewInit () {
if (this.hostApp.platform === Platform.macOS) {
this.parentDraggable.setDragHandle(this.handle.nativeElement)
}
}
showRenameTabModal (): void {
const modal = this.ngbModal.open(RenameTabModalComponent)
modal.componentInstance.value = this.tab.customTitle || this.tab.title

View File

@@ -1,7 +1,7 @@
.mb-4
.terminus-logo
h1.terminus-title Terminus
sup α
sup α
.container
.text-center.mb-5 Thank you for downloading Terminus!
@@ -10,10 +10,20 @@
.header
.title Enable analytics
.description Help us track the number of Terminus installs across the world!
toggle(
[(ngModel)]='config.store.enableAnalytics',
(ngModelChange)='config.save(); config.requestRestart()',
)
toggle([(ngModel)]='config.store.enableAnalytics')
.form-line
.header
.title Enable SSH plugin
.description Adds an SSH connection manager UI to Terminus
toggle([(ngModel)]='enableSSH')
.form-line
.header
.title Enable Serial plugin
.description Allows attaching Terminus to serial ports
toggle([(ngModel)]='enableSerial')
.text-center.mt-5
button.btn.btn-primary((click)='closeAndDisable()') Close and never show again

View File

@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core'
import { BaseTabComponent } from './baseTab.component'
import { ConfigService } from '../services/config.service'
import { AppService } from '../services/app.service'
import { HostAppService } from '../services/hostApp.service'
/** @hidden */
@Component({
@@ -10,17 +11,29 @@ import { AppService } from '../services/app.service'
styles: [require('./welcomeTab.component.scss')],
})
export class WelcomeTabComponent extends BaseTabComponent {
enableSSH = false
enableSerial = false
constructor (
private app: AppService,
private hostApp: HostAppService,
public config: ConfigService,
) {
super()
this.setTitle('Welcome')
this.enableSSH = !config.store.pluginBlacklist.includes('ssh')
this.enableSerial = !config.store.pluginBlacklist.includes('serial')
}
closeAndDisable () {
this.config.store.enableWelcomeTab = false
this.config.store.pluginBlacklist = []
if (!this.enableSSH) {
this.config.store.pluginBlacklist.push('ssh')
}
if (!this.enableSerial) {
this.config.store.pluginBlacklist.push('serial')
}
this.config.save()
this.app.closeTab(this)
this.hostApp.getWindow().reload()
}
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core'
import { HostAppService } from '../services/hostApp.service'
import { AppService } from '../services/app.service'

View File

@@ -16,6 +16,10 @@ hotkeys:
previous-tab:
- 'Ctrl-Shift-Left'
- 'Ctrl-Shift-Tab'
move-tab-left:
- 'Ctrl-Shift-PageUp'
move-tab-right:
- 'Ctrl-Shift-PageDown'
tab-1:
- 'Alt-1'
tab-2:

View File

@@ -14,6 +14,10 @@ hotkeys:
- 'Ctrl-Tab'
previous-tab:
- 'Ctrl-Shift-Tab'
move-tab-left:
- '⌘-Shift-Left'
move-tab-right:
- '⌘-Shift-Right'
tab-1:
- '⌘-1'
tab-2:

View File

@@ -17,6 +17,10 @@ hotkeys:
previous-tab:
- 'Ctrl-Shift-Left'
- 'Ctrl-Shift-Tab'
move-tab-left:
- 'Ctrl-Shift-PageUp'
move-tab-right:
- 'Ctrl-Shift-PageDown'
tab-1:
- 'Alt-1'
tab-2:

View File

@@ -7,7 +7,7 @@ import { Directive, AfterViewInit, ElementRef } from '@angular/core'
export class AutofocusDirective implements AfterViewInit {
constructor (private el: ElementRef) { }
ngAfterViewInit () {
ngAfterViewInit (): void {
this.el.nativeElement.blur()
setTimeout(() => {
this.el.nativeElement.focus()

View File

@@ -8,7 +8,7 @@ export class FastHtmlBindDirective implements OnChanges {
@Input() fastHtmlBind: string
constructor (private el: ElementRef) { }
ngOnChanges () {
ngOnChanges (): void {
this.el.nativeElement.innerHTML = this.fastHtmlBind || ''
}
}

View File

@@ -37,6 +37,14 @@ export class AppHotkeyProvider extends HotkeyProvider {
id: 'previous-tab',
name: 'Previous tab',
},
{
id: 'move-tab-left',
name: 'Move tab to the left',
},
{
id: 'move-tab-right',
name: 'Move tab to the right',
},
{
id: 'tab-1',
name: 'Tab 1',

View File

@@ -16,6 +16,7 @@ import { TitleBarComponent } from './components/titleBar.component'
import { ToggleComponent } from './components/toggle.component'
import { WindowControlsComponent } from './components/windowControls.component'
import { RenameTabModalComponent } from './components/renameTabModal.component'
import { SelectorModalComponent } from './components/selectorModal.component'
import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component'
import { SplitTabSpannerComponent } from './components/splitTabSpanner.component'
import { WelcomeTabComponent } from './components/welcomeTab.component'
@@ -65,7 +66,7 @@ const PROVIDERS = [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
NgbModule.forRoot(),
NgbModule,
PerfectScrollbarModule,
DndModule.forRoot(),
],
@@ -82,6 +83,7 @@ const PROVIDERS = [
SafeModeModalComponent,
AutofocusDirective,
FastHtmlBindDirective,
SelectorModalComponent,
SplitTabComponent,
SplitTabSpannerComponent,
WelcomeTabComponent,
@@ -89,6 +91,7 @@ const PROVIDERS = [
entryComponents: [
RenameTabModalComponent,
SafeModeModalComponent,
SelectorModalComponent,
SplitTabComponent,
WelcomeTabComponent,
],

View File

@@ -2,9 +2,12 @@
import { Observable, Subject, AsyncSubject } from 'rxjs'
import { takeUntil } from 'rxjs/operators'
import { Injectable } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { BaseTabComponent } from '../components/baseTab.component'
import { SplitTabComponent } from '../components/splitTab.component'
import { SelectorModalComponent } from '../components/selectorModal.component'
import { SelectorOption } from '../api/selector'
import { ConfigService } from './config.service'
import { HostAppService } from './hostApp.service'
@@ -69,6 +72,7 @@ export class AppService {
private hostApp: HostAppService,
private tabRecovery: TabRecoveryService,
private tabsService: TabsService,
private ngbModal: NgbModal,
) {
if (hostApp.getWindow().id === 1) {
if (config.store.terminal.recoverTabs) {
@@ -89,7 +93,7 @@ export class AppService {
})
}
startTabStorage () {
startTabStorage (): void {
this.tabsChanged$.subscribe(() => {
this.tabRecovery.saveTabs(this.tabs)
})
@@ -98,7 +102,7 @@ export class AppService {
}, 30000)
}
addTabRaw (tab: BaseTabComponent, index: number|null = null) {
addTabRaw (tab: BaseTabComponent, index: number|null = null): void {
if (index !== null) {
this.tabs.splice(index, 0, tab)
} else {
@@ -141,7 +145,7 @@ export class AppService {
* Adds a new tab **without** wrapping it in a SplitTabComponent
* @param inputs Properties to be assigned on the new tab component instance
*/
openNewTabRaw (type: TabComponentType, inputs?: any): BaseTabComponent {
openNewTabRaw (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
const tab = this.tabsService.create(type, inputs)
this.addTabRaw(tab)
return tab
@@ -151,7 +155,7 @@ export class AppService {
* Adds a new tab while wrapping it in a SplitTabComponent
* @param inputs Properties to be assigned on the new tab component instance
*/
openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
openNewTab (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
const splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent
const tab = this.tabsService.create(type, inputs)
splitTab.addTab(tab, null, 'r')
@@ -159,7 +163,7 @@ export class AppService {
return tab
}
selectTab (tab: BaseTabComponent) {
selectTab (tab: BaseTabComponent): void {
if (this._activeTab === tab) {
this._activeTab.emitFocused()
return
@@ -195,14 +199,14 @@ export class AppService {
}
/** Switches between the current tab and the previously active one */
toggleLastTab () {
toggleLastTab (): void {
if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) {
this.lastTabIndex = 0
}
this.selectTab(this.tabs[this.lastTabIndex])
}
nextTab () {
nextTab (): void {
if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex < this.tabs.length - 1) {
@@ -213,7 +217,7 @@ export class AppService {
}
}
previousTab () {
previousTab (): void {
if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex > 0) {
@@ -224,8 +228,37 @@ export class AppService {
}
}
moveSelectedTabLeft (): void {
if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex > 0) {
this.swapTabs(this._activeTab, this.tabs[tabIndex - 1])
} else if (this.config.store.appearance.cycleTabs) {
this.swapTabs(this._activeTab, this.tabs[this.tabs.length - 1])
}
}
}
moveSelectedTabRight (): void {
if (this.tabs.length > 1) {
const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex < this.tabs.length - 1) {
this.swapTabs(this._activeTab, this.tabs[tabIndex + 1])
} else if (this.config.store.appearance.cycleTabs) {
this.swapTabs(this._activeTab, this.tabs[0])
}
}
}
swapTabs (a: BaseTabComponent, b: BaseTabComponent): void {
const i1 = this.tabs.indexOf(a)
const i2 = this.tabs.indexOf(b)
this.tabs[i1] = b
this.tabs[i2] = a
}
/** @hidden */
emitTabsChanged () {
emitTabsChanged (): void {
this.tabsChanged.next()
}
@@ -239,11 +272,12 @@ export class AppService {
tab.destroy()
}
async duplicateTab (tab: BaseTabComponent) {
async duplicateTab (tab: BaseTabComponent): Promise<BaseTabComponent|null> {
const dup = await this.tabsService.duplicate(tab)
if (dup) {
this.addTabRaw(dup, this.tabs.indexOf(tab) + 1)
}
return dup
}
/**
@@ -262,7 +296,7 @@ export class AppService {
}
/** @hidden */
emitReady () {
emitReady (): void {
this.ready.next()
this.ready.complete()
this.hostApp.emitReady()
@@ -283,7 +317,15 @@ export class AppService {
return this.completionObservers.get(tab)!.done$
}
stopObservingTabCompletion (tab: BaseTabComponent) {
stopObservingTabCompletion (tab: BaseTabComponent): void {
this.completionObservers.delete(tab)
}
showSelector <T> (name: string, options: SelectorOption<T>[]): Promise<T> {
const modal = this.ngbModal.open(SelectorModalComponent)
const instance: SelectorModalComponent<T> = modal.componentInstance
instance.name = name
instance.options = options
return modal.result as Promise<T>
}
}

View File

@@ -20,7 +20,7 @@ function isNonStructuralObjectMember (v): boolean {
/** @hidden */
export class ConfigProxy {
constructor (real: any, defaults: any) {
constructor (real: Record<string, any>, defaults: Record<string, any>) {
for (const key in defaults) {
if (isStructuralMember(defaults[key])) {
if (!real[key]) {
@@ -71,8 +71,10 @@ export class ConfigProxy {
}
}
getValue (_key: string): any { } // eslint-disable-line @typescript-eslint/no-empty-function
setValue (_key: string, _value: any) { } // eslint-disable-line @typescript-eslint/no-empty-function
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
getValue (_key: string): any { }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
setValue (_key: string, _value: any) { }
}
@Injectable({ providedIn: 'root' })
@@ -124,7 +126,7 @@ export class ConfigService {
})
}
getDefaults () {
getDefaults (): Record<string, any> {
const cleanup = o => {
if (o instanceof Array) {
return o.map(cleanup)
@@ -188,11 +190,11 @@ export class ConfigService {
enabledServices<T extends object> (services: T[]): T[] {
if (!this.servicesCache) {
this.servicesCache = {}
const ngModule = window['rootModule'].ngInjectorDef
const ngModule = window['rootModule'].ɵinj
for (const imp of ngModule.imports) {
const module = imp['ngModule'] || imp
if (module.ngInjectorDef && module.ngInjectorDef.providers) {
this.servicesCache[module['pluginName']] = module.ngInjectorDef.providers.map(provider => {
if (module.ɵinj?.providers) {
this.servicesCache[module['pluginName']] = module.ɵinj.providers.map(provider => {
return provider['useClass'] || provider
})
}

View File

@@ -15,7 +15,7 @@ export class DockingService {
electron.screen.on('display-metrics-changed', () => this.repositionWindow())
}
dock () {
dock (): void {
const dockSide = this.config.store.appearance.dock
if (dockSide === 'off') {
@@ -59,16 +59,17 @@ export class DockingService {
})
}
getCurrentScreen () {
getCurrentScreen (): Electron.Display {
return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint())
}
getScreens () {
getScreens (): Electron.Display[] {
const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id
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
).map((display,index) => {
).map((display, index) => {
return {
...display,
id: display.id,
name: display.id === primaryDisplayID ? 'Primary Display' : `Display ${index +1}`,
}

View File

@@ -46,7 +46,7 @@ export class ElectronService {
/**
* Removes OS focus from Terminus' window
*/
loseFocus () {
loseFocus (): void {
if (process.platform === 'darwin') {
this.remote.Menu.sendActionToFirstResponder('hide:')
}

View File

@@ -22,11 +22,11 @@ export class HomeBaseService {
}
}
openGitHub () {
openGitHub (): void {
this.electron.shell.openExternal('https://github.com/eugeny/terminus')
}
reportBug () {
reportBug (): void {
let body = `Version: ${this.appVersion}\n`
body += `Platform: ${os.platform()} ${os.release()}\n`
const label = {
@@ -44,7 +44,7 @@ export class HomeBaseService {
this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`)
}
enableAnalytics () {
enableAnalytics (): void {
if (!window.localStorage.analyticsUserID) {
window.localStorage.analyticsUserID = uuidv4()
}
@@ -56,7 +56,7 @@ export class HomeBaseService {
this.mixpanel.track('launch', this.getAnalyticsProperties())
}
getAnalyticsProperties () {
getAnalyticsProperties (): Record<string, string> {
return {
distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase
platform: process.platform,

View File

@@ -4,6 +4,7 @@ import { Observable, Subject } from 'rxjs'
import { Injectable, NgZone, EventEmitter } from '@angular/core'
import { ElectronService } from './electron.service'
import { Logger, LogService } from './log.service'
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
export enum Platform {
Linux, macOS, Windows,
@@ -164,53 +165,61 @@ export class HostAppService {
electron.ipcRenderer.on('host:config-change', () => this.zone.run(() => {
this.configChangeBroadcast.next()
}))
if (
isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED) &&
!isWindowsBuild(WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED)
) {
electron.ipcRenderer.send('window-set-disable-vibrancy-while-dragging', true)
}
}
/**
* Returns the current remote [[BrowserWindow]]
*/
getWindow () {
getWindow (): Electron.BrowserWindow {
return this.electron.BrowserWindow.fromId(this.windowId)
}
newWindow () {
newWindow (): void {
this.electron.ipcRenderer.send('app:new-window')
}
toggleFullscreen () {
toggleFullscreen (): void {
const window = this.getWindow()
window.setFullScreen(!this.isFullScreen)
}
openDevTools () {
openDevTools (): void {
this.getWindow().webContents.openDevTools({ mode: 'undocked' })
}
focusWindow () {
focusWindow (): void {
this.electron.ipcRenderer.send('window-focus')
}
minimize () {
minimize (): void {
this.electron.ipcRenderer.send('window-minimize')
}
maximize () {
maximize (): void {
this.electron.ipcRenderer.send('window-maximize')
}
unmaximize () {
unmaximize (): void {
this.electron.ipcRenderer.send('window-unmaximize')
}
toggleMaximize () {
toggleMaximize (): void {
this.electron.ipcRenderer.send('window-toggle-maximize')
}
setBounds (bounds: Bounds) {
setBounds (bounds: Bounds): void {
this.electron.ipcRenderer.send('window-set-bounds', bounds)
}
setAlwaysOnTop (flag: boolean) {
setAlwaysOnTop (flag: boolean): void {
this.electron.ipcRenderer.send('window-set-always-on-top', flag)
}
@@ -219,48 +228,46 @@ export class HostAppService {
*
* @param type `null`, or `fluent` when supported (Windowd only)
*/
setVibrancy (enable: boolean, type: string) {
setVibrancy (enable: boolean, type: string|null): void {
if (!isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
type = null
}
document.body.classList.toggle('vibrant', enable)
if (this.platform === Platform.macOS) {
this.getWindow().setVibrancy(enable ? 'dark' : null as any) // electron issue 20269
}
if (this.platform === Platform.Windows) {
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
}
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
}
setTitle (title: string) {
setTitle (title: string): void {
this.electron.ipcRenderer.send('window-set-title', title)
}
setTouchBar (touchBar: Electron.TouchBar) {
setTouchBar (touchBar: Electron.TouchBar): void {
this.getWindow().setTouchBar(touchBar)
}
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]) {
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]): void {
this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
}
/**
* Notifies other windows of config file changes
*/
broadcastConfigChange () {
broadcastConfigChange (): void {
this.electron.ipcRenderer.send('app:config-change')
}
emitReady () {
emitReady (): void {
this.electron.ipcRenderer.send('app:ready')
}
bringToFront () {
bringToFront (): void {
this.electron.ipcRenderer.send('window-bring-to-front')
}
closeWindow () {
closeWindow (): void {
this.electron.ipcRenderer.send('window-close')
}
relaunch () {
relaunch (): void {
if (this.isPortable) {
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
} else {
@@ -269,7 +276,7 @@ export class HostAppService {
this.electron.app.exit()
}
quit () {
quit (): void {
this.logger.info('Quitting')
this.electron.app.quit()
}

View File

@@ -1,4 +1,5 @@
import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
import { Observable, Subject } from 'rxjs'
import { HotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
import { stringifyKeySequence } from './hotkeys.util'
import { ConfigService } from '../services/config.service'
@@ -20,8 +21,17 @@ interface EventBufferEntry {
@Injectable({ providedIn: 'root' })
export class HotkeysService {
key = new EventEmitter<KeyboardEvent>()
/** @hidden */
matchedHotkey = new EventEmitter<string>()
/**
* Fired for each recognized hotkey
*/
get hotkey$ (): Observable<string> { return this._hotkey }
globalHotkey = new EventEmitter<void>()
private _hotkey = new Subject<string>()
private currentKeystrokes: EventBufferEntry[] = []
private disabledLevel = 0
private hotkeyDescriptions: HotkeyDescription[] = []
@@ -49,6 +59,9 @@ export class HotkeysService {
this.getHotkeyDescriptions().then(hotkeys => {
this.hotkeyDescriptions = hotkeys
})
// deprecated
this.hotkey$.subscribe(h => this.matchedHotkey.emit(h))
}
/**
@@ -57,7 +70,7 @@ export class HotkeysService {
* @param name DOM event name
* @param nativeEvent event object
*/
pushKeystroke (name: string, nativeEvent: KeyboardEvent) {
pushKeystroke (name: string, nativeEvent: KeyboardEvent): void {
(nativeEvent as any).event = name
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
}
@@ -65,26 +78,26 @@ export class HotkeysService {
/**
* Check the buffer for new complete keystrokes
*/
processKeystrokes () {
processKeystrokes (): void {
if (this.isEnabled()) {
this.zone.run(() => {
const matched = this.getCurrentFullyMatchedHotkey()
if (matched) {
console.log('Matched hotkey', matched)
this.matchedHotkey.emit(matched)
this._hotkey.next(matched)
this.clearCurrentKeystrokes()
}
})
}
}
emitKeyEvent (nativeEvent: KeyboardEvent) {
emitKeyEvent (nativeEvent: KeyboardEvent): void {
this.zone.run(() => {
this.key.emit(nativeEvent)
})
}
clearCurrentKeystrokes () {
clearCurrentKeystrokes (): void {
this.currentKeystrokes = []
}
@@ -142,15 +155,15 @@ export class HotkeysService {
return this.hotkeyDescriptions.filter((x) => x.id === id)[0]
}
enable () {
enable (): void {
this.disabledLevel--
}
disable () {
disable (): void {
this.disabledLevel++
}
isEnabled () {
isEnabled (): boolean {
return this.disabledLevel === 0
}
@@ -203,6 +216,9 @@ export class HotkeysService {
if (typeof value === 'string') {
value = [value]
}
if (!(value instanceof Array)) {
continue
}
if (value) {
value = value.map((item: string | string[]) => typeof item === 'string' ? [item] : item)
keys[key] = value

View File

@@ -32,27 +32,27 @@ export class Logger {
private name: string,
) {}
debug (...args: any[]) {
debug (...args: any[]): void {
this.doLog('debug', ...args)
}
info (...args: any[]) {
info (...args: any[]): void {
this.doLog('info', ...args)
}
warn (...args: any[]) {
warn (...args: any[]): void {
this.doLog('warn', ...args)
}
error (...args: any[]) {
error (...args: any[]): void {
this.doLog('error', ...args)
}
log (...args: any[]) {
log (...args: any[]): void {
this.doLog('log', ...args)
}
private doLog (level: string, ...args: any[]) {
private doLog (level: string, ...args: any[]): void {
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
if (this.winstonLogger) {
this.winstonLogger[level](...args)

View File

@@ -8,7 +8,7 @@ import { HostAppService, Platform } from './hostApp.service'
/* eslint-disable block-scoped-var */
try {
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
} catch (_) { }
@Injectable({ providedIn: 'root' })
@@ -58,7 +58,7 @@ export class ShellIntegrationService {
return true
}
async install () {
async install (): Promise<void> {
const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
if (this.hostApp.platform === Platform.macOS) {
for (const wf of this.automatorWorkflows) {
@@ -82,7 +82,7 @@ export class ShellIntegrationService {
}
}
async remove () {
async remove (): Promise<void> {
if (this.hostApp.platform === Platform.macOS) {
for (const wf of this.automatorWorkflows) {
await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)

View File

@@ -1,5 +1,5 @@
import { Injectable, Inject } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery'
import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from '../api/tabRecovery'
import { BaseTabComponent } from '../components/baseTab.component'
import { Logger, LogService } from '../services/log.service'
import { ConfigService } from '../services/config.service'
@@ -17,21 +17,34 @@ export class TabRecoveryService {
this.logger = log.create('tabRecovery')
}
async saveTabs (tabs: BaseTabComponent[]) {
async saveTabs (tabs: BaseTabComponent[]): Promise<void> {
window.localStorage.tabsRecovery = JSON.stringify(
await Promise.all(
tabs
.map(tab => tab.getRecoveryToken())
.map(tab => {
let token = tab.getRecoveryToken()
if (token) {
token = token.then(r => {
if (r && tab.color) {
r.tabColor = tab.color
}
return r
})
}
return token
})
.filter(token => !!token)
)
)
}
async recoverTab (token: any): Promise<RecoveredTab|null> {
async recoverTab (token: RecoveryToken): Promise<RecoveredTab|null> {
for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
try {
const tab = await provider.recover(token)
if (tab) {
if (tab !== null) {
tab.options = tab.options || {}
tab.options.color = token.tabColor || null
return tab
}
} catch (error) {

View File

@@ -17,7 +17,7 @@ export class TabsService {
/**
* Instantiates a tab component and assigns given inputs
*/
create (type: TabComponentType, inputs?: any): BaseTabComponent {
create (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
const componentRef = componentFactory.create(this.injector)
const tab = componentRef.instance

View File

@@ -48,7 +48,7 @@ export class TouchbarService {
})
}
updateTabs () {
updateTabs (): void {
this.tabSegments = this.app.tabs.map(tab => ({
label: this.shortenTitle(tab.title),
}))
@@ -56,7 +56,7 @@ export class TouchbarService {
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
}
update () {
update (): void {
if (this.hostApp.platform !== Platform.macOS) {
return
}

View File

@@ -8,6 +8,7 @@ import { Injectable } from '@angular/core'
import { Logger, LogService } from './log.service'
import { ElectronService } from './electron.service'
import { ConfigService } from './config.service'
import { AppUpdater } from 'electron-updater'
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
@@ -18,12 +19,12 @@ export class UpdaterService {
private downloaded: Promise<boolean>
private electronUpdaterAvailable = true
private updateURL: string
private autoUpdater
private autoUpdater: AppUpdater
constructor (
log: LogService,
private electron: ElectronService,
config: ConfigService,
private config: ConfigService,
) {
this.logger = log.create('updater')
@@ -48,9 +49,8 @@ export class UpdaterService {
this.autoUpdater.once('update-downloaded', () => resolve(true))
})
this.logger.debug('Checking for updates')
if (this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
this.logger.debug('Checking for updates')
try {
this.autoUpdater.checkForUpdates()
} catch (e) {
@@ -61,6 +61,9 @@ export class UpdaterService {
}
async check (): Promise<boolean> {
if (!this.config.store.enableAutomaticUpdates) {
return false
}
if (!this.electronUpdaterAvailable) {
this.logger.debug('Checking for updates through fallback method.')
const response = await axios.get(UPDATES_URL)
@@ -77,7 +80,7 @@ export class UpdaterService {
return this.downloaded
}
async update () {
async update (): Promise<void> {
if (!this.electronUpdaterAvailable) {
this.electron.shell.openExternal(this.updateURL)
} else {

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable, NgZone } from '@angular/core'
import { Subscription } from 'rxjs'
import { AppService } from './services/app.service'

View File

@@ -3,11 +3,14 @@ import * as os from 'os'
export const WIN_BUILD_CONPTY_SUPPORTED = 17692
export const WIN_BUILD_CONPTY_STABLE = 18309
export const WIN_BUILD_WSL_EXE_DISTRO_FLAG = 17763
export const WIN_BUILD_FLUENT_BG_SUPPORTED = 17063
export const WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED = 18917
export function isWindowsBuild (build: number): boolean {
return process.platform === 'win32' && parseFloat(os.release()) >= 10 && parseInt(os.release().split('.')[2]) >= build
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function getCSSFontFamily (config: any): string {
let fonts: string[] = config.terminal.font.split(',').map(x => x.trim().replace(/"/g, ''))
if (config.terminal.fallbackFont) {

View File

@@ -3,14 +3,21 @@
"@types/js-yaml@^3.9.0":
version "3.12.1"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656"
integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==
version "3.12.2"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.2.tgz#a35a1809c33a68200fb6403d1ad708363c56470a"
integrity sha512-0CFu/g4mDSNkodVwWijdlr8jH7RoplRWNgovjFLEZeT+QEbbZXjBmCe3HwaWheAlCbHwomTwzZoSedeOycABug==
"@types/semver@^6.0.2":
version "6.2.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
"@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:
"@types/node" "*"
"@types/shell-escape@^0.2.0":
version "0.2.0"
@@ -46,9 +53,9 @@ async@^2.6.1:
lodash "^4.17.11"
axios@^0.19.0:
version "0.19.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.1.tgz#8a6a04eed23dfe72747e1dd43c604b8f1677b5aa"
integrity sha512-Yl+7nfreYKaLRvAvjNPkvfjnQHJM1yLBY3zhqAwcJSwR/6ETkanUgylgtIvkvz0xJ+p/vZuNw8X7Hnb7Whsbpw==
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
dependencies:
follow-redirects "1.5.10"
@@ -57,10 +64,10 @@ bootstrap@^4.1.3:
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
builder-util-runtime@8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz#3163fffc078e6b8f3dd5b6eb12a8345573590682"
integrity sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==
builder-util-runtime@8.6.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.0.tgz#b7007c30126da9a90e99932128d2922c8c178649"
integrity sha512-WTDhTUVrm7zkFyd6Qn7AXgmWifjpZ/fYnEdV3XCOIDMNNb/KPddBTbQ8bUlxxVeuOYlhGpcLUypG+4USdGL1ww==
dependencies:
debug "^4.1.1"
sax "^1.2.4"
@@ -162,18 +169,18 @@ diagnostics@^1.1.1:
kuler "1.0.x"
electron-updater@^4.0.6:
version "4.2.0"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.0.tgz#f9ecfc657f65ead737d42b9efecf628d3756b550"
integrity sha512-GuS3g7HDh17x/SaFjxjswlWUaKHczksYkV2Xc5CKj/bZH0YCvTSHtOmnBAdAmCk99u/71p3zP8f0jIqDfGcjww==
version "4.2.2"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.2.tgz#57e106bffad16f71b1ffa3968a52a1b71c8147e6"
integrity sha512-e/OZhr5tLW0GcgmpR5wD0ImxgKMa8pPoNWRcwRyMzTL9pGej7+ORp0t9DtI5ZBHUbObIoEbrk+6EDGUGtJf+aA==
dependencies:
"@types/semver" "^6.0.2"
builder-util-runtime "8.4.0"
"@types/semver" "^7.1.0"
builder-util-runtime "8.6.0"
fs-extra "^8.1.0"
js-yaml "^3.13.1"
lazy-val "^1.0.4"
lodash.isequal "^4.5.0"
pako "^1.0.10"
semver "^6.3.0"
pako "^1.0.11"
semver "^7.1.3"
enabled@1.0.x:
version "1.0.2"
@@ -346,10 +353,10 @@ one-time@0.0.4:
resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e"
integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=
pako@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
pako@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
perfect-scrollbar@^1.4.0:
version "1.4.0"
@@ -398,10 +405,10 @@ sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6"
integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==
shell-escape@^0.2.0:
version "0.2.0"
@@ -459,10 +466,10 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
uuid@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.1.tgz#95ed6ff3d8c881cbf85f0f05cc3915ef994818ef"
integrity sha512-yqjRXZzSJm9Dbl84H2VDHpM3zMjzSJQ+hn6C4zqd5ilW+7P4ZmLEEqwho9LjP+tGuZlF4xrHQXT0h9QZUS/pWA==
winston-transport@^4.3.0:
version "4.3.0"

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-plugin-manager",
"version": "1.0.99-nightly.0",
"version": "1.0.104-nightly.0",
"description": "Terminus' plugin manager",
"keywords": [
"terminus-builtin-plugin"
@@ -17,7 +17,7 @@
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
"@types/semver": "^6.0.0",
"@types/semver": "^7.1.0",
"axios": "^0.19.0",
"mz": "^2.6.0",
"semver": "^7.1.1"

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { BehaviorSubject, Observable } from 'rxjs'
import { debounceTime, distinctUntilChanged, first, tap, flatMap, map } from 'rxjs/operators'
import * as semver from 'semver'
import semverGt from 'semver/functions/gt'
import { Component, Input } from '@angular/core'
import { ConfigService, ElectronService } from 'terminus-core'
@@ -48,7 +49,7 @@ export class PluginsSettingsTabComponent {
return plugins
})).subscribe(available => {
for (const plugin of this.pluginManager.installedPlugins) {
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version)) || null
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semverGt(x.version, plugin.version)) || null
}
})
}

View File

@@ -40,7 +40,7 @@ export class PluginManagerService {
this.logger = log.create('pluginManager')
}
async getNPM () {
async getNPM (): Promise<any> {
if (!this.npm) {
if (!this.npmReady) {
this.npmReady = new Promise(resolve => {
@@ -83,7 +83,7 @@ export class PluginManagerService {
)
}
async installPlugin (plugin: PluginInfo) {
async installPlugin (plugin: PluginInfo): Promise<void> {
(await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => {
if (err) {
this.logger.error(err)
@@ -93,7 +93,7 @@ export class PluginManagerService {
})
}
async uninstallPlugin (plugin: PluginInfo) {
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
(await this.getNPM()).commands.remove([plugin.packageName], err => {
if (err) {
this.logger.error(err)

View File

@@ -2,10 +2,17 @@
# yarn lockfile v1
"@types/semver@^6.0.0":
version "6.2.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
"@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":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408"
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==
dependencies:
"@types/node" "*"
any-promise@^1.0.0:
version "1.3.0"
@@ -13,9 +20,9 @@ any-promise@^1.0.0:
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
axios@^0.19.0:
version "0.19.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.1.tgz#8a6a04eed23dfe72747e1dd43c604b8f1677b5aa"
integrity sha512-Yl+7nfreYKaLRvAvjNPkvfjnQHJM1yLBY3zhqAwcJSwR/6ETkanUgylgtIvkvz0xJ+p/vZuNw8X7Hnb7Whsbpw==
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
dependencies:
follow-redirects "1.5.10"

View File

@@ -0,0 +1,37 @@
{
"name": "terminus-serial",
"version": "1.0.104-nightly.0",
"description": "Serial connection manager for Terminus",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
"typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color",
"watch": "webpack --progress --color --watch"
},
"files": [
"dist"
],
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
"@types/node": "12.7.3",
"@types/ssh2": "^0.5.35",
"ansi-colors": "^4.1.1",
"cli-spinner": "^0.2.10",
"electron-rebuild": "^1.10.0",
"terminus-terminal": "^1.0.98-nightly.0"
},
"peerDependencies": {
"@angular/common": "^7",
"@angular/core": "^7",
"@angular/forms": "^7",
"@ng-bootstrap/ng-bootstrap": "^1",
"rxjs": "^5",
"terminus-core": "*",
"terminus-settings": "*",
"terminus-terminal": "*"
}
}

156
terminus-serial/src/api.ts Normal file
View File

@@ -0,0 +1,156 @@
import { BaseSession } from 'terminus-terminal'
import { SerialPort } from 'serialport'
import { Logger } from 'terminus-core'
import { Subject, Observable } from 'rxjs'
export interface LoginScript {
expect: string
send: string
isRegex?: boolean
optional?: boolean
}
export interface SerialConnection {
name: string
port: string
baudrate: number
databits: number
stopbits: number
parity: string
rtscts: boolean
xon: boolean
xoff: boolean
xany: boolean
scripts?: LoginScript[]
color?: string
}
export const BAUD_RATES = [
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600,
]
export interface SerialPortInfo {
name: string
description?: string
}
export class SerialSession extends BaseSession {
scripts?: LoginScript[]
serial: SerialPort
logger: Logger
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
private serviceMessage = new Subject<string>()
constructor (public connection: SerialConnection) {
super()
this.scripts = connection.scripts || []
}
async start (): Promise<void> {
this.open = true
this.serial.on('data', data => {
const dataString = data.toString()
this.emitOutput(data)
if (this.scripts) {
let found = false
for (const script of this.scripts) {
let match = false
let cmd = ''
if (script.isRegex) {
const re = new RegExp(script.expect, 'g')
if (dataString.match(re)) {
cmd = dataString.replace(re, script.send)
match = true
found = true
}
} else {
if (dataString.includes(script.expect)) {
cmd = script.send
match = true
found = true
}
}
if (match) {
this.logger.info('Executing script: "' + cmd + '"')
this.serial.write(cmd + '\n')
this.scripts = this.scripts.filter(x => x !== script)
} else {
if (script.optional) {
this.logger.debug('Skip optional script: ' + script.expect)
found = true
this.scripts = this.scripts.filter(x => x !== script)
} else {
break
}
}
}
if (found) {
this.executeUnconditionalScripts()
}
}
})
this.serial.on('end', () => {
this.logger.info('Shell session ended')
if (this.open) {
this.destroy()
}
})
this.executeUnconditionalScripts()
}
write (data: Buffer): void {
if (this.serial) {
this.serial.write(data.toString())
}
}
async destroy (): Promise<void> {
this.serviceMessage.complete()
await super.destroy()
}
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
resize (_, __) { }
kill (_?: string): void {
this.serial.close()
}
async getChildProcesses (): Promise<any[]> {
return []
}
async gracefullyKillProcess (): Promise<void> {
this.kill('TERM')
}
async getWorkingDirectory (): Promise<string|null> {
return null
}
private executeUnconditionalScripts () {
if (this.scripts) {
for (const script of this.scripts) {
if (!script.expect) {
console.log('Executing script:', script.send)
this.serial.write(script.send + '\n')
this.scripts = this.scripts.filter(x => x !== script)
} else {
break
}
}
}
}
}
export interface SerialConnectionGroup {
name: string
connections: SerialConnection[]
}

View File

@@ -0,0 +1,37 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Injectable } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
import { SerialModalComponent } from './components/serialModal.component'
/** @hidden */
@Injectable()
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
private ngbModal: NgbModal,
hotkeys: HotkeysService,
) {
super()
hotkeys.matchedHotkey.subscribe(async (hotkey: string) => {
if (hotkey === 'serial') {
this.activate()
}
})
}
activate () {
this.ngbModal.open(SerialModalComponent)
}
provide (): ToolbarButton[] {
return [{
icon: require('./icons/serial.svg'),
weight: 5,
title: 'Serial connections',
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
click: async () => {
this.activate()
},
}]
}
}

View File

@@ -0,0 +1,134 @@
.modal-body
ngb-tabset([activeId]='basic')
ngb-tab(id='basic')
ng-template(ngbTabTitle) General
ng-template(ngbTabContent)
.form-group
label Name
input.form-control(
type='text',
autofocus,
[(ngModel)]='connection.name',
)
.form-group
label Path
input.form-control(
type='text',
[(ngModel)]='connection.port',
[ngbTypeahead]='portsAutocomplete',
[resultFormatter]='portsFormatter',
)
.form-group
label Baud Rate
select.form-control(
[(ngModel)]='connection.baudrate',
)
option([value]='x', *ngFor='let x of baudRates') {{x}}
ngb-tab(id='advanced')
ng-template(ngbTabTitle) Advanced
ng-template(ngbTabContent)
.form-line
.header
.title Tab color
input.form-control(
type='text',
autofocus,
[(ngModel)]='connection.color',
placeholder='#000000'
)
.form-line
.header
.title DataBits
input.form-control(
type='number',
placeholder='8',
[(ngModel)]='connection.databits',
)
.form-line
.header
.title StopBits
input.form-control(
type='number',
placeholder='1',
[(ngModel)]='connection.stopbits',
)
.form-line
.header
.title Parity
input.form-control(
type='text',
[(ngModel)]='connection.parity',
placeholder='none'
)
.form-line
.header
.title RTSCTS
toggle([(ngModel)]='connection.rtscts')
.form-line
.header
.title Xon
toggle([(ngModel)]='connection.xon')
.form-line
.header
.title Xoff
toggle([(ngModel)]='connection.xoff')
.form-line
.header
.title Xany
toggle([(ngModel)]='connection.xany')
ngb-tab(id='scripts')
ng-template(ngbTabTitle) Login scripts
ng-template(ngbTabContent)
table(*ngIf='connection.scripts.length > 0')
tr
th String to expect
th String to be sent
th.pl-2 Regex
th.pl-2 Optional
th.pl-2 Actions
tr(*ngFor='let script of connection.scripts')
td.pr-2
input.form-control(
type='text',
[(ngModel)]='script.expect'
)
td
input.form-control(
type='text',
[(ngModel)]='script.send'
)
td.pl-2
checkbox(
[(ngModel)]='script.isRegex',
)
td.pl-2
checkbox(
[(ngModel)]='script.optional',
)
td.pl-2
.input-group.flex-nowrap
button.btn.btn-outline-info.ml-0((click)='moveScriptUp(script)')
i.fas.fa-arrow-up
button.btn.btn-outline-info.ml-0((click)='moveScriptDown(script)')
i.fas.fa-arrow-down
button.btn.btn-outline-danger.ml-0((click)='deleteScript(script)')
i.fas.fa-trash
button.btn.btn-outline-info.mt-2((click)='addScript()')
i.fas.fa-plus
span New item
.modal-footer
button.btn.btn-outline-primary((click)='save()') Save
button.btn.btn-outline-danger((click)='cancel()') Cancel

View File

@@ -0,0 +1,95 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { map } from 'rxjs/operators'
import { ElectronService, HostAppService } from 'terminus-core'
import { SerialConnection, LoginScript, SerialPortInfo, BAUD_RATES } from '../api'
import { SerialService } from '../services/serial.service'
// import { PromptModalComponent } from './promptModal.component'
/** @hidden */
@Component({
template: require('./editConnectionModal.component.pug'),
})
export class EditConnectionModalComponent {
connection: SerialConnection
foundPorts: SerialPortInfo[]
baudRates = BAUD_RATES
constructor (
private modalInstance: NgbActiveModal,
private electron: ElectronService,
private hostApp: HostAppService,
private serial: SerialService,
) {
}
portsAutocomplete = text$ => text$.pipe(map(() => {
return this.foundPorts.map(x => x.name)
}))
portsFormatter = port => {
const p = this.foundPorts.find(x => x.name === port)
if (p?.description) {
return `${port} (${p.description})`
}
return port
}
async ngOnInit () {
this.connection.scripts = this.connection.scripts || []
this.foundPorts = await this.serial.listPorts()
}
save () {
this.modalInstance.close(this.connection)
}
cancel () {
this.modalInstance.dismiss()
}
moveScriptUp (script: LoginScript) {
if (!this.connection.scripts) {
this.connection.scripts = []
}
const index = this.connection.scripts.indexOf(script)
if (index > 0) {
this.connection.scripts.splice(index, 1)
this.connection.scripts.splice(index - 1, 0, script)
}
}
moveScriptDown (script: LoginScript) {
if (!this.connection.scripts) {
this.connection.scripts = []
}
const index = this.connection.scripts.indexOf(script)
if (index >= 0 && index < this.connection.scripts.length - 1) {
this.connection.scripts.splice(index, 1)
this.connection.scripts.splice(index + 1, 0, script)
}
}
async deleteScript (script: LoginScript) {
if (this.connection.scripts && (await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
message: 'Delete this script?',
detail: script.expect,
buttons: ['Keep', 'Delete'],
defaultId: 1,
}
)).response === 1) {
this.connection.scripts = this.connection.scripts.filter(x => x !== script)
}
}
addScript () {
if (!this.connection.scripts) {
this.connection.scripts = []
}
this.connection.scripts.push({ expect: '', send: '' })
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,16 @@
h3 Connections
.list-group.list-group-flush.mt-3.mb-3
.list-group-item.list-group-item-action.d-flex.align-items-center(
*ngFor='let connection of connections',
(click)='editConnection(connection)'
)
.mr-auto
div {{connection.name}}
.text-muted {{connection.port}}
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteConnection(connection)')
i.fas.fa-trash
button.btn.btn-primary((click)='createConnection()')
i.fas.fa-fw.fa-plus
span.ml-2 Add connection

View File

@@ -0,0 +1,80 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, ElectronService, HostAppService } from 'terminus-core'
import { SerialConnection } from '../api'
import { EditConnectionModalComponent } from './editConnectionModal.component'
/** @hidden */
@Component({
template: require('./serialSettingsTab.component.pug'),
})
export class SerialSettingsTabComponent {
connections: SerialConnection[]
constructor (
public config: ConfigService,
private electron: ElectronService,
private hostApp: HostAppService,
private ngbModal: NgbModal,
) {
this.connections = this.config.store.serial.connections
this.refresh()
}
createConnection () {
const connection: SerialConnection = {
name: '',
port: '',
baudrate: 115200,
databits: 8,
parity: 'none',
rtscts: false,
stopbits: 1,
xany: false,
xoff: false,
xon: false,
}
const modal = this.ngbModal.open(EditConnectionModalComponent)
modal.componentInstance.connection = connection
modal.result.then(result => {
this.connections.push(result)
this.config.store.serial.connections = this.connections
this.config.save()
this.refresh()
})
}
editConnection (connection: SerialConnection) {
const modal = this.ngbModal.open(EditConnectionModalComponent, { size: 'lg' })
modal.componentInstance.connection = Object.assign({}, connection)
modal.result.then(result => {
Object.assign(connection, result)
this.config.store.serial.connections = this.connections
this.config.save()
this.refresh()
})
}
async deleteConnection (connection: SerialConnection) {
if ((await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
message: `Delete "${connection.name}"?`,
buttons: ['Keep', 'Delete'],
defaultId: 1,
}
)).response === 1) {
this.connections = this.connections.filter(x => x !== connection)
this.config.store.serial.connections = this.connections
this.config.save()
this.refresh()
}
}
refresh () {
this.connections = this.config.store.serial.connections
}
}

View File

@@ -0,0 +1,16 @@
.tab-toolbar
.btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h
.toolbar(*ngIf='session', [class.show]='!session.open')
i.fas.fa-circle.text-success.mr-2(*ngIf='session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open')
strong(*ngIf='session') {{session.connection.port}} ({{session.connection.baudrate}})
.mr-auto
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session.open')
span Change baud rate
button.btn.btn-info((click)='reconnect()', *ngIf='!session.open')
i.fas.fa-reload
span Reconnect

View File

@@ -0,0 +1,7 @@
@import '../../../terminus-ssh/src/components/sshTab.component.scss';
:host {
select {
width: auto;
}
}

View File

@@ -0,0 +1,122 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import colors from 'ansi-colors'
import { Spinner } from 'cli-spinner'
import { Component, Injector } from '@angular/core'
import { first } from 'rxjs/operators'
import { BaseTerminalTabComponent } from 'terminus-terminal'
import { SerialService } from '../services/serial.service'
import { SerialConnection, SerialSession, BAUD_RATES } from '../api'
import { Subscription } from 'rxjs'
/** @hidden */
@Component({
selector: 'serial-tab',
template: BaseTerminalTabComponent.template + require<string>('./serialTab.component.pug'),
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
animations: BaseTerminalTabComponent.animations,
})
export class SerialTabComponent extends BaseTerminalTabComponent {
connection: SerialConnection
session: SerialSession
serialPort: any
private homeEndSubscription: Subscription
constructor (
injector: Injector,
private serial: SerialService,
) {
super(injector)
}
ngOnInit () {
this.logger = this.log.create('terminalTab')
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
if (!this.hasFocus) {
return
}
switch (hotkey) {
case 'home':
this.sendInput('\x1b[H' )
break
case 'end':
this.sendInput('\x1b[F' )
break
}
})
this.frontendReady$.pipe(first()).subscribe(() => {
this.initializeSession()
})
super.ngOnInit()
setImmediate(() => {
this.setTitle(this.connection.name)
})
}
async initializeSession () {
if (!this.connection) {
this.logger.error('No Serial connection info supplied')
return
}
this.session = this.serial.createSession(this.connection)
this.session.serviceMessage$.subscribe(msg => {
this.write('\r\n' + colors.black.bgWhite(' serial ') + ' ' + msg + '\r\n')
this.session.resize(this.size.columns, this.size.rows)
})
this.attachSessionHandlers()
this.write(`Connecting to `)
const spinner = new Spinner({
text: 'Connecting',
stream: {
write: x => this.write(x),
},
})
spinner.setSpinnerString(6)
spinner.start()
try {
this.serialPort = await this.serial.connectSession(this.session, (message: string) => {
spinner.stop(true)
this.write(message + '\r\n')
spinner.start()
})
spinner.stop(true)
} catch (e) {
spinner.stop(true)
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
return
}
await this.session.start()
this.session.resize(this.size.columns, this.size.rows)
}
async getRecoveryToken (): Promise<any> {
return {
type: 'app:serial-tab',
connection: this.connection,
savedState: this.frontend?.saveState(),
}
}
reconnect () {
this.initializeSession()
}
async changeBaudRate () {
const rate = await this.app.showSelector('Baud rate', BAUD_RATES.map(x => ({
name: x.toString(), result: x,
})))
this.serialPort.update({ baudRate: rate })
this.connection.baudrate = rate
}
ngOnDestroy () {
this.homeEndSubscription.unsubscribe()
super.ngOnDestroy()
}
}

View File

@@ -0,0 +1,19 @@
import { ConfigProvider } from 'terminus-core'
/** @hidden */
export class SerialConfigProvider extends ConfigProvider {
defaults = {
serial: {
connections: [],
options: {
},
},
hotkeys: {
serial: [
'Alt-K',
],
},
}
platformDefaults = { }
}

View File

@@ -0,0 +1,17 @@
import { Injectable } from '@angular/core'
import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
/** @hidden */
@Injectable()
export class SerialHotkeyProvider extends HotkeyProvider {
hotkeys: HotkeyDescription[] = [
{
id: 'serial',
name: 'Show Serial connections',
},
]
async provide (): Promise<HotkeyDescription[]> {
return this.hotkeys
}
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="16"
viewBox="0 0 32 16"
version="1.1"
id="svg3749">
<defs
id="defs3753" />
<g
id="g3747"
transform="matrix(0.48599086,0,0,0.48599086,0.50191451,-0.299629)"
style="fill:none;fill-rule:evenodd">
<g
id="g3741"
transform="translate(-292.02353,-314.25882)"
style="fill:#ffffff">
<path
style="fill-rule:nonzero;stroke-width:0.10270619"
d="M 16.007812,0 3.2929688,0.03515625 2.2324219,0.40234375 C 0.91449728,1.1071083 0,2.575555 0,3.9863281 c 0,1.2651363 1.3074352,7.8137089 1.7402344,8.7167969 0.553077,1.153703 1.988134,2.456836 3.234375,2.9375 0.8530743,0.328933 1.4753185,0.348528 10.9804686,0.357422 9.789951,0.0091 10.106534,-0.002 11.087891,-0.369141 1.221173,-0.456851 2.835858,-1.955656 3.333984,-3.09375 0.336145,-0.767943 1.638672,-7.5615083 1.638672,-8.5488279 0,-1.4107731 -0.849384,-3.02258715 -2.234375,-3.58398435 L 28.791016,0 Z m -4.27539,4.890625 c 0.427942,0 0.812664,0.071135 1.152344,0.2128906 0.342354,0.1390812 0.631097,0.3382162 0.86914,0.5976563 0.243393,0.2674641 0.430211,0.5965523 0.558594,0.984375 0.131057,0.3878229 0.197266,0.8262256 0.197266,1.3183593 0,0.4921338 -0.06744,0.9337216 -0.201172,1.3242188 -0.131058,0.387823 -0.316645,0.711263 -0.554688,0.970703 -0.246067,0.270139 -0.536042,0.474922 -0.873047,0.611328 -0.33433,0.136407 -0.71782,0.203125 -1.148437,0.203125 -0.419919,0 -0.801456,-0.0699 -1.146484,-0.208984 C 10.243584,10.765216 9.9516549,10.563618 9.7109375,10.298828 9.4702197,10.034039 9.2834009,9.7093672 9.1523438,9.3242188 9.0239608,8.9390707 8.9609375,8.4987146 8.9609375,8.0039062 c 0,-0.4867846 0.063023,-0.9214925 0.1914063,-1.3066406 C 9.2807263,6.3094427 9.4687769,5.9766597 9.7148438,5.7011719 9.950212,5.4390572 10.242141,5.2386906 10.589844,5.0996094 10.940222,4.9605279 11.320527,4.890625 11.732422,4.890625 Z m 9.933594,0 c 0.427942,0 0.812664,0.071135 1.152343,0.2128906 0.342354,0.1390812 0.631098,0.3382162 0.869141,0.5976563 0.243392,0.2674641 0.430211,0.5965523 0.558594,0.984375 0.131057,0.3878229 0.197265,0.8262256 0.197265,1.3183593 0,0.4921338 -0.06744,0.9337216 -0.201171,1.3242188 -0.131058,0.387823 -0.316645,0.711263 -0.554688,0.970703 -0.246067,0.270139 -0.536042,0.474922 -0.873047,0.611328 -0.33433,0.136407 -0.71782,0.203125 -1.148437,0.203125 -0.419919,0 -0.801456,-0.0699 -1.146485,-0.208984 -0.342353,-0.139081 -0.634282,-0.340679 -0.875,-0.605469 C 19.403813,10.034039 19.216995,9.7093672 19.085938,9.3242188 18.957555,8.9390707 18.894531,8.4987146 18.894531,8.0039062 c 0,-0.4867846 0.06302,-0.9214925 0.191407,-1.3066406 0.128382,-0.3878229 0.316433,-0.7206059 0.5625,-0.9960937 0.235368,-0.2621147 0.527296,-0.4624813 0.875,-0.6015625 0.350377,-0.1390815 0.730683,-0.2089844 1.142578,-0.2089844 z m -16.0839848,0.125 h 2.359375 V 5.625 H 7.1582031 v 4.753906 h 0.7832031 v 0.611328 H 5.5820312 V 10.378906 H 6.3652344 V 5.625 H 5.5820312 Z m 9.9335938,0 H 17.875 V 5.625 h -0.783203 v 4.753906 H 17.875 v 0.611328 h -2.359375 v -0.611328 h 0.783203 V 5.625 h -0.783203 z m 9.933594,0 h 2.359375 V 5.625 h -0.783203 v 4.753906 h 0.783203 v 0.611328 h -2.359375 v -0.611328 h 0.783203 V 5.625 h -0.783203 z m -13.712891,0.5625 c -0.607143,0 -1.083937,0.2102191 -1.43164,0.6328125 -0.3450291,0.4199185 -0.5175786,1.0173231 -0.5175786,1.7929687 0,0.7836694 0.1762443,1.3854905 0.5292966,1.8027344 0.353053,0.4145694 0.826152,0.6210934 1.419922,0.6210934 0.59377,0 1.065638,-0.206524 1.416016,-0.6210934 0.353052,-0.4172439 0.529297,-1.019065 0.529297,-1.8027344 0,-0.7756456 -0.173782,-1.3730502 -0.521485,-1.7929687 C 12.812453,5.7883441 12.338122,5.578125 11.736328,5.578125 Z m 9.933594,0 c -0.607144,0 -1.083938,0.2102191 -1.431641,0.6328125 -0.345028,0.4199185 -0.517578,1.0173231 -0.517578,1.7929687 0,0.7836694 0.176244,1.3854905 0.529297,1.8027344 0.353052,0.4145694 0.826152,0.6210934 1.419922,0.6210934 0.59377,0 1.065638,-0.206524 1.416016,-0.6210934 0.353052,-0.4172439 0.529296,-1.019065 0.529296,-1.8027344 0,-0.7756456 -0.173781,-1.3730502 -0.521484,-1.7929687 C 22.746047,5.7883441 22.271716,5.578125 21.669922,5.578125 Z"
transform="matrix(2.0576519,0,0,2.0576519,290.99076,314.87535)"
id="path3739" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,51 @@
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { ToastrModule } from 'ngx-toastr'
import TerminusCoreModule, { ToolbarButtonProvider, ConfigProvider, TabRecoveryProvider, HotkeyProvider } from 'terminus-core'
import { SettingsTabProvider } from 'terminus-settings'
import TerminusTerminalModule from 'terminus-terminal'
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
import { SerialModalComponent } from './components/serialModal.component'
import { SerialSettingsTabComponent } from './components/serialSettingsTab.component'
import { SerialTabComponent } from './components/serialTab.component'
import { ButtonProvider } from './buttonProvider'
import { SerialConfigProvider } from './config'
import { SerialSettingsTabProvider } from './settings'
import { RecoveryProvider } from './recoveryProvider'
import { SerialHotkeyProvider } from './hotkeys'
/** @hidden */
@NgModule({
imports: [
NgbModule,
CommonModule,
FormsModule,
ToastrModule,
TerminusCoreModule,
TerminusTerminalModule,
],
providers: [
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
{ provide: ConfigProvider, useClass: SerialConfigProvider, multi: true },
{ provide: SettingsTabProvider, useClass: SerialSettingsTabProvider, multi: true },
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
{ provide: HotkeyProvider, useClass: SerialHotkeyProvider, multi: true },
],
entryComponents: [
EditConnectionModalComponent,
SerialModalComponent,
SerialSettingsTabComponent,
SerialTabComponent,
],
declarations: [
EditConnectionModalComponent,
SerialModalComponent,
SerialSettingsTabComponent,
SerialTabComponent,
],
})
export default class SerialModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class

View File

@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from 'terminus-core'
import { SerialTabComponent } from './components/serialTab.component'
/** @hidden */
@Injectable()
export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
if (recoveryToken?.type === 'app:serial-tab') {
return {
type: SerialTabComponent,
options: {
connection: recoveryToken['connection'],
savedState: recoveryToken['savedState'],
},
}
}
return null
}
}

View File

@@ -0,0 +1,60 @@
import { Injectable, NgZone } from '@angular/core'
import SerialPort from 'serialport'
import { ToastrService } from 'ngx-toastr'
import { LogService } from 'terminus-core'
import { SerialConnection, SerialSession, SerialPortInfo } from '../api'
@Injectable({ providedIn: 'root' })
export class SerialService {
private constructor (
private log: LogService,
private zone: NgZone,
private toastr: ToastrService,
) { }
async listPorts (): Promise<SerialPortInfo[]> {
return (await SerialPort.list()).map(x => ({
name: x.path,
description: x.manufacturer || x.serialNumber ? `${x.manufacturer || ''} ${x.serialNumber || ''}` : undefined,
}))
}
createSession (connection: SerialConnection): SerialSession {
const session = new SerialSession(connection)
session.logger = this.log.create(`serial-${connection.port}`)
return session
}
async connectSession (session: SerialSession, _?: (s: any) => void): Promise<SerialPort> {
const serial = new SerialPort(session.connection.port, { autoOpen: false, baudRate: session.connection.baudrate,
dataBits: session.connection.databits, stopBits: session.connection.stopbits, parity: session.connection.parity,
rtscts: session.connection.rtscts, xon: session.connection.xon, xoff: session.connection.xoff,
xany: session.connection.xany })
session.serial = serial
let connected = false
await new Promise(async (resolve, reject) => {
serial.on('open', () => {
connected = true
this.zone.run(resolve)
})
serial.on('error', error => {
this.zone.run(() => {
if (connected) {
this.toastr.error(error.toString())
} else {
reject(error)
}
})
})
try {
serial.open()
} catch (e) {
this.toastr.error(e.message)
reject(e)
}
})
return serial
}
}

View File

@@ -0,0 +1,16 @@
import { Injectable } from '@angular/core'
import { SettingsTabProvider } from 'terminus-settings'
import { SerialSettingsTabComponent } from './components/serialSettingsTab.component'
/** @hidden */
@Injectable()
export class SerialSettingsTabProvider extends SettingsTabProvider {
id = 'serial'
icon = 'keyboard'
title = 'Serial'
getComponentType (): any {
return SerialSettingsTabComponent
}
}

View File

@@ -0,0 +1,7 @@
{
"extends": "../tsconfig.json",
"exclude": ["node_modules", "dist", "typings"],
"compilerOptions": {
"baseUrl": "src"
}
}

View File

@@ -0,0 +1,15 @@
{
"extends": "../tsconfig.json",
"exclude": ["node_modules", "dist", "typings"],
"include": ["src"],
"compilerOptions": {
"baseUrl": "src",
"emitDeclarationOnly": true,
"declaration": true,
"declarationDir": "./typings",
"paths": {
"terminus-*": ["../../terminus-*"],
"*": ["../../app/node_modules/*"]
}
}
}

View File

@@ -0,0 +1,59 @@
const path = require('path')
module.exports = {
target: 'node',
entry: 'src/index.ts',
context: __dirname,
devtool: 'source-map',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
pathinfo: true,
libraryTarget: 'umd',
devtoolModuleFilenameTemplate: 'webpack-terminus-serial:///[resource-path]',
},
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
optimization:{
minimize: false,
},
resolve: {
modules: ['.', 'src', 'node_modules', '../app/node_modules'].map(x => path.join(__dirname, x)),
extensions: ['.ts', '.js', '.node'],
},
module: {
rules: [
{
test: /\.ts$/,
use: {
loader: 'awesome-typescript-loader',
options: {
configFileName: path.resolve(__dirname, 'tsconfig.json'),
typeRoots: [
path.resolve(__dirname, 'node_modules/@types'),
path.resolve(__dirname, '../node_modules/@types'),
],
paths: {
"terminus-*": [path.resolve(__dirname, '../terminus-*')],
"*": [path.resolve(__dirname, '../app/node_modules/*')],
},
},
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.svg/, use: ['svg-inline-loader'] },
],
},
externals: [
'fs',
'keytar',
'path',
'ngx-toastr',
'serialport',
'windows-process-tree/build/Release/windows_process_tree.node',
/^rxjs/,
/^@angular/,
/^@ng-bootstrap/,
/^terminus-/,
],
}

1110
terminus-serial/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-settings",
"version": "1.0.99-nightly.0",
"version": "1.0.104-nightly.0",
"description": "Terminus terminal settings page",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -27,7 +27,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
title: 'Settings',
touchBarNSImage: 'NSTouchBarComposeTemplate',
weight: 10,
click: () => this.open(),
click: (): void => this.open(),
}]
}

View File

@@ -61,7 +61,7 @@ export class HotkeyInputModalComponent {
return keys.split('+').map((x) => x.trim())
}
ngOnInit () {
ngOnInit (): void {
this.keyTimeoutInterval = window.setInterval(() => {
if (!this.lastKeyEvent) {
return
@@ -74,14 +74,14 @@ export class HotkeyInputModalComponent {
this.hotkeys.disable()
}
ngOnDestroy () {
ngOnDestroy (): void {
this.keySubscription.unsubscribe()
this.hotkeys.clearCurrentKeystrokes()
this.hotkeys.enable()
clearInterval(this.keyTimeoutInterval!)
}
close () {
close (): void {
this.modalInstance.dismiss()
}
}

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