Compare commits

..

291 Commits

Author SHA1 Message Date
Eugene Pankov
d0ddd82906 fixed wsl crash when default distro is not available (fixes #2130) 2020-02-18 10:52:17 +01: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
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
Eugene Pankov
f6d08af986 Revert "re-added snap build"
This reverts commit ff2c2031b5.
2020-01-30 18:54:55 +03:00
Eugene Pankov
7ddb67f28e added snap plugs 2020-01-29 15:10:47 +03:00
Eugene Pankov
ff2c2031b5 re-added snap build 2020-01-29 15:05:34 +03:00
Eugene Pankov
1ab528b05c append --no-sandbox when starting on Linux (fixes #1525) 2020-01-29 14:28:03 +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
Eugene Pankov
f4f52321f5 unify context menus (fixes #2054) 2020-01-28 21:39:02 +03:00
Eugene Pankov
286b6cfdde fixed improper split tab saving (fixes #2025) 2020-01-28 20:55:51 +03:00
Eugene Pankov
b97149aa73 duplicate tab placement (fixes #2062) 2020-01-28 20:55:27 +03:00
Eugene
2094c44992 Merge pull request #2037 from Eugeny/dependabot/npm_and_yarn/electron-installer-snap-5.0.0
Bump electron-installer-snap from 4.1.0 to 5.0.0
2020-01-28 20:18:50 +03:00
Eugene
a8409a0aec Merge pull request #2047 from Eugeny/dependabot/npm_and_yarn/electron-rebuild-1.9.0
Bump electron-rebuild from 1.8.6 to 1.9.0
2020-01-28 20:18:38 +03:00
Eugene
5c2ac72bac Bump electron from 7.1.9 to 7.1.10 (#2046)
Bump electron from 7.1.9 to 7.1.10
2020-01-28 20:18:01 +03: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
Eugene
be09e7829f fixed #2048 2020-01-23 14:01:56 +01:00
dependabot-preview[bot]
a9320a33c9 Bump electron-rebuild from 1.8.6 to 1.9.0
Bumps [electron-rebuild](https://github.com/electron/electron-rebuild) from 1.8.6 to 1.9.0.
- [Release notes](https://github.com/electron/electron-rebuild/releases)
- [Changelog](https://github.com/electron/electron-rebuild/blob/master/.releaserc.json)
- [Commits](https://github.com/electron/electron-rebuild/compare/v1.8.6...v1.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-23 04:24:49 +00:00
dependabot-preview[bot]
0e881e47e2 Bump electron from 7.1.9 to 7.1.10
Bumps [electron](https://github.com/electron/electron) from 7.1.9 to 7.1.10.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v7.1.9...v7.1.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-23 04:24:20 +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]
3b7f4be643 Bump electron-installer-snap from 4.1.0 to 5.0.0
Bumps [electron-installer-snap](https://github.com/electron-userland/electron-installer-snap) from 4.1.0 to 5.0.0.
- [Release notes](https://github.com/electron-userland/electron-installer-snap/releases)
- [Changelog](https://github.com/electron-userland/electron-installer-snap/blob/master/NEWS.md)
- [Commits](https://github.com/electron-userland/electron-installer-snap/compare/v4.1.0...v5.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-22 04:25:45 +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
Eugene Pankov
8f361f841c Update README.md 2020-01-21 23:11:01 +01:00
Eugene Pankov
0e0d59f2c5 blacklisted shell-selector 2020-01-21 23:09:27 +01:00
Eugene
ca9b8307c2 Merge pull request #1998 from Eugeny/dependabot/npm_and_yarn/terminus-core/core-js-3.6.4
Bump core-js from 3.6.3 to 3.6.4 in /terminus-core
2020-01-21 23:03:16 +01:00
Eugene
d837a3d7fd Merge pull request #1997 from Eugeny/dependabot/npm_and_yarn/core-js-3.6.4
Bump core-js from 3.6.2 to 3.6.4
2020-01-21 23:02:55 +01:00
Eugene
555e1e733d Merge pull request #2010 from Eugeny/dependabot/npm_and_yarn/webpack-5.0.0-beta.12
Bump webpack from 5.0.0-beta.11 to 5.0.0-beta.12
2020-01-21 23:02:38 +01:00
Eugene
2e546fb72e Merge pull request #2015 from Eugeny/dependabot/npm_and_yarn/terminus-terminal/uuid-3.4.0
Bump uuid from 3.3.3 to 3.4.0 in /terminus-terminal
2020-01-21 23:01:31 +01:00
Eugene
a2d4b76070 Merge pull request #2016 from Eugeny/dependabot/npm_and_yarn/terminus-core/uuid-3.4.0
Bump uuid from 3.3.3 to 3.4.0 in /terminus-core
2020-01-21 23:01:18 +01:00
Eugene
34edee2f37 Merge pull request #2024 from Eugeny/dependabot/npm_and_yarn/typedoc-0.16.7
Bump typedoc from 0.15.7 to 0.16.7
2020-01-21 23:00:58 +01:00
Eugene
f17b7fb8ce Update updater.service.ts 2020-01-21 11:57:01 +01:00
dependabot-preview[bot]
cbe5ea7fdd Bump core-js from 3.6.2 to 3.6.4
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.2 to 3.6.4.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.2...v3.6.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-21 10:37:51 +00:00
dependabot-preview[bot]
c00405afff Bump core-js from 3.6.3 to 3.6.4 in /terminus-core
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.3 to 3.6.4.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.3...v3.6.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-21 10:37:06 +00:00
dependabot-preview[bot]
555db7bef9 Bump webpack from 5.0.0-beta.11 to 5.0.0-beta.12
Bumps [webpack](https://github.com/webpack/webpack) from 5.0.0-beta.11 to 5.0.0-beta.12.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.0.0-beta.11...v5.0.0-beta.12)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-21 10:35:55 +00:00
Eugene
94e9e7d439 Bump electron from 7.1.7 to 7.1.9 (#1995)
Bump electron from 7.1.7 to 7.1.9
2020-01-21 11:35:44 +01:00
dependabot-preview[bot]
c4850f2172 Bump electron from 7.1.7 to 7.1.9
Bumps [electron](https://github.com/electron/electron) from 7.1.7 to 7.1.9.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v7.1.7...v7.1.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-21 10:35:11 +00:00
Eugene
2d33a0030d Merge pull request #2033 from Eugeny/dependabot/npm_and_yarn/typescript-eslint/parser-2.17.0
Bump @typescript-eslint/parser from 2.15.0 to 2.17.0
2020-01-21 11:33:45 +01:00
Eugene
1f576edf85 Merge pull request #1984 from Eugeny/dependabot/npm_and_yarn/css-loader-3.4.2
Bump css-loader from 3.4.1 to 3.4.2
2020-01-21 11:33:11 +01:00
Eugene
6d139434d7 Merge pull request #1982 from Eugeny/dependabot/npm_and_yarn/eslint-plugin-import-2.20.0
Bump eslint-plugin-import from 2.19.1 to 2.20.0
2020-01-21 11:33:03 +01:00
dependabot-preview[bot]
e9ba07c7a3 Bump @typescript-eslint/parser from 2.15.0 to 2.17.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.15.0 to 2.17.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.17.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-21 04:23:20 +00:00
Eugene
4f083098c3 Merge pull request #2026 from CyrilTaylor/dev/wsl/icon
add icon for wsl distributions(fixes #2020)
2020-01-20 09:47:58 +01:00
Eugene
03369da32c Merge pull request #2028 from CyrilTaylor/dev/os.platform
update identify of platform
2020-01-20 09:46:19 +01:00
Cyril Taylor
edb2cf2b7b add icon for wsl distributions(#2020) 2020-01-20 15:56:46 +08:00
Cyril Taylor
91a1ae1cbe update identify of platform 2020-01-20 15:30:39 +08:00
dependabot-preview[bot]
4a9f17ace9 Bump typedoc from 0.15.7 to 0.16.7
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.15.7 to 0.16.7.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.15.7...v0.16.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-20 04:26:08 +00:00
Eugene
d5babde1fa Update xtermFrontend.ts 2020-01-17 13:57:31 +01:00
dependabot-preview[bot]
902c1fceb1 Bump uuid from 3.3.3 to 3.4.0 in /terminus-core
Bumps [uuid](https://github.com/uuidjs/uuid) from 3.3.3 to 3.4.0.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v3.3.3...v3.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-17 04:30:59 +00:00
dependabot-preview[bot]
1d340e4666 Bump uuid from 3.3.3 to 3.4.0 in /terminus-terminal
Bumps [uuid](https://github.com/uuidjs/uuid) from 3.3.3 to 3.4.0.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v3.3.3...v3.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-17 04:24:01 +00:00
Eugene Pankov
b922fe7776 fixed corrupted profile icons 2020-01-16 17:48:40 +01:00
Eugene Pankov
de3829a94c fixed cygwin $PATH (fixes #1683, fixes #1570) 2020-01-16 17:45:32 +01:00
Eugene Pankov
964e0ad2bc hide __nonStructural members from the default config (fixes #2004) 2020-01-15 16:20:32 +01:00
Eugene Pankov
742affb88b allow resizing window near the drag space (fixes #2005) 2020-01-15 16:07:51 +01:00
Eugene Pankov
e9999ee883 don't crash if the PTY suddenly produces strings (#2004, fixes #1955) 2020-01-15 16:07:13 +01:00
Eugene Pankov
1c8288bfe1 bumped xterm 2020-01-14 11:57:17 +01:00
Eugene Pankov
37044fbb01 enable vibrancy by default 2020-01-14 11:57:08 +01:00
Eugene Pankov
5507171fee zmodem fixes (fixes #1949) 2020-01-14 11:41:05 +01:00
Eugene
472b421484 Merge pull request #2000 from CyrilTaylor/dev/portable/userData_location
set userData location to the 'data' folder which at the same level as the Terminus executable directory if exist with portable mode
2020-01-14 09:26:26 +01:00
Eugene
b076541962 Merge pull request #1991 from CyrilTaylor/dev.theme.compact.margin
narrow down the margin of ssh tab to 5px with theme compact
2020-01-14 09:25:12 +01:00
Cyril Taylor
8201e0b9ef set userData location to the 'data' folder which at the same level as the Terminus executable directory if exist with portable mode 2020-01-14 15:06:54 +08:00
Cyril Taylor
6293a43571 narrow down the margin of ssh tab to 5px with theme compact 2020-01-14 11:34:52 +08:00
Eugene
b61bc943ec Merge pull request #1989 from Eugeny/all-contributors/add-CyrilTaylor
docs: add CyrilTaylor as a contributor
2020-01-13 12:27:47 +01:00
allcontributors[bot]
be668403c5 docs: update .all-contributorsrc [skip ci] 2020-01-13 11:27:32 +00:00
allcontributors[bot]
90a173d8b7 docs: update README.md [skip ci] 2020-01-13 11:27:31 +00:00
Eugene
bbcc84e9b0 1. Fit the shell integration with windos registry style 2. Add… (#1986)
1. Fit the shell integration with windos registry style 2. Add folder context menu with Terminus
2020-01-13 12:27:13 +01:00
Cyril Taylor
b0a8832499 remove old entry for windows shell integration 2020-01-13 19:07:03 +08:00
Eugene
8cd1c4a9af Update sshTab.component.ts 2020-01-13 11:53:28 +01:00
Cyril Taylor
1ada4338b7 1. Fit the shell integration with windos registry style 2. Add folder context menu with Terminus 2020-01-13 14:08:58 +08:00
dependabot-preview[bot]
4a701fa7b4 Bump css-loader from 3.4.1 to 3.4.2
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 3.4.1 to 3.4.2.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v3.4.1...v3.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-13 04:25:02 +00:00
dependabot-preview[bot]
b718448904 Bump eslint-plugin-import from 2.19.1 to 2.20.0
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.19.1 to 2.20.0.
- [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.19.1...v2.20.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-13 04:24:11 +00:00
Eugene
7770cf2573 Bump core-js from 3.6.1 to 3.6.3 in /terminus-core (#1978)
Bump core-js from 3.6.1 to 3.6.3 in /terminus-core
2020-01-11 14:13:50 +01:00
dependabot-preview[bot]
49755f855f Bump core-js from 3.6.1 to 3.6.3 in /terminus-core
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.1 to 3.6.3.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.1...v3.6.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-11 13:12:40 +00:00
Eugene
daa1b4572e Bump node-gyp from 6.0.1 to 6.1.0 (#1968)
Bump node-gyp from 6.0.1 to 6.1.0
2020-01-11 14:11:22 +01:00
Eugene
d48e22a9d2 Bump slug from 2.0.0 to 2.1.0 in /terminus-terminal (#1947)
Bump slug from 2.0.0 to 2.1.0 in /terminus-terminal
2020-01-11 14:08:30 +01:00
Eugene
fc82010729 Bump @types/webpack-env from 1.14.1 to 1.15.0 (#1961)
Bump @types/webpack-env from 1.14.1 to 1.15.0
2020-01-11 14:08:17 +01:00
Eugene
4a8f3fbd7f Bump core-js from 3.6.1 to 3.6.2 in /terminus-core (#1965)
Bump core-js from 3.6.1 to 3.6.2 in /terminus-core
2020-01-11 14:08:05 +01:00
Eugene
4c435672a5 Bump core-js from 3.6.1 to 3.6.2 (#1963)
Bump core-js from 3.6.1 to 3.6.2
2020-01-11 14:07:44 +01:00
Eugene
0311754ce0 Bump css-loader from 3.4.0 to 3.4.1 (#1960)
Bump css-loader from 3.4.0 to 3.4.1
2020-01-11 14:07:30 +01:00
Eugene
ff5da104c1 Bump @typescript-eslint/parser from 2.14.0 to 2.15.0 (#1962)
Bump @typescript-eslint/parser from 2.14.0 to 2.15.0
2020-01-11 14:07:12 +01:00
Eugene
b01b902829 Bump typedoc from 0.15.6 to 0.15.7 (#1975)
Bump typedoc from 0.15.6 to 0.15.7
2020-01-11 14:06:45 +01:00
Eugene
595707eed4 Bump axios from 0.19.0 to 0.19.1 in /terminus-core (#1969)
Bump axios from 0.19.0 to 0.19.1 in /terminus-core
2020-01-11 14:06:35 +01:00
Eugene
441ee4fb6e Bump axios from 0.19.0 to 0.19.1 in /terminus-plugin-manager (#1970)
Bump axios from 0.19.0 to 0.19.1 in /terminus-plugin-manager
2020-01-11 14:06:20 +01:00
dependabot-preview[bot]
51827d6750 Bump typedoc from 0.15.6 to 0.15.7
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.15.6 to 0.15.7.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.15.6...v0.15.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-10 04:23:31 +00:00
dependabot-preview[bot]
9807bbe32a Bump axios from 0.19.0 to 0.19.1 in /terminus-plugin-manager
Bumps [axios](https://github.com/axios/axios) from 0.19.0 to 0.19.1.
- [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/v0.19.0...0.19.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 04:25:18 +00:00
dependabot-preview[bot]
181b55890d Bump axios from 0.19.0 to 0.19.1 in /terminus-core
Bumps [axios](https://github.com/axios/axios) from 0.19.0 to 0.19.1.
- [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/v0.19.0...0.19.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 04:25:09 +00:00
dependabot-preview[bot]
c8c5f1a0fd Bump node-gyp from 6.0.1 to 6.1.0
Bumps [node-gyp](https://github.com/nodejs/node-gyp) from 6.0.1 to 6.1.0.
- [Release notes](https://github.com/nodejs/node-gyp/releases)
- [Changelog](https://github.com/nodejs/node-gyp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodejs/node-gyp/compare/v6.0.1...v6.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 04:24:57 +00:00
dependabot-preview[bot]
222c6a9f3c Bump core-js from 3.6.1 to 3.6.2 in /terminus-core
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.1 to 3.6.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.1...v3.6.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 04:25:23 +00:00
dependabot-preview[bot]
0400c8fe63 Bump core-js from 3.6.1 to 3.6.2
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.1 to 3.6.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.1...v3.6.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 04:22:18 +00:00
dependabot-preview[bot]
099d9b06d6 Bump @typescript-eslint/parser from 2.14.0 to 2.15.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.14.0 to 2.15.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.15.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 04:21:51 +00:00
dependabot-preview[bot]
ad26b39cca Bump @types/webpack-env from 1.14.1 to 1.15.0
Bumps [@types/webpack-env](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack-env) from 1.14.1 to 1.15.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack-env)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 04:24:44 +00:00
dependabot-preview[bot]
f465c359ef Bump css-loader from 3.4.0 to 3.4.1
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v3.4.0...v3.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 04:24:25 +00:00
Eugene Pankov
67aead225c Merge branch 'master' of github.com:Eugeny/terminus 2020-01-03 18:40:46 +01:00
Eugene Pankov
280c421ae4 use node-sshpk for better key parsing (fixes #1956, fixes #1612, fixes #1191, fixes #1788, fixes #1300) 2020-01-03 18:40:43 +01:00
Eugene
b6fc43faa2 Bump yargs from 15.0.2 to 15.1.0 in /app (#1953)
Bump yargs from 15.0.2 to 15.1.0 in /app
2020-01-03 16:14:31 +01:00
Eugene Pankov
b5a985b8a3 ui tweaks 2020-01-03 16:11:31 +01:00
Eugene Pankov
2f7dcf3339 made x11 forwarding configurable (fixes #1950, fixes #1954) 2020-01-03 16:04:30 +01:00
dependabot-preview[bot]
7e38f11c06 Bump yargs from 15.0.2 to 15.1.0 in /app
Bumps [yargs](https://github.com/yargs/yargs) from 15.0.2 to 15.1.0.
- [Release notes](https://github.com/yargs/yargs/releases)
- [Changelog](https://github.com/yargs/yargs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/yargs/compare/v15.0.2...v15.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-03 04:24:28 +00:00
Eugene Pankov
86cd560089 disabled electron-updater on Linux 2020-01-02 12:22:56 +01:00
dependabot-preview[bot]
c0c4580461 Bump slug from 2.0.0 to 2.1.0 in /terminus-terminal
Bumps [slug](https://github.com/Trott/node-slug) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/Trott/node-slug/releases)
- [Changelog](https://github.com/Trott/node-slug/blob/master/CHANGELOG)
- [Commits](https://github.com/Trott/node-slug/compare/v2.0.0...v2.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-01 04:23:06 +00:00
Eugene
5cb65dfd84 Bump bootstrap from 4.3.1 to 4.4.1 in /terminus-core (#1841)
Bump bootstrap from 4.3.1 to 4.4.1 in /terminus-core
2020-01-01 01:09:05 +01:00
Eugene Pankov
2b5f623b50 profile and SSH connection colors (fixes #954) 2020-01-01 01:04:41 +01:00
Eugene Pankov
a8d5cf469e ui fixes 2020-01-01 01:04:25 +01:00
Eugene Pankov
d261b89803 added notifications for tab activity (fixes #1123) 2019-12-31 23:38:27 +01:00
Eugene Pankov
21cb452d62 fixed terminal not getting focus when switching windows (fixes #692) 2019-12-31 23:20:07 +01:00
Eugene Pankov
b07a2113d2 ssh: added a reconnect button (fixes #761) 2019-12-31 23:12:08 +01:00
Eugene Pankov
f545b3eacf mention Zmodem in README 2019-12-31 22:51:58 +01:00
Eugene Pankov
87fe8deaa8 apis 2019-12-31 22:48:36 +01:00
Eugene Pankov
1068450ddd performance improv 2019-12-31 22:30:05 +01:00
Eugene Pankov
b355fff0f8 added a shortcut to maximize a pane (fixes #819) 2019-12-31 21:53:36 +01:00
Eugene
f80b0eb65b Bump rxjs from 6.5.3 to 6.5.4 in /app (#1934)
Bump rxjs from 6.5.3 to 6.5.4 in /app
2019-12-31 20:16:49 +01:00
dependabot-preview[bot]
285691326f Bump rxjs from 6.5.3 to 6.5.4 in /app
Bumps [rxjs](https://github.com/reactivex/rxjs) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/reactivex/rxjs/releases)
- [Changelog](https://github.com/ReactiveX/rxjs/blob/6.5.4/CHANGELOG.md)
- [Commits](https://github.com/reactivex/rxjs/compare/6.5.3...6.5.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-31 19:15:39 +00:00
Eugene
3ecffbfda6 Bump typescript from 3.7.3 to 3.7.4 (#1939)
Bump typescript from 3.7.3 to 3.7.4
2019-12-31 20:14:36 +01:00
Eugene
3d89a15d18 Bump rxjs-compat from 6.5.3 to 6.5.4 in /app (#1936)
Bump rxjs-compat from 6.5.3 to 6.5.4 in /app
2019-12-31 20:14:17 +01:00
dependabot-preview[bot]
491d4c3b3a Bump typescript from 3.7.3 to 3.7.4
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.7.3 to 3.7.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-31 19:13:57 +00:00
Eugene
995f329835 Bump @fortawesome/fontawesome-free from 5.11.2 to 5.12.0 (#1937)
Bump @fortawesome/fontawesome-free from 5.11.2 to 5.12.0
2019-12-31 20:13:19 +01:00
Eugene
28f2ea595d Bump style-loader from 1.0.1 to 1.1.2 (#1938)
Bump style-loader from 1.0.1 to 1.1.2
2019-12-31 20:12:34 +01:00
Eugene
42b7c573ea Bump @typescript-eslint/parser from 2.13.0 to 2.14.0 (#1945)
Bump @typescript-eslint/parser from 2.13.0 to 2.14.0
2019-12-31 20:12:05 +01:00
Eugene Pankov
c40294628a zmodem support (fixes #693) 2019-12-31 20:10:37 +01:00
Eugene Pankov
c11a10144e ssh: stow away the ports button (fixes #1932) 2019-12-31 13:27:34 +01:00
Eugene Pankov
7b6cdb274c fixed shell process not being killed on tab close 2019-12-31 13:01:37 +01:00
dependabot-preview[bot]
a3c74ecdba Bump @typescript-eslint/parser from 2.13.0 to 2.14.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.13.0 to 2.14.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.14.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-31 04:24:07 +00:00
Eugene Pankov
94d91f8182 reset split ratio on double click (fixes #1377) 2019-12-30 18:42:50 +01:00
Eugene Pankov
e4f32c9ade fixed split tab spanner width (fixes #1676) 2019-12-30 18:24:14 +01:00
dependabot-preview[bot]
65fd7b05b1 Bump style-loader from 1.0.1 to 1.1.2
Bumps [style-loader](https://github.com/webpack-contrib/style-loader) from 1.0.1 to 1.1.2.
- [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.0.1...v1.1.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-30 04:24:12 +00:00
dependabot-preview[bot]
2150fab55b Bump @fortawesome/fontawesome-free from 5.11.2 to 5.12.0
Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 5.11.2 to 5.12.0.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/5.11.2...5.12.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-30 04:23:42 +00:00
dependabot-preview[bot]
644cb76fd3 Bump rxjs-compat from 6.5.3 to 6.5.4 in /app
Bumps rxjs-compat from 6.5.3 to 6.5.4.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-30 04:23:22 +00:00
Eugene Pankov
4106d97f6b Revert "Bump deep-equal from 1.1.0 to 2.0.1 in /terminus-terminal"
This reverts commit 402b76bcc9.
2019-12-29 20:19:07 +01:00
Eugene Pankov
98103fd139 disable sandboxing on linux (fixes #960 again) 2019-12-29 19:07:32 +01:00
Eugene
9453e8ba7b Option to disable middle click paste (#1928)
Option to disable middle click paste
2019-12-28 23:32:10 +01:00
LeSeulArtichaut
2f78575cd7 Implement setting 2019-12-28 22:48:06 +01:00
LeSeulArtichaut
500acee064 Add pasteOnMiddleClickOption 2019-12-28 22:42:12 +01:00
Eugene
42eb5f6b78 Bump slug from 1.1.0 to 2.0.0 in /terminus-terminal (#1919)
Bump slug from 1.1.0 to 2.0.0 in /terminus-terminal
2019-12-28 22:15:41 +01:00
dependabot-preview[bot]
ef19b92e85 Bump slug from 1.1.0 to 2.0.0 in /terminus-terminal
Bumps [slug](https://github.com/Trott/node-slug) from 1.1.0 to 2.0.0.
- [Release notes](https://github.com/Trott/node-slug/releases)
- [Changelog](https://github.com/Trott/node-slug/blob/master/CHANGELOG)
- [Commits](https://github.com/Trott/node-slug/compare/v1.1.0...v2.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 21:15:27 +00:00
Eugene
f263f954d4 Bump deep-equal from 1.1.0 to 2.0.1 in /terminus-terminal (#1895)
Bump deep-equal from 1.1.0 to 2.0.1 in /terminus-terminal
2019-12-28 22:14:15 +01:00
Eugene Pankov
2ce0f03282 lint 2019-12-28 22:13:36 +01:00
Eugene
150999d3a3 Bump @typescript-eslint/eslint-plugin from 2.9.0 to 2.13.0 (#1917)
Bump @typescript-eslint/eslint-plugin from 2.9.0 to 2.13.0
2019-12-28 22:10:17 +01:00
dependabot-preview[bot]
8cc76555d2 Bump @typescript-eslint/eslint-plugin from 2.9.0 to 2.13.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 2.9.0 to 2.13.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.13.0/packages/eslint-plugin)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 21:06:02 +00:00
Eugene
f0f8f06890 Bump @typescript-eslint/parser from 2.10.0 to 2.13.0 (#1916)
Bump @typescript-eslint/parser from 2.10.0 to 2.13.0
2019-12-28 22:04:16 +01:00
Eugene
176a55c91d Bump val-loader from 2.0.1 to 2.1.0 (#1900)
Bump val-loader from 2.0.1 to 2.1.0
2019-12-28 22:04:07 +01:00
Eugene
fc6dfc50dd Bump core-js from 3.4.2 to 3.6.1 in /terminus-core (#1923)
Bump core-js from 3.4.2 to 3.6.1 in /terminus-core
2019-12-28 22:03:14 +01:00
Eugene
34d020f66a Bump core-js from 3.4.2 to 3.6.1 (#1922)
Bump core-js from 3.4.2 to 3.6.1
2019-12-28 22:03:07 +01:00
Eugene
fa0ef69c46 Bump typedoc from 0.15.3 to 0.15.6 (#1924)
Bump typedoc from 0.15.3 to 0.15.6
2019-12-28 22:02:30 +01:00
dependabot-preview[bot]
e5c1e421f7 Bump core-js from 3.4.2 to 3.6.1
Bumps [core-js](https://github.com/zloirock/core-js) from 3.4.2 to 3.6.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.4.2...v3.6.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 21:02:14 +00:00
dependabot-preview[bot]
f3994f1bd9 Bump val-loader from 2.0.1 to 2.1.0
Bumps [val-loader](https://github.com/webpack-contrib/val-loader) from 2.0.1 to 2.1.0.
- [Release notes](https://github.com/webpack-contrib/val-loader/releases)
- [Changelog](https://github.com/webpack-contrib/val-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/val-loader/compare/v2.0.1...v2.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 21:01:35 +00:00
dependabot-preview[bot]
6956ef9e0f Bump core-js from 3.4.2 to 3.6.1 in /terminus-core
Bumps [core-js](https://github.com/zloirock/core-js) from 3.4.2 to 3.6.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.4.2...v3.6.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 21:01:33 +00:00
Eugene
a080129882 Bump eslint-plugin-import from 2.18.2 to 2.19.1 (#1874)
Bump eslint-plugin-import from 2.18.2 to 2.19.1
2019-12-28 22:01:31 +01:00
Eugene
ef9bfe6120 docs: add LeSeulArtichaut as a contributor (#1927)
docs: add LeSeulArtichaut as a contributor
2019-12-28 22:01:25 +01:00
dependabot-preview[bot]
37d69e858f Bump eslint-plugin-import from 2.18.2 to 2.19.1
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.18.2 to 2.19.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.18.2...v2.19.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 21:01:24 +00:00
Eugene
ee594f5bcd Bump semver from 6.3.0 to 7.1.1 in /terminus-plugin-manager (#1899)
Bump semver from 6.3.0 to 7.1.1 in /terminus-plugin-manager
2019-12-28 22:00:37 +01:00
Eugene
adf022de2c Bump css-loader from 3.2.1 to 3.4.0 (#1901)
Bump css-loader from 3.2.1 to 3.4.0
2019-12-28 22:00:16 +01:00
Eugene
c5a9b890c4 Bump eslint from 6.7.1 to 6.8.0 (#1914)
Bump eslint from 6.7.1 to 6.8.0
2019-12-28 21:59:39 +01:00
dependabot-preview[bot]
2d1a96a12b Bump css-loader from 3.2.1 to 3.4.0
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 3.2.1 to 3.4.0.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v3.2.1...v3.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 20:59:38 +00:00
Eugene
5289981485 Bump webpack from 5.0.0-beta.7 to 5.0.0-beta.11 (#1920)
Bump webpack from 5.0.0-beta.7 to 5.0.0-beta.11
2019-12-28 21:59:22 +01:00
Eugene
a89047b205 Bump electron from 7.1.3 to 7.1.7 (#1911)
Bump electron from 7.1.3 to 7.1.7
2019-12-28 21:57:27 +01:00
Eugene
a7b4496d22 Bump windows-native-registry from 1.0.16 to 1.0.17 in /app (#1857)
Bump windows-native-registry from 1.0.16 to 1.0.17 in /app
2019-12-28 21:56:18 +01:00
Eugene
09cd9d0e18 Bump xterm-addon-webgl from 0.4.0 to 0.4.1 in /terminus-terminal (#1884)
Bump xterm-addon-webgl from 0.4.0 to 0.4.1 in /terminus-terminal
2019-12-28 21:56:04 +01:00
allcontributors[bot]
fb2a4d268d docs: update .all-contributorsrc [skip ci] 2019-12-28 20:54:29 +00:00
allcontributors[bot]
9b61615701 docs: update README.md [skip ci] 2019-12-28 20:54:28 +00:00
Eugene
077d2421e1 Merge pull request #1926 from LeSeulArtichaut/disable-right-click
Add option to disable right click in terminal
2019-12-28 21:54:22 +01:00
LeSeulArtichaut
202ba18a8c Add option to disable right click 2019-12-28 20:17:26 +01:00
dependabot-preview[bot]
63f33f8f4b Bump typedoc from 0.15.3 to 0.15.6
Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.15.3 to 0.15.6.
- [Release notes](https://github.com/TypeStrong/TypeDoc/releases)
- [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.15.3...v0.15.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-27 04:26:35 +00:00
dependabot-preview[bot]
3bd89a0194 Bump webpack from 5.0.0-beta.7 to 5.0.0-beta.11
Bumps [webpack](https://github.com/webpack/webpack) from 5.0.0-beta.7 to 5.0.0-beta.11.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.0.0-beta.7...v5.0.0-beta.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-25 04:23:26 +00:00
dependabot-preview[bot]
604bc28c9a Bump @typescript-eslint/parser from 2.10.0 to 2.13.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.10.0 to 2.13.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.13.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-24 04:25:41 +00:00
dependabot-preview[bot]
f81f5d122a Bump eslint from 6.7.1 to 6.8.0
Bumps [eslint](https://github.com/eslint/eslint) from 6.7.1 to 6.8.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.7.1...v6.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-23 04:23:30 +00:00
dependabot-preview[bot]
3633be750e Bump electron from 7.1.3 to 7.1.7
Bumps [electron](https://github.com/electron/electron) from 7.1.3 to 7.1.7.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v7.1.3...v7.1.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-20 04:23:02 +00:00
dependabot-preview[bot]
404fd72ea9 Bump semver from 6.3.0 to 7.1.1 in /terminus-plugin-manager
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 7.1.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/master/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v7.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-18 04:23:05 +00:00
dependabot-preview[bot]
402b76bcc9 Bump deep-equal from 1.1.0 to 2.0.1 in /terminus-terminal
Bumps [deep-equal](https://github.com/inspect-js/node-deep-equal) from 1.1.0 to 2.0.1.
- [Release notes](https://github.com/inspect-js/node-deep-equal/releases)
- [Changelog](https://github.com/inspect-js/node-deep-equal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/inspect-js/node-deep-equal/compare/v1.1.0...v2.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-17 04:21:25 +00:00
Eugene Pankov
b6c97ffa49 ui tweaks 2019-12-15 16:57:38 +01:00
dependabot-preview[bot]
20aa1d814f Bump xterm-addon-webgl from 0.4.0 to 0.4.1 in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.4.0 to 0.4.1.
- [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>
2019-12-12 04:23:48 +00:00
Eugene Pankov
786daaac32 lint 2019-12-11 18:07:01 +01:00
Eugene Pankov
0360ad2dd0 lint 2019-12-11 16:34:01 +01:00
Eugene Pankov
0a451c5876 automatically reconnect without x11 forwarding if rejected (fixes #1880) 2019-12-11 16:31:05 +01:00
Eugene Pankov
5a9625424c added 'duplicate as admin' tab menu item 2019-12-09 18:06:16 +01:00
Eugene Pankov
62c1f6463b added x11 forwarding (fixes #630) 2019-12-08 13:40:15 +01:00
Eugene Pankov
9fe82f2c0a xterm binary input support 2019-12-06 12:26:19 +01:00
Eugene
09838197a2 Bump electron from 7.1.2 to 7.1.3 (#1858)
Bump electron from 7.1.2 to 7.1.3
2019-12-06 12:06:38 +01:00
Eugene
27114797a2 Bump typescript from 3.7.2 to 3.7.3 (#1859)
Bump typescript from 3.7.2 to 3.7.3
2019-12-06 12:06:17 +01:00
Eugene
4dc77d11cf Bump xterm-addon-search from 0.4.0-beta5 to 0.4.0 in /terminus-… (#1863)
Bump xterm-addon-search from 0.4.0-beta5 to 0.4.0 in /terminus-terminal
2019-12-06 12:06:00 +01:00
Eugene
245698b67d Bump xterm-addon-webgl from 0.4.0-beta.15 to 0.4.0 in /terminus… (#1862)
Bump xterm-addon-webgl from 0.4.0-beta.15 to 0.4.0 in /terminus-terminal
2019-12-06 12:05:49 +01:00
Eugene
017fabaf6f Bump xterm from 4.3.0-beta.30 to 4.3.0 in /terminus-terminal (#1864)
Bump xterm from 4.3.0-beta.30 to 4.3.0 in /terminus-terminal
2019-12-06 12:05:11 +01:00
dependabot-preview[bot]
6c11189b3e Bump xterm from 4.3.0-beta.30 to 4.3.0 in /terminus-terminal
Bumps [xterm](https://github.com/xtermjs/xterm.js) from 4.3.0-beta.30 to 4.3.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/4.3.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-06 04:26:55 +00:00
dependabot-preview[bot]
dd70f5f5d8 Bump xterm-addon-search from 0.4.0-beta5 to 0.4.0 in /terminus-terminal
Bumps [xterm-addon-search](https://github.com/xtermjs/xterm.js) from 0.4.0-beta5 to 0.4.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-06 04:26:30 +00:00
dependabot-preview[bot]
47277ac5aa Bump xterm-addon-webgl from 0.4.0-beta.15 to 0.4.0 in /terminus-terminal
Bumps [xterm-addon-webgl](https://github.com/xtermjs/xterm.js) from 0.4.0-beta.15 to 0.4.0.
- [Release notes](https://github.com/xtermjs/xterm.js/releases)
- [Commits](https://github.com/xtermjs/xterm.js/commits/0.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-06 04:26:30 +00:00
Eugene
b69cbbcdd1 [Security] Bump serialize-javascript from 2.1.0 to 2.1.1 (#1861)
[Security] Bump serialize-javascript from 2.1.0 to 2.1.1
2019-12-05 20:31:44 +01:00
dependabot-preview[bot]
efba980a1d [Security] Bump serialize-javascript from 2.1.0 to 2.1.1
Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) from 2.1.0 to 2.1.1. **This update includes a security fix.**
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](https://github.com/yahoo/serialize-javascript/compare/v2.1.0...v2.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-05 18:51:22 +00:00
dependabot-preview[bot]
f31da67508 Bump typescript from 3.7.2 to 3.7.3
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.7.2 to 3.7.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.7.2...v3.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-05 04:27:04 +00:00
dependabot-preview[bot]
2ba76cc0b9 Bump electron from 7.1.2 to 7.1.3
Bumps [electron](https://github.com/electron/electron) from 7.1.2 to 7.1.3.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v7.1.2...v7.1.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-05 04:26:44 +00:00
dependabot-preview[bot]
62d14ac0cb Bump windows-native-registry from 1.0.16 to 1.0.17 in /app
Bumps [windows-native-registry](https://github.com/Eugeny/windows-native-registry) from 1.0.16 to 1.0.17.
- [Release notes](https://github.com/Eugeny/windows-native-registry/releases)
- [Commits](https://github.com/Eugeny/windows-native-registry/commits/v1.0.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-05 04:26:02 +00:00
Eugene
c1b4ffd248 Bump raw-loader from 3.1.0 to 4.0.0 (#1813)
Bump raw-loader from 3.1.0 to 4.0.0
2019-12-04 11:11:01 +01:00
Eugene
87cacdb568 Bump url-loader from 2.3.0 to 3.0.0 (#1827)
Bump url-loader from 2.3.0 to 3.0.0
2019-12-04 11:09:33 +01:00
Eugene
2a11bc4fcc Bump node-abi from 2.12.0 to 2.13.0 in /app (#1835)
Bump node-abi from 2.12.0 to 2.13.0 in /app
2019-12-04 11:04:02 +01:00
Eugene
f716baa7d4 Bump file-loader from 4.3.0 to 5.0.2 (#1815)
Bump file-loader from 4.3.0 to 5.0.2
2019-12-04 11:03:31 +01:00
Eugene
5b60daf366 Bump css-loader from 3.2.0 to 3.2.1 (#1848)
Bump css-loader from 3.2.0 to 3.2.1
2019-12-04 11:03:08 +01:00
Eugene
11f9f4e824 Bump @typescript-eslint/parser from 2.9.0 to 2.10.0 (#1845)
Bump @typescript-eslint/parser from 2.9.0 to 2.10.0
2019-12-04 11:02:38 +01:00
Eugene
0daf48f699 Bump style-loader from 1.0.0 to 1.0.1 (#1840)
Bump style-loader from 1.0.0 to 1.0.1
2019-12-04 11:01:57 +01:00
Eugene
8fb0ea4d75 Bump ssh2 from 0.8.6 to 0.8.7 in /terminus-ssh (#1852)
Bump ssh2 from 0.8.6 to 0.8.7 in /terminus-ssh
2019-12-04 11:01:38 +01:00
dependabot-preview[bot]
d9948cf6e2 Bump ssh2 from 0.8.6 to 0.8.7 in /terminus-ssh
Bumps [ssh2](https://github.com/mscdex/ssh2) from 0.8.6 to 0.8.7.
- [Release notes](https://github.com/mscdex/ssh2/releases)
- [Commits](https://github.com/mscdex/ssh2/compare/v0.8.6...v0.8.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-04 07:54:14 +00:00
Eugene
54b618cffc Merge pull request #1853 from Eugeny/dependabot/npm_and_yarn/terminus-ssh/ssh2-streams-0.4.8
Bump ssh2-streams from 0.4.7 to 0.4.8 in /terminus-ssh
2019-12-04 08:52:56 +01:00
dependabot-preview[bot]
690dde628e Bump ssh2-streams from 0.4.7 to 0.4.8 in /terminus-ssh
Bumps [ssh2-streams](https://github.com/mscdex/ssh2-streams) from 0.4.7 to 0.4.8.
- [Release notes](https://github.com/mscdex/ssh2-streams/releases)
- [Commits](https://github.com/mscdex/ssh2-streams/compare/v0.4.7...v0.4.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-04 04:22:42 +00:00
dependabot-preview[bot]
3dfbcf9d41 Bump css-loader from 3.2.0 to 3.2.1
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-03 04:26:53 +00:00
dependabot-preview[bot]
d91ba71ec0 Bump @typescript-eslint/parser from 2.9.0 to 2.10.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.9.0 to 2.10.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.10.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-03 04:25:19 +00:00
Eugene Pankov
99698913a8 lint 2019-12-03 00:55:22 +01:00
Eugene Pankov
0dbb16d859 implemented port forwarding (fixes #821) 2019-12-03 00:45:35 +01:00
Eugene Pankov
0f8cff2d5b fixes 2019-12-01 19:11:05 +01:00
Eugene Pankov
471f9effcf better search UI 2019-12-01 18:52:22 +01:00
dependabot-preview[bot]
04faf1a04a Bump file-loader from 4.3.0 to 5.0.2
Bumps [file-loader](https://github.com/webpack-contrib/file-loader) from 4.3.0 to 5.0.2.
- [Release notes](https://github.com/webpack-contrib/file-loader/releases)
- [Changelog](https://github.com/webpack-contrib/file-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/file-loader/compare/v4.3.0...v5.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-30 20:11:55 +00:00
Eugene Pankov
656f5c2561 eslint 2019-11-30 21:09:42 +01:00
Eugene
99bc2c1c65 Bump @typescript-eslint/parser from 2.8.0 to 2.9.0 (#1814)
Bump @typescript-eslint/parser from 2.8.0 to 2.9.0
2019-11-30 21:01:11 +01:00
dependabot-preview[bot]
87837bf66b Bump bootstrap from 4.3.1 to 4.4.1 in /terminus-core
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 4.3.1 to 4.4.1.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v4.3.1...v4.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-29 04:38:02 +00:00
dependabot-preview[bot]
c8735243f3 Bump style-loader from 1.0.0 to 1.0.1
Bumps [style-loader](https://github.com/webpack-contrib/style-loader) from 1.0.0 to 1.0.1.
- [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.0.0...v1.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-29 04:30:36 +00:00
dependabot-preview[bot]
b197a16e5c Bump node-abi from 2.12.0 to 2.13.0 in /app
Bumps [node-abi](https://github.com/lgeiger/node-abi) from 2.12.0 to 2.13.0.
- [Release notes](https://github.com/lgeiger/node-abi/releases)
- [Commits](https://github.com/lgeiger/node-abi/compare/v2.12.0...v2.13.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-28 04:22:41 +00:00
dependabot-preview[bot]
1a361e67b3 Bump url-loader from 2.3.0 to 3.0.0
Bumps [url-loader](https://github.com/webpack-contrib/url-loader) from 2.3.0 to 3.0.0.
- [Release notes](https://github.com/webpack-contrib/url-loader/releases)
- [Changelog](https://github.com/webpack-contrib/url-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/url-loader/compare/v2.3.0...v3.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-27 04:28:12 +00:00
Eugene Pankov
fc471b2c16 prevent infinite timers caused by sentry 2019-11-26 16:55:33 +01:00
dependabot-preview[bot]
ae17faa7e5 Bump raw-loader from 3.1.0 to 4.0.0
Bumps [raw-loader](https://github.com/webpack-contrib/raw-loader) from 3.1.0 to 4.0.0.
- [Release notes](https://github.com/webpack-contrib/raw-loader/releases)
- [Changelog](https://github.com/webpack-contrib/raw-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/raw-loader/compare/v3.1.0...v4.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-26 14:53:43 +00:00
Eugene Pankov
5fb70f1812 sentry electron sdk 2019-11-26 15:51:31 +01:00
Eugene Pankov
03fc68bb6d fixed #1785 2019-11-26 15:11:26 +01:00
Eugene Pankov
bb9c80623d fixed wnr version 2019-11-26 10:49:22 +01:00
dependabot-preview[bot]
4dd0a5951f Bump @typescript-eslint/parser from 2.8.0 to 2.9.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 2.8.0 to 2.9.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.9.0/packages/parser)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-26 04:26:18 +00:00
Eugene Pankov
b010791767 bumped xterm 2019-11-26 00:38:52 +01:00
Eugene Pankov
ef61a141a6 xterm version fix 2019-11-26 00:02:12 +01:00
130 changed files with 3802 additions and 1680 deletions

View File

@@ -225,6 +225,24 @@
"contributions": [
"code"
]
},
{
"login": "LeSeulArtichaut",
"name": "LeSeulArtichaut",
"avatar_url": "https://avatars1.githubusercontent.com/u/38361244?v=4",
"profile": "https://github.com/LeSeulArtichaut",
"contributions": [
"code"
]
},
{
"login": "CyrilTaylor",
"name": "Cyril Taylor",
"avatar_url": "https://avatars0.githubusercontent.com/u/12631466?v=4",
"profile": "https://github.com/CyrilTaylor",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
@@ -232,5 +250,6 @@
"projectOwner": "Eugeny",
"repoType": "github",
"repoHost": "https://github.com",
"commitConvention": "none"
"commitConvention": "none",
"skipCi": true
}

View File

@@ -79,6 +79,7 @@ rules:
args: after-used
argsIgnorePattern: ^_
no-undef: error
no-var: error
object-curly-spacing:
- error
- always
@@ -97,3 +98,4 @@ rules:
'@typescript-eslint/no-untyped-public-signature': off # bugs out on constructors
'@typescript-eslint/restrict-template-expressions': off
'@typescript-eslint/no-dynamic-delete': off
'@typescript-eslint/prefer-nullish-coalescing': off

View File

@@ -38,7 +38,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

@@ -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

4
.gitignore vendored
View File

@@ -24,3 +24,7 @@ yarn-error.log
docs/api
.travis.ssh.key
*.code-workspace
.electron-symbols
sentry.properties
sentry-symbols.js

View File

@@ -13,12 +13,13 @@
**Terminus** is a highly configurable terminal emulator for Windows, macOS and Linux
* Integrated SSH client and connection manager
* Theming and color schemes
* Fully configurable shortcuts
* Split panes
* Remembers your tabs
* PowerShell (and PS Core), WSL, Git-Bash, Cygwin, Cmder and CMD support
* Integrated SSH client and connection manager
* Direct file transfer from/to SSH sessions via Zmodem
* Full Unicode support including double-width characters
* Doesn't choke on fast-flowing outputs
* Proper shell experience on Windows including tab completion (via Clink)
@@ -34,12 +35,15 @@
---
# 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.
* [clickable-links](https://github.com/Eugeny/terminus-clickable-links) - makes paths and URLs in the terminal clickable
* [shell-selector](https://github.com/Eugeny/terminus-shell-selector) - a quick shell selector pane
* [title-control](https://github.com/kbjr/terminus-title-control) - allows modifying the title of the terminal tabs by providing a prefix, suffix, and/or strings to be removed
* [quick-cmds](https://github.com/Domain/terminus-quick-cmds) - quickly send commands to one or all terminal tabs
* [save-output](https://github.com/Eugeny/terminus-save-output) - record terminal output into a file
@@ -66,42 +70,47 @@ See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) and
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt="Russell Myers"/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt="Austin Warren"/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt="Felicia Hummel"/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt="Mike MacCana"/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt="Yacine Kanzari"/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt="BBJip"/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt="Futagirl"/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
</tr>
<tr>
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt="Levin Rickert"/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt="OJ Kwon"/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt="domain"/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt="James Brumond"/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt="Daniel Imms"/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt="Florian Bachmann"/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt="Michael Kühnel"/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt="Tilmann Meyer"/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt="PM Extra"/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt="Jonathan"/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt="Hans Koch"/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt="Dak Smyth"/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt="Wang Zhi"/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt="jack1142"/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt="Howie Douglas"/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt="Chris Kaczor"/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt="Johannes Kadak"/><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/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
<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>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

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'
@@ -13,16 +14,19 @@ export class Application {
})
const configData = loadConfig()
if (process.platform === 'linux' && ((configData.appearance || {}).opacity || 1) !== 1) {
app.commandLine.appendSwitch('enable-transparent-visuals')
app.disableHardwareAcceleration()
if (process.platform === 'linux') {
app.commandLine.appendSwitch('no-sandbox')
if (((configData.appearance || {}).opacity || 1) !== 1) {
app.commandLine.appendSwitch('enable-transparent-visuals')
app.disableHardwareAcceleration()
}
}
app.commandLine.appendSwitch('disable-http-cache')
app.commandLine.appendSwitch('lang', 'EN')
app.allowRendererProcessReuse = false
for (const flag of configData.flags || [['force_discrete_gpu', '0']]) {
console.log('Setting Electron flag:', flag.join('='))
app.commandLine.appendSwitch(flag[0], flag[1])
}
}
@@ -72,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',
@@ -183,7 +187,7 @@ export class Application {
},
},
],
}
},
]
Menu.setApplicationMenu(Menu.buildFromTemplate(template))

View File

@@ -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,3 +1,5 @@
import './portable'
import './sentry'
import './lru'
import { app, ipcMain, Menu } from 'electron'
import { parseArgs } from './cli'
@@ -46,7 +48,7 @@ if (argv.d) {
electronDebug({
isEnabled: true,
showDevTools: true,
devToolsMode: 'undocked'
devToolsMode: 'undocked',
})
}
@@ -57,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)
}
}
}

21
app/lib/sentry.ts Executable file
View File

@@ -0,0 +1,21 @@
const { init } = process.type === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer')
import * as isDev from 'electron-is-dev'
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
let release
try {
release = require('electron').app.getVersion()
} catch {
release = require('electron').remote.app.getVersion()
}
if (!isDev) {
init({
dsn: SENTRY_DSN,
release,
integrations (integrations) {
return integrations.filter(integration => integration.name !== 'Breadcrumbs')
},
})
}

View File

@@ -3,6 +3,7 @@ import { debounceTime } from 'rxjs/operators'
import { BrowserWindow, app, ipcMain, Rectangle, screen } from 'electron'
import ElectronConfig = require('electron-config')
import * as os from 'os'
import * as path from 'path'
import { loadConfig } from './config'
@@ -26,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 }
@@ -46,6 +49,8 @@ export class Window {
minHeight: 300,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'sentry.js'),
backgroundThrottling: false,
},
frame: false,
show: false,
@@ -54,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
}
}
@@ -115,11 +120,12 @@ export class Window {
}
setVibrancy (enabled: boolean, type?: string) {
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
@@ -129,6 +135,8 @@ export class Window {
} else {
DwmEnableBlurBehindWindow(this.window, enabled)
}
} else {
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
}
}
@@ -147,14 +155,14 @@ export class Window {
this.window.webContents.send(event, ...args)
}
isDestroyed() {
return !this.window || this.window.isDestroyed();
isDestroyed () {
return !this.window || this.window.isDestroyed()
}
private setupWindowManagement () {
this.window.on('show', () => {
this.visible.next(true)
this.window.webContents.send('host:window-shown')
this.send('host:window-shown')
})
this.window.on('hide', () => {
@@ -164,20 +172,20 @@ export class Window {
let moveSubscription = new Observable<void>(observer => {
this.window.on('move', () => observer.next())
}).pipe(debounceTime(250)).subscribe(() => {
this.window.webContents.send('host:window-moved')
this.send('host:window-moved')
})
this.window.on('closed', () => {
moveSubscription.unsubscribe()
})
this.window.on('enter-full-screen', () => this.window.webContents.send('host:window-enter-full-screen'))
this.window.on('leave-full-screen', () => this.window.webContents.send('host:window-leave-full-screen'))
this.window.on('enter-full-screen', () => this.send('host:window-enter-full-screen'))
this.window.on('leave-full-screen', () => this.send('host:window-leave-full-screen'))
this.window.on('close', event => {
if (!this.closing) {
event.preventDefault()
this.window.webContents.send('host:window-close-request')
this.send('host:window-close-request')
return
}
this.windowConfig.set('windowBoundaries', this.windowBounds)
@@ -200,6 +208,10 @@ export class Window {
}
})
this.window.on('focus', () => {
this.send('host:window-focused')
})
ipcMain.on('window-focus', event => {
if (!this.window || event.sender !== this.window.webContents) {
return
@@ -287,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

@@ -28,27 +28,27 @@
"electron-updater": "^4.2.0",
"fontmanager-redux": "0.4.0",
"js-yaml": "3.13.1",
"keytar": "^5.0.0",
"keytar": "^5.2.0",
"mz": "^2.7.0",
"ngx-toastr": "^10.2.0",
"node-pty": "^0.10.0-beta2",
"npm": "6.9.0",
"path": "0.12.7",
"rxjs": "^6.5.3",
"rxjs-compat": "^6.5.3",
"yargs": "^15.0.2",
"rxjs": "^6.5.4",
"rxjs-compat": "^6.5.4",
"yargs": "^15.1.0",
"zone.js": "^0.8.29"
},
"optionalDependencies": {
"macos-native-processlist": "^1.0.2",
"windows-blurbehind": "^1.0.1",
"windows-native-registry": "^1.0.15",
"windows-native-registry": "^1.0.17",
"windows-process-tree": "^0.2.4",
"windows-swca": "^2.0.2"
},
"devDependencies": {
"@types/mz": "0.0.32",
"@types/node": "12.7.12",
"node-abi": "^2.12.0"
"node-abi": "^2.15.0"
}
}

View File

@@ -6,33 +6,3 @@ import '@fortawesome/fontawesome-free/css/brands.css'
import '@fortawesome/fontawesome-free/css/fontawesome.css'
import 'ngx-toastr/toastr.css'
import './preload.scss'
import * as Raven from 'raven-js'
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
Raven.config(
SENTRY_DSN,
{
release: require('electron').remote.app.getVersion(),
dataCallback: (data: any) => {
const normalize = (filename: string) => {
const splitArray = filename.split('/')
return splitArray[splitArray.length - 1]
}
data.exception.values[0].stacktrace.frames.forEach((frame: any) => {
frame.filename = normalize(frame.filename)
})
data.culprit = data.exception.values[0].stacktrace.frames[0].filename
return data
},
},
)
process.on('uncaughtException' as any, (err) => {
Raven.captureException(err as any)
console.error(err)
})

View File

@@ -7,7 +7,8 @@ import * as isDev from 'electron-is-dev'
import './global.scss'
import './toastr.scss'
import { enableProdMode, NgModuleRef } from '@angular/core'
import { enableProdMode, NgModuleRef, ApplicationRef } from '@angular/core'
import { enableDebugTools } from '@angular/platform-browser'
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
import { getRootModule } from './app.module'
@@ -37,7 +38,14 @@ async function bootstrap (plugins: PluginInfo[], safeMode = false): Promise<NgMo
})
const module = getRootModule(pluginsModules)
window['rootModule'] = module
return platformBrowserDynamic().bootstrapModule(module)
return platformBrowserDynamic().bootstrapModule(module).then(moduleRef => {
if (isDev) {
const applicationRef = moduleRef.injector.get(ApplicationRef)
const componentRef = applicationRef.components[0]
enableDebugTools(componentRef)
}
return moduleRef
})
}
findPlugins().then(async plugins => {

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

@@ -10,6 +10,10 @@
background-image: none;
width: auto;
&.toast-error {
background-color: #BD362F;
}
&.toast-info {
background-color: #555;
}

View File

@@ -6,6 +6,7 @@ module.exports = {
target: 'node',
entry: {
'index.ignore': 'file-loader?name=index.html!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
sentry: path.resolve(__dirname, 'lib/sentry.ts'),
preload: path.resolve(__dirname, 'src/entry.preload.ts'),
bundle: path.resolve(__dirname, 'src/entry.ts'),
},
@@ -78,5 +79,8 @@ module.exports = {
},
plugins: [
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.DefinePlugin({
'process.type': '"renderer"'
}),
],
}

View File

@@ -45,5 +45,8 @@ module.exports = {
},
plugins: [
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.DefinePlugin({
'process.type': '"main"',
}),
],
}

View File

@@ -1485,10 +1485,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.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.2.0.tgz#7543190be98e2a751466096ce3ca1b1a4b8f39fe"
integrity sha512-vsIX6n2BgTwzbKOSPIiJ8YduwHlPEE/G5dkmZWXaQK9qiGZMQyhxlFA4O6vrvM5fsXTMgUOrODYAqgpfNSRLDw==
dependencies:
nan "2.14.0"
prebuild-install "5.3.3"
@@ -1925,10 +1925,10 @@ ngx-toastr@^10.2.0:
dependencies:
tslib "^1.9.0"
node-abi@^2.12.0, node-abi@^2.7.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.12.0.tgz#40e9cfabdda1837863fa825e7dfa0b15686adf6f"
integrity sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw==
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"
@@ -2801,15 +2801,15 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
rxjs-compat@^6.5.3:
version "6.5.3"
resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.3.tgz#18440949b2678bf87a78a754009676b2c49183dc"
integrity sha512-BIJX2yovz3TBpjJoAZyls2QYuU6ZiCaZ+U96SmxQpuSP/qDUfiXPKOVLbThBB2WZijNHkdTTJXKRwvv5Y48H7g==
rxjs-compat@^6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.4.tgz#03825692af3fe363e04c43f41ff4113d76bbd305"
integrity sha512-rkn+lbOHUQOurdd74J/hjmDsG9nFx0z66fvnbs8M95nrtKvNqCKdk7iZqdY51CGmDemTQk+kUPy4s8HVOHtkfA==
rxjs@^6.5.3:
version "6.5.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
rxjs@^6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
dependencies:
tslib "^1.9.0"
@@ -3397,10 +3397,10 @@ windows-blurbehind@^1.0.1:
resolved "https://registry.yarnpkg.com/windows-blurbehind/-/windows-blurbehind-1.0.1.tgz#ff098713873304e38330b2c54cc41bb369b587b9"
integrity sha512-1HzHfCiM1ayrbACJu5qE9zELV24uX/tINT6kxaZwLY3rtQAoeav6x9z7LFHWoLaGDN/sYbnK+9Vk0cz7fsk5HQ==
windows-native-registry@^1.0.15:
version "1.0.15"
resolved "https://registry.yarnpkg.com/windows-native-registry/-/windows-native-registry-1.0.15.tgz#02593331fb7dcab99ef3ac9dd71f2c71ae57b189"
integrity sha512-uIsz1y3LrKPkphcZsezThz07FW7Vm00Zfa6ZU88rIo2zilOLE6Ui75jh6UkBAMso8xJeyvYbbcxF9kr4Zt8Iuw==
windows-native-registry@^1.0.17:
version "1.0.17"
resolved "https://registry.yarnpkg.com/windows-native-registry/-/windows-native-registry-1.0.17.tgz#d8cce48b364703a55c226690431b325114405022"
integrity sha512-u9Fp9TyDo5dvhlW6hYBOdHPETtAahXKxo3jeW5EXwNK7qa+nSNopQycN1drtBVWe3jpJXvyKpt9zrjiDd+u4JQ==
dependencies:
nan "^2.14.0"
@@ -3519,10 +3519,10 @@ yargs@^11.0.0:
y18n "^3.2.1"
yargs-parser "^9.0.2"
yargs@^15.0.2:
version "15.0.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3"
integrity sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==
yargs@^15.1.0:
version "15.1.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219"
integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==
dependencies:
cliui "^6.0.0"
decamelize "^1.2.0"

View File

@@ -1,4 +1,7 @@
#!/bin/bash
cat > '/usr/bin/${executable}' << END
#!/bin/sh
'/opt/${productFilename}/${executable}' --no-sandbox $@
END
# Link to the binary
ln -sf '/opt/${productFilename}/${executable}' '/usr/bin/${executable}'
chmod +x '/usr/bin/${executable}'

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

View File

@@ -1,30 +1,34 @@
{
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.11.2",
"@fortawesome/fontawesome-free": "^5.12.1",
"@sentry/cli": "^1.49.0",
"@sentry/electron": "^1.0.0",
"@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.14.1",
"@typescript-eslint/eslint-plugin": "^2.8.0",
"@typescript-eslint/parser": "^2.8.0",
"@types/webpack-env": "1.15.0",
"@typescript-eslint/eslint-plugin": "^2.13.0",
"@typescript-eslint/parser": "^2.19.2",
"apply-loader": "2.0.0",
"awesome-typescript-loader": "^5.0.0",
"core-js": "^3.4.2",
"cross-env": "6.0.3",
"css-loader": "3.2.0",
"electron": "^7.1.2",
"electron-builder": "22.1.0",
"electron-installer-snap": "^4.1.0",
"core-js": "^3.6.4",
"cross-env": "7.0.0",
"css-loader": "3.4.2",
"electron": "^8.0.0",
"electron-builder": "22.3.2",
"electron-download": "^4.1.1",
"electron-installer-snap": "^5.0.0",
"electron-notarize": "^0.1.1",
"electron-rebuild": "^1.8.5",
"eslint": "^6.7.1",
"file-loader": "^4.3.0",
"electron-rebuild": "^1.9.0",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.20.0",
"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-gyp": "^6.0.1",
"node-abi": "^2.15.0",
"node-gyp": "^6.1.0",
"node-sass": "^4.13.0",
"npmlog": "4.1.2",
"npx": "^10.2.0",
@@ -33,95 +37,25 @@
"pug-lint": "^2.6.0",
"pug-loader": "^2.4.0",
"pug-static-loader": "2.0.0",
"raven-js": "3.27.2",
"raw-loader": "3.1.0",
"raw-loader": "4.0.0",
"sass-loader": "^8.0.0",
"shelljs": "0.8.3",
"source-code-pro": "^2.30.2",
"source-sans-pro": "3.6.0",
"style-loader": "^1.0.0",
"style-loader": "^1.1.3",
"svg-inline-loader": "^0.8.0",
"to-string-loader": "1.1.6",
"tslib": "^1.10.0",
"typedoc": "^0.15.3",
"typescript": "^3.6.4",
"url-loader": "^2.3.0",
"val-loader": "2.0.1",
"webpack": "^5.0.0-beta.7",
"typedoc": "^0.16.7",
"typescript": "^3.7.5",
"url-loader": "^3.0.0",
"val-loader": "2.1.0",
"webpack": "^5.0.0-beta.12",
"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}"
},
"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",
@@ -130,11 +64,8 @@
"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",
"dependencies": {
"eslint-plugin-import": "^2.18.2"
}
"repository": "eugeny/terminus"
}

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

@@ -25,8 +25,5 @@ if (['darwin', 'linux'].includes(process.platform)) {
for (let x of vars.builtinPlugins) {
sh.ln('-fs', '../' + x, x)
}
for (let x of vars.bundledModules) {
sh.ln('-fs', '../app/node_modules/' + x, x)
}
sh.cd('..')
}

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-core",
"version": "1.0.93-nightly.0",
"version": "1.0.99-nightly.0",
"description": "Terminus core",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -1,4 +1,5 @@
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 { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider'
@@ -18,3 +19,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

@@ -38,7 +38,7 @@ title-bar(
button.btn.btn-secondary.btn-tab-bar(
[title]='button.title',
(click)='button.click && button.click()',
[innerHTML]='sanitizeIcon(button.icon)',
[fastHtmlBind]='button.icon',
ngbDropdownToggle,
)
div(*ngIf='button.submenu', ngbDropdownMenu)
@@ -47,8 +47,11 @@ title-bar(
(click)='item.click()',
ngbDropdownItem,
)
.icon-wrapper([innerHTML]='sanitizeIcon(item.icon)')
.ml-3 {{item.title}}
.icon-wrapper(
*ngIf='hasIcons(button.submenuItems)',
[fastHtmlBind]='item.icon'
)
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
@@ -61,7 +64,7 @@ title-bar(
button.btn.btn-secondary.btn-tab-bar(
[title]='button.title',
(click)='button.click && button.click()',
[innerHTML]='sanitizeIcon(button.icon)',
[fastHtmlBind]='button.icon',
ngbDropdownToggle,
)
div(*ngIf='button.submenu', ngbDropdownMenu)
@@ -70,14 +73,17 @@ title-bar(
(click)='item.click()',
ngbDropdownItem,
)
.icon-wrapper([innerHTML]='sanitizeIcon(item.icon)')
.ml-3 {{item.title}}
.icon-wrapper(
*ngIf='hasIcons(button.submenuItems)',
[fastHtmlBind]='item.icon'
)
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
button.btn.btn-secondary.btn-tab-bar.btn-update(
*ngIf='updatesAvailable',
title='Update available - Click to install',
(click)='updateApp()',
[innerHTML]='sanitizeIcon(updateIcon)'
[fastHtmlBind]='updateIcon'
)
window-controls.background(

View File

@@ -64,6 +64,7 @@ $tab-border-radius: 4px;
&>.drag-space {
min-width: 1px;
flex: 1 0 1%;
margin-top: 2px; // for window resizing
-webkit-app-region: drag;
&.persistent {

View File

@@ -1,6 +1,5 @@
import { Component, Inject, Input, HostListener, HostBinding } from '@angular/core'
import { trigger, style, animate, transition, state } from '@angular/animations'
import { DomSanitizer } from '@angular/platform-browser'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ElectronService } from '../services/electron.service'
@@ -75,7 +74,6 @@ export class AppRootComponent {
public hostApp: HostAppService,
public config: ConfigService,
public app: AppService,
private domSanitizer: DomSanitizer,
@Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[],
log: LogService,
ngbModal: NgbModal,
@@ -109,6 +107,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()
@@ -186,6 +190,7 @@ export class AppRootComponent {
if (this.config.store.appearance.dock === 'off') {
// not docked, visible
setTimeout(() => {
this.hostApp.getWindow().show()
this.hostApp.getWindow().focus()
})
} else {
@@ -250,8 +255,8 @@ export class AppRootComponent {
}
}
sanitizeIcon (icon: string): any {
return this.domSanitizer.bypassSecurityTrustHtml(icon || '')
hasIcons (submenuItems: ToolbarButton[]): boolean {
return submenuItems.some(x => !!x.icon)
}
private getToolbarButtons (aboveZero: boolean): ToolbarButton[] {

View File

@@ -38,7 +38,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

View File

@@ -1,4 +0,0 @@
.icon(tabindex='0', [class.active]='model', (keyup.space)='click()')
i.fas.fa-square.off
i.fas.fa-check-square.on
.text {{text}}

View File

@@ -1,55 +0,0 @@
:host {
cursor: pointer;
margin: 5px 0;
&:focus {
background: rgba(255,255,255,.05);
border-radius: 5px;
}
&:active {
background: rgba(255,255,255,.1);
border-radius: 3px;
}
&[disabled] {
opacity: 0.5;
}
display: flex;
flex-direction: row;
align-items: center;
.off {
color: rgba(0, 0, 0, .5);
}
.icon {
position: relative;
flex: none;
width: 14px;
height: 14px;
i {
position: absolute;
left: 0;
top: -2px;
transition: 0.25s opacity;
display: block;
font-size: 18px;
}
i.on, &.active i.off {
opacity: 0;
}
i.off, &.active i.on {
opacity: 1;
}
}
.text {
flex: auto;
margin-left: 8px;
}
}

View File

@@ -4,8 +4,12 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
/** @hidden */
@Component({
selector: 'checkbox',
template: require('./checkbox.component.pug'),
styles: [require('./checkbox.component.scss')],
template: `
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" [(ngModel)]='model'>
<label class="custom-control-label">{{text}}</label>
</div>
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: CheckboxComponent, multi: true },
],

View File

@@ -3,3 +3,24 @@
position: relative;
flex: auto;
}
::ng-deep split-tab > .child {
position: absolute;
transition: 0.125s all;
opacity: .75;
&.focused {
opacity: 1;
}
&.minimized {
opacity: .1;
}
&.maximized {
z-index: 2;
box-shadow: rgba(0, 0, 0, 0.25) 0px 0px 30px;
backdrop-filter: blur(10px);
border-radius: 10px;
}
}

View File

@@ -141,6 +141,8 @@ export interface SplitSpannerInfo {
styles: [require('./splitTab.component.scss')],
})
export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
static DIRECTIONS: SplitDirection[] = ['t', 'r', 'b', 'l']
/** @hidden */
@ViewChild('vc', { read: ViewContainerRef }) viewContainer: ViewContainerRef
@@ -156,6 +158,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
_spanners: SplitSpannerInfo[] = []
private focusedTab: BaseTabComponent
private maximizedTab: BaseTabComponent|null = null
private hotkeysSubscription: Subscription
private viewRefs: Map<BaseTabComponent, EmbeddedViewRef<any>> = new Map()
@@ -226,6 +229,13 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
case 'pane-nav-down':
this.navigate('b')
break
case 'pane-maximize':
if (this.maximizedTab) {
this.maximize(null)
} else if (this.getAllTabs().length > 1) {
this.maximize(this.focusedTab)
}
break
case 'close-pane':
this.removeTab(this.focusedTab)
break
@@ -261,6 +271,10 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
return this.focusedTab
}
getMaximizedTab (): BaseTabComponent|null {
return this.maximizedTab
}
focus (tab: BaseTabComponent) {
this.focusedTab = tab
for (const x of this.getAllTabs()) {
@@ -272,6 +286,15 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
tab.emitFocused()
this.focusChanged.next(tab)
}
if (this.maximizedTab !== tab) {
this.maximizedTab = null
}
this.layout()
}
maximize (tab: BaseTabComponent|null) {
this.maximizedTab = tab
this.layout()
}
@@ -436,6 +459,13 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
this.splitAdjusted.next(spanner)
}
destroy () {
super.destroy()
for (const x of this.getAllTabs()) {
x.destroy()
}
}
private attachTabView (tab: BaseTabComponent) {
const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any> // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
this.viewRefs.set(tab, ref)
@@ -486,13 +516,21 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
this.layoutInternal(child, childX, childY, childW, childH)
} else {
const element = this.viewRefs.get(child)!.rootNodes[0]
element.style.position = 'absolute'
element.classList.toggle('child', true)
element.classList.toggle('maximized', child === this.maximizedTab)
element.classList.toggle('minimized', this.maximizedTab && child !== this.maximizedTab)
element.classList.toggle('focused', child === this.focusedTab)
element.style.left = `${childX}%`
element.style.top = `${childY}%`
element.style.width = `${childW}%`
element.style.height = `${childH}%`
element.style.opacity = child === this.focusedTab ? 1 : 0.75
if (child === this.maximizedTab) {
element.style.left = '5%'
element.style.top = '5%'
element.style.width = '90%'
element.style.height = '90%'
}
}
offset += sizes[i]
@@ -526,6 +564,10 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
}
}
}
while (root.ratios.length < root.children.length) {
root.ratios.push(1)
}
root.normalize()
}
}

View File

@@ -16,13 +16,17 @@ export class SplitTabSpannerComponent {
@HostBinding('class.v') isVertical = true
@HostBinding('style.left') cssLeft: string
@HostBinding('style.top') cssTop: string
@HostBinding('style.width') cssWidth: string
@HostBinding('style.height') cssHeight: string
@HostBinding('style.width') cssWidth: string | null
@HostBinding('style.height') cssHeight: string | null
private marginOffset = -5
constructor (private element: ElementRef) { }
ngAfterViewInit () {
this.element.nativeElement.addEventListener('dblclick', () => {
this.reset()
})
this.element.nativeElement.addEventListener('mousedown', (e: MouseEvent) => {
this.isActive = true
const start = this.isVertical ? e.pageY : e.pageX
@@ -49,14 +53,16 @@ export class SplitTabSpannerComponent {
diff = Math.max(diff, -this.container.ratios[this.index - 1] + 0.1)
diff = Math.min(diff, this.container.ratios[this.index] - 0.1)
this.container.ratios[this.index - 1] += diff
this.container.ratios[this.index] -= diff
this.change.emit()
if (diff) {
this.container.ratios[this.index - 1] += diff
this.container.ratios[this.index] -= diff
this.change.emit()
}
}
document.addEventListener('mouseup', offHandler)
document.addEventListener('mouseup', offHandler, { passive: true })
this.element.nativeElement.parentElement.addEventListener('mousemove', dragHandler)
})
}, { passive: true })
}
ngOnChanges () {
@@ -79,10 +85,17 @@ export class SplitTabSpannerComponent {
}
}
reset () {
const ratio = (this.container.ratios[this.index - 1] + this.container.ratios[this.index]) / 2
this.container.ratios[this.index - 1] = ratio
this.container.ratios[this.index] = ratio
this.change.emit()
}
private setDimensions (x: number, y: number, w: number, h: number) {
this.cssLeft = `${x}%`
this.cssTop = `${y}%`
this.cssWidth = w ? `${w}%` : 'initial'
this.cssHeight = h ? `${h}%` : 'initial'
this.cssWidth = w ? `${w}%` : null
this.cssHeight = h ? `${h}%` : null
}
}

View File

@@ -20,7 +20,7 @@ $tabs-height: 38px;
cursor: -webkit-grab;
margin-left: 10px;
width: 20px;
width: 22px;
border-radius: 10px;
text-align: center;
transition: 0.25s all;
@@ -48,7 +48,7 @@ $tabs-height: 38px;
width: $button-size;
height: $button-size;
border-radius: $button-size / 2;
line-height: $button-size * 0.9;
line-height: $button-size;
align-self: center;
margin-right: 10px;

View File

@@ -16,55 +16,8 @@
padding-left: 10px;
margin-left: -10px;
&:focus {
background: rgba(255,255,255,.05);
border-radius: 5px;
}
&[disabled] {
opacity: 0.5;
}
.body {
$border-width: 2px;
border-radius: 5px;
border: $border-width solid rgba(255, 255, 255, .2);
padding: $padding;
height: $toggle-size + $border-width * 2 + $padding * 2;
width: $toggle-size * 2 + $border-width * 2 + $padding * 2;
position: relative;
.toggle {
position: absolute;
border-radius: 2px;
width: $toggle-size;
height: $toggle-size;
background: #475158;
top: $padding;
left: $padding;
transition: 0.25s left;
line-height: 19px;
text-align: center;
font-size: 10px;
i {
opacity: 0;
transition: 0.25s opacity;
}
}
}
&.active .body .toggle {
left: $toggle-size + $padding;
i {
color: white;
opacity: 1;
}
}
&:active {
background: rgba(255,255,255,.1);
}
}

View File

@@ -6,13 +6,10 @@ import { CheckboxComponent } from './checkbox.component'
@Component({
selector: 'toggle',
template: `
<div class="switch">
<div class="body">
<div class="toggle" [class.bg-primary]='model'>
<i class="fa fa-check"></i>
</div>
</div>
</div>
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" [(ngModel)]='model'>
<label class="custom-control-label"></label>
</div>
`,
styles: [require('./toggle.component.scss')],
providers: [

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:
@@ -50,5 +54,7 @@ hotkeys:
- 'Ctrl-Alt-Up'
pane-nav-left:
- 'Ctrl-Alt-Left'
pane-maximize:
- 'Ctrl-Alt-Enter'
close-pane: []
pluginBlacklist: ['ssh']

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:
@@ -48,6 +52,8 @@ hotkeys:
- '⌘-⌥-Up'
pane-nav-left:
- '⌘-⌥-Left'
pane-maximize:
- '⌘-⌥-Enter'
close-pane:
- '⌘-Shift-W'
pluginBlacklist: ['ssh']

View File

@@ -5,6 +5,7 @@ hotkeys:
- 'Ctrl+Space'
toggle-fullscreen:
- 'F11'
- 'Alt-Enter'
close-tab:
- 'Ctrl-Shift-W'
toggle-last-tab: []
@@ -16,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:
@@ -50,5 +55,7 @@ hotkeys:
- 'Ctrl-Alt-Up'
pane-nav-left:
- 'Ctrl-Alt-Left'
pane-maximize:
- 'Ctrl-Alt-Enter'
close-pane: []
pluginBlacklist: []

View File

@@ -8,7 +8,7 @@ appearance:
frame: thin
css: '/* * { color: blue !important; } */'
opacity: 1.0
vibrancy: false
vibrancy: true
vibrancyType: 'blur'
enableAnalytics: true
enableWelcomeTab: true

View File

@@ -0,0 +1,14 @@
import { Directive, Input, ElementRef, OnChanges } from '@angular/core'
/** @hidden */
@Directive({
selector: '[fastHtmlBind]',
})
export class FastHtmlBindDirective implements OnChanges {
@Input() fastHtmlBind: string
constructor (private el: ElementRef) { }
ngOnChanges () {
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',
@@ -93,6 +101,10 @@ export class AppHotkeyProvider extends HotkeyProvider {
id: 'split-top',
name: 'Split to the top',
},
{
id: 'pane-maximize',
name: 'Maximize the active pane',
},
{
id: 'pane-nav-up',
name: 'Focus the pane above',

View File

@@ -21,6 +21,7 @@ import { SplitTabSpannerComponent } from './components/splitTabSpanner.component
import { WelcomeTabComponent } from './components/welcomeTab.component'
import { AutofocusDirective } from './directives/autofocus.directive'
import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive'
import { HotkeyProvider } from './api/hotkeyProvider'
import { ConfigProvider } from './api/configProvider'
@@ -80,6 +81,7 @@ const PROVIDERS = [
RenameTabModalComponent,
SafeModeModalComponent,
AutofocusDirective,
FastHtmlBindDirective,
SplitTabComponent,
SplitTabSpannerComponent,
WelcomeTabComponent,

View File

@@ -83,6 +83,10 @@ export class AppService {
this.startTabStorage()
}
}
hostApp.windowFocused$.subscribe(() => {
this._activeTab?.emitFocused()
})
}
startTabStorage () {
@@ -94,8 +98,13 @@ export class AppService {
}, 30000)
}
addTabRaw (tab: BaseTabComponent) {
this.tabs.push(tab)
addTabRaw (tab: BaseTabComponent, index: number|null = null) {
if (index !== null) {
this.tabs.splice(index, 0, tab)
} else {
this.tabs.push(tab)
}
this.selectTab(tab)
this.tabsChanged.next()
this.tabOpened.next(tab)
@@ -121,6 +130,11 @@ export class AppService {
this.tabsChanged.next()
this.tabClosed.next(tab)
})
if (tab instanceof SplitTabComponent) {
tab.tabAdded$.subscribe(() => this.emitTabsChanged())
tab.tabRemoved$.subscribe(() => this.emitTabsChanged())
}
}
/**
@@ -169,6 +183,17 @@ export class AppService {
}
}
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
for (const topLevelTab of this.tabs) {
if (topLevelTab instanceof SplitTabComponent) {
if (topLevelTab.getAllTabs().includes(tab)) {
return topLevelTab
}
}
}
return null
}
/** Switches between the current tab and the previously active one */
toggleLastTab () {
if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) {
@@ -199,6 +224,35 @@ export class AppService {
}
}
moveSelectedTabLeft () {
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 () {
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) {
const i1 = this.tabs.indexOf(a)
const i2 = this.tabs.indexOf(b)
this.tabs[i1] = b
this.tabs[i2] = a
}
/** @hidden */
emitTabsChanged () {
this.tabsChanged.next()
@@ -217,7 +271,7 @@ export class AppService {
async duplicateTab (tab: BaseTabComponent) {
const dup = await this.tabsService.duplicate(tab)
if (dup) {
this.addTabRaw(dup)
this.addTabRaw(dup, this.tabs.indexOf(tab) + 1)
}
}

View File

@@ -125,7 +125,22 @@ export class ConfigService {
}
getDefaults () {
return this.defaults
const cleanup = o => {
if (o instanceof Array) {
return o.map(cleanup)
} else if (o instanceof Object) {
const r = {}
for (const k of Object.keys(o)) {
if (k !== '__nonStructural') {
r[k] = cleanup(o[k])
}
}
return r
} else {
return o
}
}
return cleanup(this.defaults)
}
load (): void {

View File

@@ -30,9 +30,14 @@ export class HomeBaseService {
let body = `Version: ${this.appVersion}\n`
body += `Platform: ${os.platform()} ${os.release()}\n`
const label = {
aix: 'OS: IBM AIX',
android: 'OS: Android',
darwin: 'OS: macOS',
windows: 'OS: Windows',
freebsd: 'OS: FreeBSD',
linux: 'OS: Linux',
openbsd: 'OS: OpenBSD',
sunos: 'OS: Solaris',
win32: 'OS: Windows',
}[os.platform()]
const plugins = (window as any).installedPlugins.filter(x => !x.isBuiltin).map(x => x.name)
body += `Plugins: ${plugins.join(', ') || 'none'}\n\n`

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,
@@ -39,6 +40,7 @@ export class HostAppService {
private configChangeBroadcast = new Subject<void>()
private windowCloseRequest = new Subject<void>()
private windowMoved = new Subject<void>()
private windowFocused = new Subject<void>()
private displayMetricsChanged = new Subject<void>()
private logger: Logger
private windowId: number
@@ -85,6 +87,8 @@ export class HostAppService {
get windowMoved$ (): Observable<void> { return this.windowMoved }
get windowFocused$ (): Observable<void> { return this.windowFocused }
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
private constructor (
@@ -128,6 +132,10 @@ export class HostAppService {
this.zone.run(() => this.windowMoved.next())
})
electron.ipcRenderer.on('host:window-focused', () => {
this.zone.run(() => this.windowFocused.next())
})
electron.ipcRenderer.on('host:display-metrics-changed', () => {
this.zone.run(() => this.displayMetricsChanged.next())
})
@@ -157,6 +165,14 @@ 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)
}
}
/**
@@ -212,14 +228,12 @@ export class HostAppService {
*
* @param type `null`, or `fluent` when supported (Windowd only)
*/
setVibrancy (enable: boolean, type: string) {
setVibrancy (enable: boolean, type: string|null) {
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) {

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))
}
/**
@@ -71,7 +84,7 @@ export class HotkeysService {
const matched = this.getCurrentFullyMatchedHotkey()
if (matched) {
console.log('Matched hotkey', matched)
this.matchedHotkey.emit(matched)
this._hotkey.next(matched)
this.clearCurrentKeystrokes()
}
})

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' })
@@ -18,11 +18,18 @@ export class ShellIntegrationService {
private automatorWorkflowsDestination: string
private registryKeys = [
{
path: 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
path: 'Software\\Classes\\Directory\\Background\\shell\\Terminus',
value: 'Open Terminus here',
command: 'open "%V"',
},
{
path: 'Software\\Classes\\*\\shell\\Paste path into Terminus',
path: 'SOFTWARE\\Classes\\Directory\\shell\\Terminus',
value: 'Open Terminus here',
command: 'open "%V"',
},
{
path: 'Software\\Classes\\*\\shell\\Terminus',
value: 'Paste path into Terminus',
command: 'paste "%V"',
},
]
@@ -61,9 +68,17 @@ export class ShellIntegrationService {
for (const registryKey of this.registryKeys) {
wnr.createRegistryKey(wnr.HK.CU, registryKey.path)
wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command')
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, '', wnr.REG.SZ, registryKey.value)
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, exe)
wnr.setRegistryValue(wnr.HK.CU, registryKey.path + '\\command', '', wnr.REG.SZ, exe + ' ' + registryKey.command)
}
if(wnr.getRegistryKey(wnr.HK.CU, 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here')) {
wnr.deleteRegistryKey(wnr.HK.CU, 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here')
}
if(wnr.getRegistryKey(wnr.HK.CU, 'Software\\Classes\\*\\shell\\Paste path into Terminus')) {
wnr.deleteRegistryKey(wnr.HK.CU, 'Software\\Classes\\*\\shell\\Paste path into Terminus')
}
}
}

View File

@@ -21,7 +21,18 @@ export class TabRecoveryService {
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) {
r.tabColor = tab.color
}
return r
})
}
return token
})
.filter(token => !!token)
)
)
@@ -31,7 +42,9 @@ export class TabRecoveryService {
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

@@ -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,21 +19,27 @@ 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')
if (process.platform === 'linux') {
this.electronUpdaterAvailable = false
return
}
this.autoUpdater = electron.remote.require('electron-updater').autoUpdater
this.autoUpdater.autoInstallOnAppQuit = !!config.store.enableAutomaticUpdates
this.autoUpdater.on('update-available', () => {
this.logger.info('Update available')
this.autoUpdater.downloadUpdate()
})
this.autoUpdater.once('update-not-available', () => {
this.logger.info('No updates')
@@ -42,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) {
@@ -55,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)

View File

@@ -1,4 +1,5 @@
import { Injectable, NgZone } from '@angular/core'
import { Subscription } from 'rxjs'
import { AppService } from './services/app.service'
import { BaseTabComponent } from './components/baseTab.component'
import { TabHeaderComponent } from './components/tabHeader.component'
@@ -16,39 +17,49 @@ export class CloseContextMenu extends TabContextMenuItemProvider {
super()
}
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
return [
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> {
let items = [
{
label: 'Close',
click: () => this.zone.run(() => {
this.app.closeTab(tab, true)
}),
},
{
label: 'Close other tabs',
click: () => this.zone.run(() => {
for (const t of this.app.tabs.filter(x => x !== tab)) {
this.app.closeTab(t, true)
}
}),
},
{
label: 'Close tabs to the right',
click: () => this.zone.run(() => {
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
this.app.closeTab(t, true)
}
}),
},
{
label: 'Close tabs to the left',
click: () => this.zone.run(() => {
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
this.app.closeTab(t, true)
if (this.app.tabs.includes(tab)) {
this.app.closeTab(tab, true)
} else {
tab.destroy()
}
}),
},
]
if (tabHeader) {
items = [
...items,
{
label: 'Close other tabs',
click: () => this.zone.run(() => {
for (const t of this.app.tabs.filter(x => x !== tab)) {
this.app.closeTab(t, true)
}
}),
},
{
label: 'Close tabs to the right',
click: () => this.zone.run(() => {
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
this.app.closeTab(t, true)
}
}),
},
{
label: 'Close tabs to the left',
click: () => this.zone.run(() => {
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
this.app.closeTab(t, true)
}
}),
},
]
}
return items
}
}
@@ -75,28 +86,31 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
}
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> {
return [
{
label: 'Rename',
click: () => this.zone.run(() => tabHeader && tabHeader.showRenameTabModal()),
},
{
label: 'Duplicate',
click: () => this.zone.run(() => this.app.duplicateTab(tab)),
},
{
label: 'Color',
sublabel: COLORS.find(x => x.value === tab.color)!.name,
submenu: COLORS.map(color => ({
label: color.name,
type: 'radio',
checked: tab.color === color.value,
click: () => this.zone.run(() => {
tab.color = color.value
}),
})) as Electron.MenuItemConstructorOptions[],
},
]
if (tabHeader) {
return [
{
label: 'Rename',
click: () => this.zone.run(() => tabHeader?.showRenameTabModal()),
},
{
label: 'Duplicate',
click: () => this.zone.run(() => this.app.duplicateTab(tab)),
},
{
label: 'Color',
sublabel: COLORS.find(x => x.value === tab.color)!.name,
submenu: COLORS.map(color => ({
label: color.name,
type: 'radio',
checked: tab.color === color.value,
click: () => this.zone.run(() => {
tab.color = color.value
}),
})) as Electron.MenuItemConstructorOptions[],
},
]
}
return []
}
}
@@ -112,36 +126,61 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
const process = await tab.getCurrentProcess()
if (process) {
return [
{
id: 'process-name',
enabled: false,
label: 'Current process: ' + process.name,
},
{
label: 'Notify when done',
type: 'checkbox',
checked: (tab as any).__completionNotificationEnabled,
click: () => this.zone.run(() => {
(tab as any).__completionNotificationEnabled = !(tab as any).__completionNotificationEnabled
let items: Electron.MenuItemConstructorOptions[] = []
if ((tab as any).__completionNotificationEnabled) {
this.app.observeTabCompletion(tab).subscribe(() => {
new Notification('Process completed', {
body: process.name,
}).addEventListener('click', () => {
this.app.selectTab(tab)
})
;(tab as any).__completionNotificationEnabled = false
const extTab: (BaseTabComponent & { __completionNotificationEnabled?: boolean, __outputNotificationSubscription?: Subscription|null }) = tab
if (process) {
items.push({
id: 'process-name',
enabled: false,
label: 'Current process: ' + process.name,
})
items.push({
label: 'Notify when done',
type: 'checkbox',
checked: extTab.__completionNotificationEnabled,
click: () => this.zone.run(() => {
extTab.__completionNotificationEnabled = !extTab.__completionNotificationEnabled
if (extTab.__completionNotificationEnabled) {
this.app.observeTabCompletion(tab).subscribe(() => {
new Notification('Process completed', {
body: process.name,
}).addEventListener('click', () => {
this.app.selectTab(tab)
})
} else {
this.app.stopObservingTabCompletion(tab)
}
}),
},
]
extTab.__completionNotificationEnabled = false
})
} else {
this.app.stopObservingTabCompletion(tab)
}
}),
})
}
return []
items.push({
label: 'Notify on activity',
type: 'checkbox',
checked: !!extTab.__outputNotificationSubscription,
click: () => this.zone.run(() => {
if (extTab.__outputNotificationSubscription) {
extTab.__outputNotificationSubscription.unsubscribe()
extTab.__outputNotificationSubscription = null
} else {
extTab.__outputNotificationSubscription = tab.activity$.subscribe(active => {
if (extTab.__outputNotificationSubscription && active) {
extTab.__outputNotificationSubscription.unsubscribe()
extTab.__outputNotificationSubscription = null
new Notification('Tab activity', {
body: tab.title,
}).addEventListener('click', () => {
this.app.selectTab(tab)
})
}
})
}
}),
})
return items
}
}

View File

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

View File

@@ -1,103 +1,11 @@
$tab-border-radius: 5px;
@import "./theme.vars";
// ---------
$button-hover-bg: rgba(0, 0, 0, .25);
$button-active-bg: rgba(0, 0, 0, .5);
$white: #fff !default;
$black: #000 !default;
$red: #d9534f !default;
$orange: #f0ad4e !default;
$yellow: #ffd500 !default;
$green: #5cb85c !default;
$blue: #0275d8 !default;
$teal: #5bc0de !default;
$pink: #ff5b77 !default;
$purple: #613d7c !default;
$theme-colors: (
"primary": $blue,
"secondary": #394b5d
);
$content-bg: rgba(39, 49, 60, 0.65); //#1D272D;
$content-bg-solid: #1D272D;
$body-bg: #131d27;
$body-bg2: #20333e;
$body-color: #ccc;
$font-family-sans-serif: "Source Sans Pro";
$font-family-monospace: "Source Code Pro";
$font-size-base: 14rem / 16;
$btn-border-radius: 0;
$btn-secondary-color: #ccc;
$btn-secondary-bg: #222;
$btn-secondary-border: #444;
//$btn-warning-bg: rgba($orange, .5);
$nav-tabs-border-width: 0;
$nav-tabs-border-radius: 0;
$nav-tabs-link-hover-border-color: $body-bg;
$nav-tabs-active-link-hover-color: $white;
$nav-tabs-active-link-hover-bg: $blue;
$nav-tabs-active-link-hover-border-color: darken($blue, 30%);
$nav-pills-border-radius: 0;
$input-bg: #111;
$input-disabled-bg: #333;
$input-color: $body-color;
$input-color-placeholder: #333;
$input-border-color: #344;
$input-border-width: 1px;
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
$input-border-radius: 0;
$custom-select-border-radius: 0;
$input-bg-focus: $input-bg;
$input-border-focus: lighten($blue, 25%);
$input-focus-box-shadow: none;
$input-color-focus: $input-color;
$input-group-addon-bg: $body-bg;
$input-group-addon-border-color: $input-border-color;
$modal-content-bg: $content-bg-solid;
$modal-content-border-color: $body-bg;
$modal-header-border-color: transparent;
$modal-footer-border-color: transparent;
$popover-bg: $body-bg;
$dropdown-bg: $body-bg;
$dropdown-link-color: $body-color;
$dropdown-link-hover-color: white;
$dropdown-link-hover-bg: $body-bg2;
//$dropdown-link-active-color: $component-active-color;
//$dropdown-link-active-bg: $component-active-bg;
$dropdown-link-disabled-color: #333;
$dropdown-header-color: #333;
$list-group-color: $body-color;
$list-group-bg: rgba(255,255,255,.05);
$list-group-border-color: rgba(255,255,255,.1);
$list-group-hover-bg: rgba(255,255,255,.1);
$list-group-link-active-bg: rgba(255,255,255,.2);
$list-group-action-color: $body-color;
$list-group-action-bg: rgba(255,255,255,.05);
$list-group-action-active-bg: $list-group-link-active-bg;
$pre-bg: $dropdown-bg;
$pre-color: $dropdown-link-color;
$alert-danger-bg: $body-bg;
$alert-danger-text: $red;
$alert-danger-border: $red;
$headings-font-weight: lighter;
$headings-color: #eee;
@import '~bootstrap/scss/bootstrap.scss';
window-controls {
@@ -236,13 +144,14 @@ settings-tab > ngb-tabset {
border: none;
padding: 10px 50px 10px 20px;
font-size: 14px;
border-radius: 0;
&:not(.active) {
color: $body-color;
color: $body-color;
&:hover {
color: $white;
}
&:hover {
color: $white;
}
}
}
}
@@ -310,14 +219,6 @@ hotkey-input-modal {
margin-bottom: 2px;
}
.nav-tabs {
background: $btn-secondary-bg;
.nav-link {
transition: 0.25s all;
border-bottom-color: $nav-tabs-border-color;
}
}
ngb-tabset .tab-content {
padding-top: 20px;
}
@@ -361,22 +262,10 @@ ngb-tabset .tab-content {
}
}
select.form-control {
-webkit-appearance: none;
background-image: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 24 24'><path fill='#444' d='M7.406 7.828l4.594 4.594 4.594-4.594 1.406 1.406-6 6-6-6z'></path></svg>");
background-position: 100% 50%;
background-repeat: no-repeat;
padding-right: 30px;
}
checkbox i.on {
color: $blue;
}
toggle.active .body .toggle {
background: $blue;
}
.modal .modal-footer {
background: rgba(0, 0, 0, .25);
@@ -405,3 +294,101 @@ toggle.active .body .toggle {
*::-webkit-resizer {
opacity: 0;
}
search-panel {
background: rgba(39, 49, 60, 0.65) !important;
}
.btn {
cursor: pointer;
justify-content: flex-start;
overflow: hidden;
&.disabled,
&:disabled {
cursor: not-allowed;
}
}
.btn.btn-outline-secondary {
@include button-outline-variant(#9badb9, #fff);
&:hover:not([disabled]), &:active:not([disabled]), &.active:not([disabled]) {
background-color: #3f484e;
border-color: darken(#9badb9, 25%);
}
border-color: darken(#9badb9, 25%);
&.disabled,
&:disabled {
color: #9badb9;
}
}
.btn-warning:not(:disabled):not(.disabled) {
&.active, &:active {
color: $gray-900;
}
}
.btn-secondary:not(:disabled):not(.disabled) {
&.active, &:active {
background: #191e23;
}
}
.btn-link {
&:hover, &[aria-expanded=true], &:active, &.active {
color: $link-hover-color;
border-radius: $btn-border-radius;
}
&[aria-expanded=true], &:active, &.active {
background: rgba(255, 255, 255, 0.1);
}
}
.btn-group .btn.active {
border-color: transparent !important;
}
.nav-tabs {
margin-bottom: 10px;
&.nav-justified .nav-link {
margin-right: 5px;
}
.nav-link {
border: none;
border-bottom: $nav-tabs-border-width solid transparent;
text-transform: uppercase;
font-weight: bold;
padding: 5px 0;
margin-right: 20px;
uib-tab-heading > i {
font-size: 18px;
}
@include hover-focus {
color: $nav-tabs-link-active-color;
}
&.disabled {
color: $nav-link-disabled-color;
border-color: transparent;
}
}
.nav-item:last-child .nav-link {
margin-right: 0;
}
.nav-link.active,
.nav-item.show .nav-link {
color: $nav-tabs-link-active-color;
border-color: $nav-tabs-link-active-border-color;
}
}

View File

@@ -0,0 +1,187 @@
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$black: #000;
$red: #d9534f !default;
$orange: #f0ad4e !default;
$yellow: #ffd500 !default;
$green: #5cb85c !default;
$blue: #0275d8 !default;
$teal: #5bc0de !default;
$pink: #ff5b77 !default;
$purple: #613d7c !default;
@import "~bootstrap/scss/functions";
$content-bg: rgba(39, 49, 60, 0.65); //#1D272D;
$content-bg-solid: #1D272D;
$table-bg: rgba(255,255,255,.05);
$table-bg-hover: rgba(255,255,255,.1);
$table-border-color: rgba(255,255,255,.1);
$theme-colors: (
primary: $blue,
secondary: #38434e,
success: $green,
info: $blue,
warning: $orange,
danger: $red,
light: $gray-300,
dark: $gray-800,
rare: $purple
);
$body-color: #ccc;
$body-bg: #131d27;
$body-bg2: #20333e;
$font-family-sans-serif: "Source Sans Pro";
$font-family-monospace: "Source Code Pro";
$font-size-base: 14rem / 16;
$font-size-lg: 1.28rem;
$font-size-sm: .85rem;
$line-height-base: 1.6;
$headings-color: #ced9e2;
$headings-font-weight: lighter;
$input-btn-padding-y: .3rem;
$input-btn-padding-x: .9rem;
$input-btn-line-height: 1.6;
$input-btn-line-height-sm: 1.8;
$input-btn-line-height-lg: 1.8;
$btn-link-disabled-color: $gray-600;
$btn-focus-box-shadow: none;
$h4-font-size: 18px;
$link-color: $gray-400;
$link-hover-color: $white;
$link-hover-decoration: none;
$component-active-color: $white;
$component-active-bg: #2f3a42;
$list-group-bg: $table-bg;
$list-group-border-color: $table-border-color;
$list-group-item-padding-y: 0.8rem;
$list-group-item-padding-x: 1rem;
$list-group-hover-bg: $table-bg-hover;
$list-group-active-bg: rgba(255,255,255,.2);
$list-group-active-color: $component-active-color;
$list-group-active-border-color: translate;
$list-group-action-color: $body-color;
$list-group-action-hover-color: white;
$list-group-action-active-color: $component-active-color;
$list-group-action-active-bg: $list-group-active-bg;
$alert-padding-y: 0.9rem;
$alert-padding-x: 1.25rem;
$input-box-shadow: none;
$transition-base: all .15s ease-in-out;
$transition-fade: opacity .1s linear;
$transition-collapse: height .35s ease;
$btn-transition: all .15s ease-in-out;
$popover-bg: $body-bg;
$popover-body-color: $body-color;
$popover-header-bg: $table-bg-hover;
$popover-header-color: $headings-color;
$popover-arrow-color: $popover-bg;
$popover-max-width: 360px;
$btn-border-width: 2px;
$input-bg: #181e23;
$input-disabled-bg: #2e3235;
$input-color: #ddd;
$input-border-color: $input-bg;
$input-border-width: 2px;
$input-focus-bg: $input-bg;
$input-focus-border-color: rgba(171, 171, 171, 0.61);
$input-focus-color: $input-color;
$input-btn-focus-color: var(--focus-color);
$input-btn-focus-box-shadow: 0 0 0 2px $input-btn-focus-color;
$input-group-addon-color: $input-color;
$input-group-addon-bg: $input-bg;
$input-group-addon-border-color: transparent;
$input-group-btn-border-color: $input-bg;
$nav-tabs-border-radius: 0;
$nav-tabs-border-color: transparent;
$nav-tabs-border-width: 2px;
$nav-tabs-link-hover-border-color: transparent;
$nav-tabs-link-active-color: #eee;
$nav-tabs-link-active-bg: transparent;
$nav-tabs-link-active-border-color: #eee;
$navbar-padding-y: 0;
$navbar-padding-x: 0;
$dropdown-bg: $content-bg-solid;
$dropdown-color: $body-color;
$dropdown-border-width: 1px;
$dropdown-box-shadow: 0 .5rem 1rem rgba($black,.175);
$dropdown-header-color: $gray-500;
$dropdown-link-color: $body-color;
$dropdown-link-hover-color: #eee;
$dropdown-link-hover-bg: rgba(255,255,255,.04);
$dropdown-link-active-color: white;
$dropdown-link-active-bg: rgba(0, 0, 0, .2);
$dropdown-item-padding-y: 0.5rem;
$dropdown-item-padding-x: 1.5rem;
$code-color: $orange;
$code-bg: rgba(0, 0, 0, .25);
$code-padding-y: 3px;
$code-padding-x: 5px;
$pre-bg: $dropdown-bg;
$pre-color: $dropdown-link-color;
$badge-font-size: 0.75rem;
$badge-font-weight: bold;
$badge-padding-y: 4px;
$badge-padding-x: 6px;
$custom-control-indicator-size: 1.2rem;
$custom-control-indicator-bg: $body-bg;
$custom-control-indicator-border-color: lighten($body-bg, 25%);
$custom-control-indicator-checked-bg: theme-color("primary");
$custom-control-indicator-checked-color: $body-bg;
$custom-control-indicator-checked-border-color: transparent;
$custom-control-indicator-active-bg: rgba(255, 255, 0, 0.5);
$modal-content-bg: $content-bg-solid;
$modal-content-border-color: $body-bg;
$modal-header-border-width: 0;
$modal-footer-border-color: #222;
$modal-footer-border-width: 1px;
$modal-content-border-width: 0;

View File

@@ -3,6 +3,8 @@ 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

View File

@@ -46,17 +46,16 @@ async@^2.6.1:
lodash "^4.17.11"
axios@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
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"
is-buffer "^2.0.2"
bootstrap@^4.1.3:
version "4.3.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac"
integrity sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==
version "4.4.1"
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"
@@ -118,9 +117,9 @@ colorspace@1.1.x:
text-hex "1.0.x"
core-js@^3.1.2:
version "3.4.2"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.2.tgz#ee2b1a60b50388d8ddcda8cdb44a92c7a9ea76df"
integrity sha512-bUTfqFWtNKWp73oNIfRkqwYZJeNT3lstzZcAkhhiuvDraRSgOH1/+F9ZklbpR4zpdKuo4cpXN8tKP7s61yjX+g==
version "3.6.4"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647"
integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==
core-util-is@~1.0.0:
version "1.0.2"
@@ -254,11 +253,6 @@ is-arrayish@^0.3.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-buffer@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@@ -466,9 +460,9 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
uuid@^3.3.2:
version "3.3.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
winston-transport@^4.3.0:
version "4.3.0"

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-plugin-manager",
"version": "1.0.93-nightly.0",
"version": "1.0.99-nightly.0",
"description": "Terminus' plugin manager",
"keywords": [
"terminus-builtin-plugin"
@@ -20,7 +20,7 @@
"@types/semver": "^6.0.0",
"axios": "^0.19.0",
"mz": "^2.6.0",
"semver": "^6.1.0"
"semver": "^7.1.1"
},
"peerDependencies": {
"@angular/common": "^7",

View File

@@ -5,7 +5,7 @@
.d-flex
h3.mb-1 Installed
button.btn.btn-outline-info.btn-sm.ml-auto((click)='openPluginsFolder()')
button.btn.btn-outline-secondary.btn-sm.ml-auto((click)='openPluginsFolder()')
i.fas.fa-folder
span Plugins folder
@@ -28,19 +28,19 @@
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
span Upgrade ({{knownUpgrades[plugin.name].version}})
button.btn.btn-primary.ml-2(
button.btn.btn-link.text-primary.ml-2(
*ngIf='config.store.pluginBlacklist.includes(plugin.name)',
(click)='enablePlugin(plugin)'
)
i.fas.fa-fw.fa-play
button.btn.btn-secondary.ml-2(
button.btn.btn-link.ml-2(
*ngIf='!config.store.pluginBlacklist.includes(plugin.name)',
(click)='disablePlugin(plugin)'
)
i.fas.fa-fw.fa-pause
button.btn.btn-danger.ml-2(
button.btn.btn-link.text-danger.ml-2(
(click)='uninstallPlugin(plugin)',
*ngIf='!plugin.isBuiltin',
[disabled]='busy[plugin.name] != undefined'

View File

@@ -8,6 +8,10 @@ const NAME_PREFIX = 'terminus-'
const KEYWORD = 'terminus-plugin'
const OFFICIAL_NPM_ACCOUNT = 'eugenepankov'
const BLACKLIST = [
'terminus-shell-selector', // superseded by profiles
]
export interface PluginInfo {
name: string
description: string
@@ -75,6 +79,7 @@ export class PluginManagerService {
isOfficial: item.package.publisher.username === OFFICIAL_NPM_ACCOUNT,
}))),
map(plugins => plugins.filter(x => x.packageName.startsWith(NAME_PREFIX))),
map(plugins => plugins.filter(x => !BLACKLIST.includes(x.packageName))),
)
}

View File

@@ -13,12 +13,11 @@ any-promise@^1.0.0:
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
axios@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
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"
is-buffer "^2.0.2"
debug@=3.1.0:
version "3.1.0"
@@ -34,11 +33,6 @@ follow-redirects@1.5.10:
dependencies:
debug "=3.1.0"
is-buffer@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -58,10 +52,10 @@ object-assign@^4.0.1:
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
semver@^6.1.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.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.1.tgz#29104598a197d6cbe4733eeecbe968f7b43a9667"
integrity sha512-WfuG+fl6eh3eZ2qAf6goB7nhiCd7NPXhmyFxigB/TOkQyeLP8w8GsVehvtGNtnNmyboz4TgeK40B1Kbql/8c5A==
thenify-all@^1.0.0:
version "1.6.0"

View File

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

View File

@@ -1,5 +1,4 @@
import * as yaml from 'js-yaml'
import * as os from 'os'
import { Subscription } from 'rxjs'
import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core'
import {
@@ -14,6 +13,8 @@ import {
Platform,
HomeBaseService,
ShellIntegrationService,
isWindowsBuild,
WIN_BUILD_FLUENT_BG_SUPPORTED,
} from 'terminus-core'
import { SettingsTabProvider } from '../api'
@@ -81,9 +82,7 @@ export class SettingsTabComponent extends BaseTabComponent {
this.hotkeyDescriptions = descriptions
})
this.isFluentVibrancySupported = hostApp.platform === Platform.Windows
&& parseFloat(os.release()) >= 10
&& parseInt(os.release().split('.')[2]) >= 17063
this.isFluentVibrancySupported = isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)
}
async ngOnInit () {
@@ -99,10 +98,6 @@ export class SettingsTabComponent extends BaseTabComponent {
this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled()
}
async getRecoveryToken (): Promise<any> {
return null
}
ngOnDestroy () {
this.configSubscription.unsubscribe()
this.config.save()

View File

@@ -3,7 +3,7 @@ import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import TerminusCorePlugin, { ToolbarButtonProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider } from 'terminus-core'
import TerminusCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider } from 'terminus-core'
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
@@ -11,7 +11,6 @@ import { SettingsTabComponent } from './components/settingsTab.component'
import { SettingsTabBodyComponent } from './components/settingsTabBody.component'
import { ButtonProvider } from './buttonProvider'
import { RecoveryProvider } from './recoveryProvider'
import { SettingsHotkeyProvider } from './hotkeys'
import { SettingsConfigProvider } from './config'
@@ -25,7 +24,6 @@ import { SettingsConfigProvider } from './config'
],
providers: [
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
{ provide: ConfigProvider, useClass: SettingsConfigProvider, multi: true },
{ provide: HotkeyProvider, useClass: SettingsHotkeyProvider, multi: true },
],

View File

@@ -1,15 +0,0 @@
import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from 'terminus-core'
import { SettingsTabComponent } from './components/settingsTab.component'
/** @hidden */
@Injectable()
export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> {
if (recoveryToken && recoveryToken.type === 'app:settings') {
return { type: SettingsTabComponent }
}
return null
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-ssh",
"version": "1.0.93-nightly.0",
"version": "1.0.99-nightly.0",
"description": "SSH connection manager for Terminus",
"keywords": [
"terminus-builtin-plugin"
@@ -19,8 +19,12 @@
"devDependencies": {
"@types/node": "12.7.3",
"@types/ssh2": "^0.5.35",
"ansi-colors": "^4.1.1",
"cli-spinner": "^0.2.10",
"ssh2": "^0.8.2",
"ssh2-streams": "^0.4.2"
"ssh2-streams": "^0.4.2",
"sshpk": "^1.16.1",
"terminus-terminal": "^1.0.98-nightly.0"
},
"peerDependencies": {
"@angular/common": "^7",

View File

@@ -1,4 +1,9 @@
import colors from 'ansi-colors'
import { BaseSession } from 'terminus-terminal'
import { Server, Socket, createServer, createConnection } from 'net'
import { Client, ClientChannel } from 'ssh2'
import { Logger } from 'terminus-core'
import { Subject, Observable } from 'rxjs'
export interface LoginScript {
expect: string
@@ -21,30 +26,88 @@ export interface SSHConnection {
user: string
password?: string
privateKey?: string
group?: string
group: string | null
scripts?: LoginScript[]
keepaliveInterval?: number
keepaliveCountMax?: number
readyTimeout?: number
color?: string
x11?: boolean
skipBanner?: boolean
algorithms?: {[t: string]: string[]}
}
export enum PortForwardType {
Local, Remote
}
export class ForwardedPort {
type: PortForwardType
host = '127.0.0.1'
port: number
targetAddress: string
targetPort: number
private listener: Server
async startLocalListener (callback: (Socket) => void): Promise<void> {
this.listener = createServer(callback)
return new Promise((resolve, reject) => {
this.listener.listen(this.port, '127.0.0.1')
this.listener.on('error', reject)
this.listener.on('listening', resolve)
})
}
stopLocalListener () {
this.listener.close()
}
toString () {
if (this.type === PortForwardType.Local) {
return `(local) ${this.host}:${this.port} → (remote) ${this.targetAddress}:${this.targetPort}`
} else {
return `(remote) ${this.host}:${this.port} → (local) ${this.targetAddress}:${this.targetPort}`
}
}
}
export class SSHSession extends BaseSession {
scripts?: LoginScript[]
shell: any
shell: ClientChannel
ssh: Client
forwardedPorts: ForwardedPort[] = []
logger: Logger
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
private serviceMessage = new Subject<string>()
constructor (public connection: SSHConnection) {
super()
this.scripts = connection.scripts || []
}
start () {
async start () {
this.open = true
try {
this.shell = await this.openShellChannel({ x11: this.connection.x11 })
} catch (err) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected opening a shell channel: ${err}`)
}
this.shell.on('greeting', greeting => {
this.emitServiceMessage(`Shell greeting: ${greeting}`)
})
this.shell.on('banner', banner => {
this.emitServiceMessage(`Shell banner: ${banner}`)
})
this.shell.on('data', data => {
const dataString = data.toString()
this.emitOutput(dataString)
this.emitOutput(data)
if (this.scripts) {
let found = false
@@ -67,12 +130,12 @@ export class SSHSession extends BaseSession {
}
if (match) {
console.log('Executing script: "' + cmd + '"')
this.logger.info('Executing script: "' + cmd + '"')
this.shell.write(cmd + '\n')
this.scripts = this.scripts.filter(x => x !== script)
} else {
if (script.optional) {
console.log('Skip optional script: ' + script.expect)
this.logger.debug('Skip optional script: ' + script.expect)
found = true
this.scripts = this.scripts.filter(x => x !== script)
} else {
@@ -88,17 +151,140 @@ export class SSHSession extends BaseSession {
})
this.shell.on('end', () => {
this.logger.info('Shell session ended')
if (this.open) {
this.destroy()
}
})
this.ssh.on('tcp connection', (details, accept, reject) => {
this.logger.info(`Incoming forwarded connection: (remote) ${details.srcIP}:${details.srcPort} -> (local) ${details.destIP}:${details.destPort}`)
const forward = this.forwardedPorts.find(x => x.port === details.destPort)
if (!forward) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Rejected incoming forwarded connection for unrecognized port ${details.destPort}`)
return reject()
}
const socket = new Socket()
socket.connect(forward.targetPort, forward.targetAddress)
socket.on('error', e => {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not forward the remote connection to ${forward.targetAddress}:${forward.targetPort}: ${e}`)
reject()
})
socket.on('connect', () => {
this.logger.info('Connection forwarded')
const stream = accept()
stream.pipe(socket)
socket.pipe(stream)
stream.on('close', () => {
socket.destroy()
})
socket.on('close', () => {
stream.close()
})
})
})
this.ssh.on('x11', (details, accept, reject) => {
this.logger.info(`Incoming X11 connection from ${details.srcIP}:${details.srcPort}`)
let displaySpec = process.env.DISPLAY || ':0'
this.logger.debug(`Trying display ${displaySpec}`)
let xHost = displaySpec.split(':')[0]
let xDisplay = parseInt(displaySpec.split(':')[1].split('.')[0] || '0')
let xPort = xDisplay < 100 ? xDisplay + 6000 : xDisplay
const socket = displaySpec.startsWith('/') ? createConnection(displaySpec) : new Socket()
if (!displaySpec.startsWith('/')) {
socket.connect(xPort, xHost)
}
socket.on('error', e => {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server ${xHost}:${xPort}: ${e}`)
reject()
})
socket.on('connect', () => {
this.logger.info('Connection forwarded')
const stream = accept()
stream.pipe(socket)
socket.pipe(stream)
stream.on('close', () => {
socket.destroy()
})
socket.on('close', () => {
stream.close()
})
})
})
this.executeUnconditionalScripts()
}
emitServiceMessage (msg: string) {
this.serviceMessage.next(msg)
this.logger.info(msg)
}
async addPortForward (fw: ForwardedPort) {
if (fw.type === PortForwardType.Local) {
await fw.startLocalListener((socket: Socket) => {
this.logger.info(`New connection on ${fw}`)
this.ssh.forwardOut(
socket.remoteAddress || '127.0.0.1',
socket.remotePort || 0,
fw.targetAddress,
fw.targetPort,
(err, stream) => {
if (err) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote has rejected the forwaded connection via ${fw}: ${err}`)
socket.destroy()
return
}
stream.pipe(socket)
socket.pipe(stream)
stream.on('close', () => {
socket.destroy()
})
socket.on('close', () => {
stream.close()
})
}
)
}).then(() => {
this.emitServiceMessage(colors.bgGreen.black(' -> ') + ` Forwaded ${fw}`)
this.forwardedPorts.push(fw)
}).catch(e => {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Failed to forward port ${fw}: ${e}`)
throw e
})
}
if (fw.type === PortForwardType.Remote) {
await new Promise((resolve, reject) => {
this.ssh.forwardIn(fw.host, fw.port, err => {
if (err) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected port forwarding for ${fw}: ${err}`)
return reject(err)
}
resolve()
})
})
this.emitServiceMessage(colors.bgGreen.black(' <- ') + ` Forwaded ${fw}`)
this.forwardedPorts.push(fw)
}
}
async removePortForward (fw: ForwardedPort) {
if (fw.type === PortForwardType.Local) {
fw.stopLocalListener()
this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw)
}
if (fw.type === PortForwardType.Remote) {
this.ssh.unforwardIn(fw.host, fw.port)
this.forwardedPorts = this.forwardedPorts.filter(x => x !== fw)
}
this.emitServiceMessage(`Stopped forwarding ${fw}`)
}
resize (columns, rows) {
if (this.shell) {
this.shell.setWindow(rows, columns)
this.shell.setWindow(rows, columns, rows, columns)
}
}
@@ -114,6 +300,11 @@ export class SSHSession extends BaseSession {
}
}
async destroy (): Promise<void> {
this.serviceMessage.complete()
await super.destroy()
}
async getChildProcesses (): Promise<any[]> {
return []
}
@@ -126,6 +317,18 @@ export class SSHSession extends BaseSession {
return null
}
private openShellChannel (options): Promise<ClientChannel> {
return new Promise<ClientChannel>((resolve, reject) => {
this.ssh.shell({ term: 'xterm-256color' }, options, (err, shell) => {
if (err) {
reject(err)
} else {
resolve(shell)
}
})
})
}
private executeUnconditionalScripts () {
if (this.scripts) {
for (const script of this.scripts) {

View File

@@ -1,118 +1,152 @@
.modal-body
ngb-tabset(type='pills', [activeId]='basic')
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',
type='text',
autofocus,
[(ngModel)]='connection.name',
)
.form-group
label Group
input.form-control(
type='text',
type='text',
placeholder='Ungrouped',
[(ngModel)]='connection.group',
[(ngModel)]='connection.group',
)
.form-group
label Host
input.form-control(
type='text',
[(ngModel)]='connection.host',
type='text',
[(ngModel)]='connection.host',
)
.form-group
label Port
input.form-control(
type='number',
placeholder='22',
[(ngModel)]='connection.port',
placeholder='22',
[(ngModel)]='connection.port',
)
.form-group
label Username
input.form-control(
type='text',
[(ngModel)]='connection.user',
type='text',
[(ngModel)]='connection.user',
)
.form-line
.header
.title Password
.description(*ngIf='!hasSavedPassword') Save a password in the keychain
.description(*ngIf='hasSavedPassword') There is a saved password for this connection
button.btn.btn-outline-success.ml-4(*ngIf='!hasSavedPassword', (click)='setPassword()')
i.fas.fa-key
button.btn.btn-outline-success.ml-4(*ngIf='!hasSavedPassword', (click)='setPassword()')
i.fas.fa-key
span Set password
button.btn.btn-danger.ml-4(*ngIf='hasSavedPassword', (click)='clearSavedPassword()')
button.btn.btn-danger.ml-4(*ngIf='hasSavedPassword', (click)='clearSavedPassword()')
i.fas.fa-trash-alt
span Forget
.form-line
.header
.title Private key
.title Private key
.description Path to the private key file
.input-group
input.form-control(
type='text',
placeholder='Key file path',
type='text',
placeholder='Key file path',
[(ngModel)]='connection.privateKey'
)
.input-group-btn
.input-group-append
button.btn.btn-secondary((click)='selectPrivateKey()')
i.fas.fa-folder-open
ngb-tab(id='advanced')
ng-template(ngbTabTitle) Advanced
ng-template(ngbTabContent)
.form-group
label Keep Alive Interval (Milliseconds)
.form-line
.header
.title X11 forwarding
toggle([(ngModel)]='connection.x11')
.form-line
.header
.title Tab color
input.form-control(
type='number',
placeholder='0',
[(ngModel)]='connection.keepaliveInterval',
type='text',
autofocus,
[(ngModel)]='connection.color',
placeholder='#000000'
)
.form-group
label Max Keep Alive Count
.form-line
.header
.title Skip MoTD/banner
toggle([(ngModel)]='connection.skipBanner')
.form-line
.header
.title Keep Alive Interval (Milliseconds)
input.form-control(
type='number',
placeholder='3',
[(ngModel)]='connection.keepaliveCountMax',
type='number',
placeholder='0',
[(ngModel)]='connection.keepaliveInterval',
)
.form-group
label Ready Timeout (Milliseconds)
.form-line
.header
.title Max Keep Alive Count
input.form-control(
type='number',
placeholder='20000',
[(ngModel)]='connection.readyTimeout',
type='number',
placeholder='3',
[(ngModel)]='connection.keepaliveCountMax',
)
.form-group
label Ciphers
div(*ngFor='let alg of supportedAlgorithms.cipher')
checkbox([text]='alg', [(ngModel)]='algorithms.cipher[alg]')
.form-group
label Key exchange
div(*ngFor='let alg of supportedAlgorithms.kex')
checkbox([text]='alg', [(ngModel)]='algorithms.kex[alg]')
.form-line
.header
.title Ready Timeout (Milliseconds)
input.form-control(
type='number',
placeholder='20000',
[(ngModel)]='connection.readyTimeout',
)
.form-group
label HMAC
div(*ngFor='let alg of supportedAlgorithms.hmac')
checkbox([text]='alg', [(ngModel)]='algorithms.hmac[alg]')
ngb-tab(id='ciphers')
ng-template(ngbTabTitle) Ciphers
ng-template(ngbTabContent)
.form-line.align-items-start
.header
.title Ciphers
.w-50
div(*ngFor='let alg of supportedAlgorithms.cipher')
checkbox([text]='alg', [(ngModel)]='algorithms.cipher[alg]')
.form-group
label Host key
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
.form-line.align-items-start
.header
.title Key exchange
.w-50
div(*ngFor='let alg of supportedAlgorithms.kex')
checkbox([text]='alg', [(ngModel)]='algorithms.kex[alg]')
.form-line.align-items-start
.header
.title HMAC
.w-50
div(*ngFor='let alg of supportedAlgorithms.hmac')
checkbox([text]='alg', [(ngModel)]='algorithms.hmac[alg]')
.form-line.align-items-start
.header
.title Host key
.w-50
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
ngb-tab(id='scripts')
@@ -128,12 +162,12 @@
tr(*ngFor='let script of connection.scripts')
td.pr-2
input.form-control(
type='text',
type='text',
[(ngModel)]='script.expect'
)
td
input.form-control(
type='text',
type='text',
[(ngModel)]='script.send'
)
td.pl-2
@@ -152,11 +186,11 @@
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

@@ -66,7 +66,7 @@ export class EditConnectionModalComponent {
modal.componentInstance.password = true
try {
const result = await modal.result
if (result && result.value) {
if (result?.value) {
this.passwordStorage.savePassword(this.connection, result.value)
this.hasSavedPassword = true
}
@@ -82,10 +82,11 @@ export class EditConnectionModalComponent {
this.electron.dialog.showOpenDialog(
this.hostApp.getWindow(),
{
defaultPath: this.connection.privateKey,
title: 'Select private key',
}
).then(result => {
if (result.filePaths) {
if (!result.canceled) {
this.connection.privateKey = result.filePaths[0]
}
})

View File

@@ -49,6 +49,7 @@ export class SSHModalComponent {
const connection: SSHConnection = {
name: this.quickTarget,
group: null,
host,
user,
port,
@@ -91,7 +92,7 @@ export class SSHModalComponent {
}
for (const connection of connections) {
connection.group = connection.group || undefined
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
group = {

View File

@@ -0,0 +1,48 @@
.modal-header
h5.m-0 Port forwarding
.modal-body.pt-0
.list-group-light.mb-3
.list-group-item.d-flex.align-items-center(*ngFor='let fw of session.forwardedPorts')
strong(*ngIf='fw.type === PortForwardType.Local') Local
strong(*ngIf='fw.type === PortForwardType.Remote') Remote
.ml-3 {{fw.host}}:{{fw.port}} &rarr; {{fw.targetAddress}}:{{fw.targetPort}}
button.btn.btn-link.ml-auto((click)='remove(fw)')
i.fas.fa-trash-alt.mr-2
span Remove
.input-group.mb-2
input.form-control(type='text', [(ngModel)]='newForward.host')
.input-group-append
.input-group-text :
input.form-control(type='number', [(ngModel)]='newForward.port')
.input-group-append
.input-group-text &rarr;
input.form-control(type='text', [(ngModel)]='newForward.targetAddress')
.input-group-append
.input-group-text :
input.form-control(type='number', [(ngModel)]='newForward.targetPort')
.d-flex
.btn-group.mr-auto(
[(ngModel)]='newForward.type',
ngbRadioGroup
)
label.btn.btn-secondary.m-0(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='PortForwardType.Local'
)
| Local
label.btn.btn-secondary.m-0(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='PortForwardType.Remote'
)
| Remote
button.btn.btn-primary((click)='addForward()')
i.fas.fa-check.mr-2
span Forward port

View File

@@ -0,0 +1,42 @@
import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ForwardedPort, PortForwardType, SSHSession } from '../api'
/** @hidden */
@Component({
template: require('./sshPortForwardingModal.component.pug'),
// styles: [require('./sshPortForwardingModal.component.scss')],
})
export class SSHPortForwardingModalComponent {
@Input() session: SSHSession
newForward = new ForwardedPort()
PortForwardType = PortForwardType
constructor (
public modalInstance: NgbActiveModal,
) {
this.reset()
}
reset () {
this.newForward = new ForwardedPort()
this.newForward.type = PortForwardType.Local
this.newForward.host = '127.0.0.1'
this.newForward.port = 8000
this.newForward.targetAddress = '127.0.0.1'
this.newForward.targetPort = 80
}
async addForward () {
try {
await this.session.addPortForward(this.newForward)
this.reset()
} catch (e) {
console.error(e)
}
}
remove (fw: ForwardedPort) {
this.session.removePortForward(fw)
}
}

View File

@@ -1,6 +1,7 @@
import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, ElectronService, HostAppService } from 'terminus-core'
import { PasswordStorageService } from '../services/passwordStorage.service'
import { SSHConnection, SSHConnectionGroup } from '../api'
import { EditConnectionModalComponent } from './editConnectionModal.component'
import { PromptModalComponent } from './promptModal.component'
@@ -19,6 +20,7 @@ export class SSHSettingsTabComponent {
private electron: ElectronService,
private hostApp: HostAppService,
private ngbModal: NgbModal,
private passwordStorage: PasswordStorageService,
) {
this.connections = this.config.store.ssh.connections
this.refresh()
@@ -27,6 +29,7 @@ export class SSHSettingsTabComponent {
createConnection () {
const connection: SSHConnection = {
name: '',
group: null,
host: '',
port: 22,
user: 'root',
@@ -64,6 +67,7 @@ export class SSHSettingsTabComponent {
}
)).response === 1) {
this.connections = this.connections.filter(x => x !== connection)
this.passwordStorage.deletePassword(connection)
this.config.store.ssh.connections = this.connections
this.config.save()
this.refresh()
@@ -97,7 +101,7 @@ export class SSHSettingsTabComponent {
}
)).response === 1) {
for (const connection of this.connections.filter(x => x.group === group.name)) {
connection.group = undefined
connection.group = null
}
this.config.save()
this.refresh()
@@ -109,7 +113,7 @@ export class SSHSettingsTabComponent {
this.childGroups = []
for (const connection of this.connections) {
connection.group = connection.group || undefined
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
group = {

View File

@@ -0,0 +1,15 @@
.ssh-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.mr-auto(*ngIf='session') {{session.connection.user}}@{{session.connection.host}}:{{session.connection.port}}
button.btn.btn-secondary((click)='showPortForwarding()', *ngIf='session.open')
i.fas.fa-plug
span Ports
button.btn.btn-info((click)='reconnect()', *ngIf='!session.open')
i.fas.fa-reload
span Reconnect

View File

@@ -3,6 +3,7 @@
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
&> .content {
flex: auto;
@@ -11,4 +12,60 @@
overflow: hidden;
margin: 15px;
}
.ssh-tab-toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 4;
pointer-events: none;
.reveal-button {
position: absolute;
top: 10px;
right: 30px;
border-radius: 50%;
width: 35px;
padding: 0;
height: 35px;
line-height: 35px;
transition: 0.125s opacity;
opacity: .5;
pointer-events: all;
}
&:hover .reveal-button {
opacity: 0;
}
&:hover .toolbar {
opacity: 1;
}
.toolbar {
opacity: 0;
background: rgba(0, 0, 0, .75);
padding: 10px 20px;
transition: 0.25s opacity;
display: flex;
align-items: center;
z-index: 1;
will-change: transform;
&>* {
pointer-events: all;
}
}
&.show {
.reveal-button {
opacity: 0;
}
.toolbar {
opacity: 1;
}
}
}
}

View File

@@ -1,12 +1,17 @@
import colors from 'ansi-colors'
import { Spinner } from 'cli-spinner'
import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { first } from 'rxjs/operators'
import { BaseTerminalTabComponent } from 'terminus-terminal'
import { SSHService } from '../services/ssh.service'
import { SSHConnection, SSHSession } from '../api'
import { SSHPortForwardingModalComponent } from './sshPortForwardingModal.component'
/** @hidden */
@Component({
template: BaseTerminalTabComponent.template,
selector: 'ssh-tab',
template: BaseTerminalTabComponent.template + require<string>('./sshTab.component.pug'),
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
animations: BaseTerminalTabComponent.animations,
})
@@ -14,8 +19,11 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
connection: SSHConnection
ssh: SSHService
session: SSHSession
private ngbModal: NgbModal
ngOnInit () {
this.ngbModal = this.injector.get<NgbModal>(NgbModal)
this.logger = this.log.create('terminalTab')
this.ssh = this.injector.get(SSHService)
this.frontendReady$.pipe(first()).subscribe(() => {
@@ -35,30 +43,53 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
return
}
this.session = new SSHSession(this.connection)
this.session = this.ssh.createSession(this.connection)
this.session.serviceMessage$.subscribe(msg => {
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ' ' + msg + '\r\n')
this.session.resize(this.size.columns, this.size.rows)
})
this.attachSessionHandlers()
this.write(`Connecting to ${this.connection.host}`)
const interval = setInterval(() => this.write('.'), 500)
const spinner = new Spinner({
text: 'Connecting',
stream: {
write: x => this.write(x),
},
})
spinner.setSpinnerString(6)
spinner.start()
try {
await this.ssh.connectSession(this.session, (message: string) => {
this.write('\r\n' + message)
spinner.stop(true)
this.write(message + '\r\n')
spinner.start()
})
spinner.stop(true)
} catch (e) {
this.write('\r\n')
this.write(e.message)
spinner.stop(true)
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
return
} finally {
clearInterval(interval)
this.write('\r\n')
}
await this.session.start()
this.session.resize(this.size.columns, this.size.rows)
this.session.start()
}
async getRecoveryToken (): Promise<any> {
return {
type: 'app:ssh-tab',
connection: this.connection,
savedState: this.frontend?.saveState(),
}
}
showPortForwarding () {
const modal = this.ngbModal.open(SSHPortForwardingModalComponent).componentInstance as SSHPortForwardingModalComponent
modal.session = this.session
}
reconnect () {
this.initializeSession()
}
}

View File

@@ -9,6 +9,7 @@ import TerminusTerminalModule from 'terminus-terminal'
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
import { SSHModalComponent } from './components/sshModal.component'
import { SSHPortForwardingModalComponent } from './components/sshPortForwardingModal.component'
import { PromptModalComponent } from './components/promptModal.component'
import { SSHSettingsTabComponent } from './components/sshSettingsTab.component'
import { SSHTabComponent } from './components/sshTab.component'
@@ -40,6 +41,7 @@ import { SSHHotkeyProvider } from './hotkeys'
EditConnectionModalComponent,
PromptModalComponent,
SSHModalComponent,
SSHPortForwardingModalComponent,
SSHSettingsTabComponent,
SSHTabComponent,
],
@@ -47,6 +49,7 @@ import { SSHHotkeyProvider } from './hotkeys'
EditConnectionModalComponent,
PromptModalComponent,
SSHModalComponent,
SSHPortForwardingModalComponent,
SSHSettingsTabComponent,
SSHTabComponent,
],

View File

@@ -10,7 +10,10 @@ export class RecoveryProvider extends TabRecoveryProvider {
if (recoveryToken && recoveryToken.type === 'app:ssh-tab') {
return {
type: SSHTabComponent,
options: { connection: recoveryToken.connection },
options: {
connection: recoveryToken.connection,
savedState: recoveryToken.savedState,
},
}
}
return null

View File

@@ -1,8 +1,10 @@
import colors from 'ansi-colors'
import { Injectable, NgZone } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Client } from 'ssh2'
import * as fs from 'mz/fs'
import * as path from 'path'
import * as sshpk from 'sshpk'
import { ToastrService } from 'ngx-toastr'
import { AppService, HostAppService, Platform, Logger, LogService } from 'terminus-core'
import { SSHConnection, SSHSession } from '../api'
@@ -12,7 +14,7 @@ import { PasswordStorageService } from './passwordStorage.service'
import { SSH2Stream } from 'ssh2-streams'
try {
var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires
var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
} catch { }
@Injectable({ providedIn: 'root' })
@@ -20,7 +22,7 @@ export class SSHService {
private logger: Logger
private constructor (
log: LogService,
private log: LogService,
private app: AppService,
private zone: NgZone,
private ngbModal: NgbModal,
@@ -32,15 +34,24 @@ export class SSHService {
}
async openTab (connection: SSHConnection): Promise<SSHTabComponent> {
return this.zone.run(() => this.app.openNewTab(
const tab = this.zone.run(() => this.app.openNewTab(
SSHTabComponent,
{ connection }
) as SSHTabComponent)
if (connection.color) {
(this.app.getParentTab(tab) || tab).color = connection.color
}
return tab
}
createSession (connection: SSHConnection): SSHSession {
const session = new SSHSession(connection)
session.logger = this.log.create(`ssh-${connection.host}-${connection.port}`)
return session
}
async connectSession (session: SSHSession, logCallback?: (s: any) => void): Promise<void> {
let privateKey: string|null = null
let privateKeyPassphrase: string|null = null
let privateKeyPath = session.connection.privateKey
if (!logCallback) {
@@ -55,42 +66,51 @@ export class SSHService {
if (!privateKeyPath) {
const userKeyPath = path.join(process.env.HOME as string, '.ssh', 'id_rsa')
if (await fs.exists(userKeyPath)) {
log(`Using user's default private key: ${userKeyPath}`)
log('Using user\'s default private key')
privateKeyPath = userKeyPath
}
}
if (privateKeyPath) {
log('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' '))
try {
privateKey = (await fs.readFile(privateKeyPath)).toString()
} catch (error) {
log('Could not read the private key file')
log(colors.bgRed.black(' X ') + 'Could not read the private key file')
this.toastr.error('Could not read the private key file')
}
if (privateKey) {
log(`Loading private key from ${privateKeyPath}`)
let parsedKey: any = null
try {
parsedKey = sshpk.parsePrivateKey(privateKey, 'auto')
} catch (e) {
if (e instanceof sshpk.KeyEncryptedError) {
const modal = this.ngbModal.open(PromptModalComponent)
log(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase')
modal.componentInstance.prompt = 'Private key passphrase'
modal.componentInstance.password = true
let passphrase = ''
try {
const result = await modal.result
passphrase = result?.value
} catch (e) { }
parsedKey = sshpk.parsePrivateKey(
privateKey,
'auto',
{ passphrase: passphrase }
)
} else {
throw e
}
}
let encrypted = privateKey.includes('ENCRYPTED')
if (privateKeyPath.toLowerCase().endsWith('.ppk')) {
encrypted = encrypted || privateKey.includes('Encryption:') && !privateKey.includes('Encryption: none')
}
if (encrypted) {
const modal = this.ngbModal.open(PromptModalComponent)
log('Key requires passphrase')
modal.componentInstance.prompt = 'Private key passphrase'
modal.componentInstance.password = true
try {
const result = await modal.result
if (result) {
privateKeyPassphrase = result.value
}
} catch (e) { }
}
privateKey = parsedKey!.toString('pem')
}
}
const ssh = new Client()
session.ssh = ssh
let connected = false
let savedPassword: string|null = null
await new Promise(async (resolve, reject) => {
@@ -114,7 +134,7 @@ export class SSHService {
})
})
ssh.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => this.zone.run(async () => {
log(`Keyboard-interactive auth requested: ${name}`)
log(colors.bgBlackBright(' ') + ` Keyboard-interactive auth requested: ${name}`)
this.logger.info('Keyboard-interactive auth:', name, instructions, instructionsLang)
const results: string[] = []
for (const prompt of prompts) {
@@ -128,11 +148,15 @@ export class SSHService {
}))
ssh.on('greeting', greeting => {
log('Greeting: ' + greeting)
if (!session.connection.skipBanner) {
log('Greeting: ' + greeting)
}
})
ssh.on('banner', banner => {
log('Banner: \n' + banner)
if (!session.connection.skipBanner) {
log(banner)
}
})
let agent: string|null = null
@@ -156,7 +180,6 @@ export class SSHService {
username: session.connection.user,
password: session.connection.privateKey ? undefined : '',
privateKey: privateKey || undefined,
passphrase: privateKeyPassphrase || undefined,
tryKeyboard: true,
agent: agent || undefined,
agentForward: !!agent,
@@ -164,7 +187,8 @@ export class SSHService {
keepaliveCountMax: session.connection.keepaliveCountMax,
readyTimeout: session.connection.readyTimeout,
hostVerifier: digest => {
log('SHA256 fingerprint: ' + digest)
log(colors.bgWhite(' ') + ' Host key fingerprint:')
log(colors.bgWhite(' ') + ' ' + colors.black.bgWhite(' SHA256 ') + colors.bgBlackBright(' ' + digest + ' '))
return true
},
hostHash: 'sha256' as any,
@@ -210,31 +234,6 @@ export class SSHService {
}
})
})
try {
const shell: any = await new Promise<any>((resolve, reject) => {
ssh.shell({ term: 'xterm-256color' }, (err, shell) => {
if (err) {
reject(err)
} else {
resolve(shell)
}
})
})
session.shell = shell
shell.on('greeting', greeting => {
log(`Shell Greeting: ${greeting}`)
})
shell.on('banner', banner => {
log(`Shell Banner: ${banner}`)
})
} catch (error) {
this.toastr.error(error.message)
throw error
}
}
}

View File

@@ -20,54 +20,116 @@
"@types/node" "*"
"@types/ssh2@^0.5.35":
version "0.5.39"
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.39.tgz#e39ab7e38fc01337f66237ed6c42237ef3e58e3b"
integrity sha512-MtX4tr6Jtdn/JPVsQytjB/NBeOd7JfCyf/l79KOdkUYL+r4GXUXcySX1n8W4O61fnQdljTBXEPJJ2dhnGhi2xg==
version "0.5.40"
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.40.tgz#b65465897f40c67e66e630b1f059f13a1ea7f1fa"
integrity sha512-Yrs2vFIirdscR+xY4leiUosHTClRbVBiFLlm5gA0JMZMjbCulHKO3qcgMqATElrquiZal5sSHoXMk4t8DzDawA==
dependencies:
"@types/node" "*"
"@types/ssh2-streams" "*"
asn1@~0.2.0:
ansi-colors@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
asn1@~0.2.0, asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
safer-buffer "~2.1.0"
bcrypt-pbkdf@^1.0.2:
assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
safer-buffer@~2.1.0:
cli-spinner@^0.2.10:
version "0.2.10"
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
integrity sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
dependencies:
assert-plus "^1.0.0"
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
dependencies:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
dependencies:
assert-plus "^1.0.0"
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
ssh2-streams@^0.4.2, ssh2-streams@~0.4.7:
version "0.4.7"
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.7.tgz#093b89069de9cf5f06feff0601a5301471b01611"
integrity sha512-JhF8BNfeguOqVHOLhXjzLlRKlUP8roAEhiT/y+NcBQCqpRUupLNrRf2M+549OPNVGx21KgKktug4P3MY/IvTig==
ssh2-streams@^0.4.2, ssh2-streams@~0.4.8:
version "0.4.8"
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.8.tgz#2ff92df2e0063fef86cf934eaea197967deda715"
integrity sha512-auxXfgYySz2vYw7TMU7PK7vFI7EPvhvTH8/tZPgGaWocK4p/vwCMiV3icz9AEkb0R40kOKZtFtqYIxDJyJiytw==
dependencies:
asn1 "~0.2.0"
bcrypt-pbkdf "^1.0.2"
streamsearch "~0.1.2"
ssh2@^0.8.2:
version "0.8.6"
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.6.tgz#dcc62e1d3b9e58a21f711f5186f043e4e792e6da"
integrity sha512-T0cPmEtmtC8WxSupicFDjx3vVUdNXO8xu2a/D5bjt8ixOUCe387AgvxU3mJgEHpu7+Sq1ZYx4d3P2pl/yxMH+w==
version "0.8.7"
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.7.tgz#2dc15206f493010b98027201cf399b90bab79c89"
integrity sha512-/u1BO12kb0lDVxJXejWB9pxyF3/ncgRqI9vPCZuPzo05pdNDzqUeQRavScwSPsfMGK+5H/VRqp1IierIx0Bcxw==
dependencies:
ssh2-streams "~0.4.7"
ssh2-streams "~0.4.8"
sshpk@^1.16.1:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
bcrypt-pbkdf "^1.0.0"
dashdash "^1.12.0"
ecc-jsbn "~0.1.1"
getpass "^0.1.1"
jsbn "~0.1.0"
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
streamsearch@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
tweetnacl@^0.14.3:
terminus-terminal@^1.0.98-nightly.0:
version "1.0.98-nightly.0"
resolved "https://registry.yarnpkg.com/terminus-terminal/-/terminus-terminal-1.0.98-nightly.0.tgz#10df71b0a81adf76a076fb21a91c859dd2f8bef7"
integrity sha512-JLxkeoQkORcfe6cRW6BJF5ZPSbvKA8IWUAb7fzBONVmNfRKj2Mq/uYPy76UXsdmb9F1n+rYIg+DShNp57asMKA==
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-terminal",
"version": "1.0.93-nightly.0",
"version": "1.0.99-nightly.0",
"description": "Terminus' terminal emulation core",
"keywords": [
"terminus-builtin-plugin"
@@ -19,19 +19,23 @@
"devDependencies": {
"@types/deep-equal": "^1.0.0",
"@types/slug": "^0.9.1",
"ansi-colors": "^4.1.1",
"dataurl": "0.1.0",
"deep-equal": "1.1.0",
"hterm-umdjs": "1.4.1",
"mz": "^2.6.0",
"ps-node": "^0.1.6",
"runes": "^0.4.2",
"slug": "^1.1.0",
"slug": "^2.0.0",
"uuid": "^3.3.2",
"xterm": "3.15.0-beta98",
"xterm-addon-fit": "^0.4.0-beta1",
"xterm-addon-ligatures": "^0.2.0",
"xterm-addon-search": "^0.4.0-beta3",
"xterm-addon-webgl": "^0.4.0-beta1"
"xterm": "^4.4.0-beta.15",
"xterm-addon-fit": "^0.4.0-beta2",
"xterm-addon-ligatures": "^0.2.1",
"xterm-addon-search": "^0.5.0",
"xterm-addon-serialize": "^0.1.1",
"xterm-addon-unicode11": "^0.1.1",
"xterm-addon-webgl": "^0.6.0-beta.2",
"zmodem.js": "^0.1.9"
},
"peerDependencies": {
"@angular/animations": "^7",

View File

@@ -1,9 +1,10 @@
import { Observable, Subject, Subscription } from 'rxjs'
import { first } from 'rxjs/operators'
import { ToastrService } from 'ngx-toastr'
import colors from 'ansi-colors'
import { NgZone, OnInit, OnDestroy, Inject, Injector, Optional, ViewChild, HostBinding, Input, ElementRef } from '@angular/core'
import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger } from 'terminus-core'
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger, TabContextMenuItemProvider } from 'terminus-core'
import { BaseSession, SessionsService } from '../services/sessions.service'
import { TerminalFrontendService } from '../services/terminalFrontend.service'
@@ -11,7 +12,6 @@ import { TerminalFrontendService } from '../services/terminalFrontend.service'
import { Frontend } from '../frontends/frontend'
import { ResizeEvent } from './interfaces'
import { TerminalDecorator } from './decorator'
import { TerminalContextMenuItemProvider } from './contextMenuProvider'
/** @hidden */
@@ -22,8 +22,8 @@ export interface ToastrServiceProxy {
* A class to base your custom terminal tabs on
*/
export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
static template = require('../components/baseTerminalTab.component.pug')
static styles = [require('../components/terminalTab.component.scss')]
static template = require<string>('../components/baseTerminalTab.component.pug')
static styles = [require<string>('../components/terminalTab.component.scss')]
static animations: AnimationTriggerMetadata[] = [trigger('slideInOut', [
transition(':enter', [
style({ transform: 'translateY(-25%)' }),
@@ -35,6 +35,8 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
])]
session: BaseSession
savedState: any
@Input() zoom = 0
@Input() showSearchPanel = false
@@ -56,6 +58,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
frontendReady = new Subject<void>()
size: ResizeEvent
/**
* Enables normall passthrough from session output to terminal input
*/
enablePassthrough = true
protected logger: Logger
protected output = new Subject<string>()
private sessionCloseSubscription: Subscription
@@ -63,7 +70,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
private bellPlayer: HTMLAudioElement
private termContainerSubscriptions: Subscription[] = []
get input$ (): Observable<string> { return this.frontend.input$ }
get input$ (): Observable<Buffer> { return this.frontend.input$ }
get output$ (): Observable<string> { return this.output }
get resize$ (): Observable<ResizeEvent> { return this.frontend.resize$ }
get alternateScreenActive$ (): Observable<boolean> { return this.frontend.alternateScreenActive$ }
@@ -83,7 +90,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
@Inject(ToastrService) protected toastr: ToastrServiceProxy,
protected log: LogService,
@Optional() @Inject(TerminalDecorator) protected decorators: TerminalDecorator[],
@Optional() @Inject(TerminalContextMenuItemProvider) protected contextMenuProviders: TerminalContextMenuItemProvider[],
@Optional() @Inject(TabContextMenuItemProvider) protected contextMenuProviders: TabContextMenuItemProvider[],
) {
super()
this.logger = log.create('baseTerminalTab')
@@ -167,6 +174,14 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.size = { columns, rows }
this.frontendReady.next()
this.config.enabledServices(this.decorators).forEach(decorator => {
try {
decorator.attach(this)
} catch (e) {
this.logger.warn('Decorator attach() throws', e)
}
})
setTimeout(() => {
this.session.resize(columns, rows)
}, 1000)
@@ -174,6 +189,13 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.session.releaseInitialDataBuffer()
})
if (this.savedState) {
this.frontend.restoreState(this.savedState)
this.frontend.write('\r\n\r\n')
this.frontend.write(colors.bgWhite.black(' * ') + colors.bgBlackBright.white(' History restored '))
this.frontend.write('\r\n\r\n')
}
setImmediate(() => {
if (this.hasFocus) {
this.frontend.attach(this.content.nativeElement)
@@ -190,14 +212,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.configure()
this.config.enabledServices(this.decorators).forEach((decorator) => {
try {
decorator.attach(this)
} catch (e) {
this.logger.warn('Decorator attach() throws', e)
}
})
setTimeout(() => {
this.output.subscribe(() => {
this.displayActivity()
@@ -229,7 +243,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
/**
* Feeds input into the active session
*/
sendInput (data: string) {
sendInput (data: string|Buffer) {
if (!(data instanceof Buffer)) {
data = Buffer.from(data, 'utf-8')
}
this.session.write(data)
if (this.config.store.terminal.scrollOnInput) {
this.frontend.scrollToBottom()
@@ -245,7 +262,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
if (percentage > 0 && percentage <= 100) {
this.setProgress(percentage)
this.logger.debug('Detected progress:', percentage)
// this.logger.debug('Detected progress:', percentage)
}
} else {
this.setProgress(null)
@@ -350,7 +367,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.frontend.mouseEvent$.subscribe(async event => {
if (event.type === 'mousedown') {
if (event.which === 2) {
this.paste()
if (this.config.store.terminal.pasteOnMiddleClick) {
this.paste()
}
event.preventDefault()
event.stopPropagation()
return
@@ -405,10 +424,12 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
protected attachSessionHandlers () {
// this.session.output$.bufferTime(10).subscribe((datas) => {
this.session.output$.subscribe(data => {
this.zone.run(() => {
this.output.next(data)
this.write(data)
})
if (this.enablePassthrough) {
this.zone.run(() => {
this.output.next(data)
this.write(data)
})
}
})
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {

View File

@@ -2,6 +2,7 @@ import { BaseTerminalTabComponent } from './baseTerminalTab.component'
/**
* Extend to add more terminal context menu items
* @deprecated
*/
export abstract class TerminalContextMenuItemProvider {
weight: number

View File

@@ -1,16 +1,35 @@
import { Subscription } from 'rxjs'
import { BaseTerminalTabComponent } from './baseTerminalTab.component'
/**
* Extend to automatically run actions on new terminals
*/
export abstract class TerminalDecorator {
private smartSubscriptions = new Map<BaseTerminalTabComponent, Subscription[]>()
/**
* Called when a new terminal tab starts
*/
attach (terminal: BaseTerminalTabComponent): void { } // eslint-disable-line
/**
* Called before a terminal tab is destroyed
* Called before a terminal tab is destroyed.
* Make sure to call super()
*/
detach (terminal: BaseTerminalTabComponent): void { } // eslint-disable-line
detach (terminal: BaseTerminalTabComponent): void {
for (const s of this.smartSubscriptions.get(terminal) || []) {
s.unsubscribe()
}
this.smartSubscriptions.delete(terminal)
}
/**
* Automatically cancel @subscription once detached from @terminal
*/
protected subscribeUntilDetached (terminal: BaseTerminalTabComponent, subscription: Subscription) {
if (!this.smartSubscriptions.has(terminal)) {
this.smartSubscriptions.set(terminal, [])
}
this.smartSubscriptions.get(terminal)?.push(subscription)
}
}

View File

@@ -16,8 +16,9 @@ export interface SessionOptions {
}
export interface Profile {
name: string,
sessionOptions: SessionOptions,
name: string
color?: string
sessionOptions: SessionOptions
isBuiltin?: boolean
icon?: string
}

View File

@@ -8,7 +8,7 @@ module.exports = function patchPTYModule (mod) {
mod.spawn = (file, args, opt) => {
let terminal = oldSpawn(file, args, opt)
let timeout = null
let buffer = ''
let buffer = Buffer.from('')
let lastFlush = 0
let nextTimeout = 0
@@ -19,11 +19,11 @@ module.exports = function patchPTYModule (mod) {
const maxWindow = 100
function flush () {
if (buffer) {
if (buffer.length) {
terminal.emit('data-buffered', buffer)
}
lastFlush = Date.now()
buffer = ''
buffer = Buffer.from('')
}
function reschedule () {
@@ -38,12 +38,15 @@ module.exports = function patchPTYModule (mod) {
}
terminal.on('data', data => {
buffer += data
if (typeof data === 'string') {
data = Buffer.from(data)
}
buffer = Buffer.concat([buffer, data])
if (Date.now() - lastFlush > maxWindow) {
// Taking too much time buffering, flush to keep things interactive
flush()
} else {
if (Date.now() > nextTimeout - (maxWindow / 10)) {
if (Date.now() > nextTimeout - maxWindow / 10) {
// Extend the window if it's expiring
reschedule()
}

View File

@@ -1,24 +1,11 @@
h3.mb-3 Appearance
.d-flex
.mr-5
.form-line
.header
.title Frontend
.description Switches terminal frontend implementation (experimental)
select.form-control(
[(ngModel)]='config.store.terminal.frontend',
(ngModelChange)='config.save()',
)
option(value='hterm') hterm
option(value='xterm') xterm
option(value='xterm-webgl') xterm (WebGL)
.form-line
.header
.title Font
.d-flex.w-75
.input-group.w-75
input.form-control.w-75(
type='text',
[ngbTypeahead]='fontAutocomplete',
@@ -52,9 +39,10 @@ h3.mb-3 Appearance
)
option(*ngFor='let scheme of config.store.terminal.customColorSchemes', [ngValue]='scheme') Custom: {{scheme.name}}
option(*ngFor='let scheme of colorSchemes', [ngValue]='scheme') {{scheme.name}}
.input-group-btn
button.btn.btn-secondary((click)='editScheme(config.store.terminal.colorScheme)') Edit
.input-group-btn
.input-group-append
button.btn.btn-secondary((click)='editScheme(config.store.terminal.colorScheme)')
i.fas.fa-pen
.input-group-append
button.btn.btn-outline-danger(
(click)='deleteScheme(config.store.terminal.colorScheme)',
*ngIf='isCustomScheme(config.store.terminal.colorScheme)'
@@ -65,10 +53,12 @@ h3.mb-3 Appearance
label Editing
.input-group
input.form-control(type='text', [(ngModel)]='editingColorScheme.name')
.input-group-btn
button.btn.btn-secondary((click)='saveScheme()') Save
.input-group-btn
button.btn.btn-secondary((click)='cancelEditing()') Cancel
.input-group-append
button.btn.btn-secondary((click)='saveScheme()')
i.fas.fa-check
.input-group-append
button.btn.btn-secondary((click)='cancelEditing()')
i.fas.fa-times
.form-group(*ngIf='editingColorScheme')
color-picker(
@@ -180,6 +170,19 @@ h3.mb-3 Appearance
span rm -rf /
span([style.background-color]='config.store.terminal.colorScheme.cursor') &nbsp;
.form-line
.header
.title Frontend
.description Switches terminal frontend implementation (experimental)
select.form-control(
[(ngModel)]='config.store.terminal.frontend',
(ngModelChange)='config.save()',
)
option(value='hterm') hterm
option(value='xterm') xterm
option(value='xterm-webgl') xterm (WebGL)
.form-line
.header
.title Terminal background

View File

@@ -5,10 +5,9 @@ import deepEqual from 'deep-equal'
const fontManager = require('fontmanager-redux') // eslint-disable-line
import { Component, Inject } from '@angular/core'
import { ConfigService, HostAppService, Platform, ElectronService } from 'terminus-core'
import { ConfigService, HostAppService, Platform, ElectronService, getCSSFontFamily } from 'terminus-core'
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
import { TerminalColorScheme } from '../api/interfaces'
import { getCSSFontFamily } from '../utils'
/** @hidden */
@Component({

View File

@@ -2,55 +2,64 @@
.form-group
label Name
input.form-control(
type='text',
autofocus,
[(ngModel)]='profile.name',
type='text',
autofocus,
[(ngModel)]='profile.name',
)
.form-group
label Command
input.form-control(
type='text',
[(ngModel)]='profile.sessionOptions.command',
type='text',
[(ngModel)]='profile.sessionOptions.command',
)
.form-group
label Arguments
.input-group(
*ngFor='let arg of profile.sessionOptions.args; index as i; trackBy: trackByIndex',
)
input.form-control(
type='text',
[(ngModel)]='profile.sessionOptions.args[i]',
type='text',
[(ngModel)]='profile.sessionOptions.args[i]',
)
.input-group-btn
.input-group-append
button.btn.btn-secondary((click)='profile.sessionOptions.args.splice(i, 1)')
i.fas.fa-trash
.mt-2
button.btn.btn-secondary((click)='profile.sessionOptions.args.push("")')
i.fas.fa-plus.mr-2
| Add
.form-line(*ngIf='uac.isAvailable')
.header
.title Run as administrator
toggle(
[(ngModel)]='profile.sessionOptions.runAsAdministrator',
)
.form-group
label Working directory
input.form-control(
type='text',
[(ngModel)]='profile.sessionOptions.cwd',
type='text',
[(ngModel)]='profile.sessionOptions.cwd',
)
.form-group
label Environment
environment-editor(
type='text',
[(model)]='profile.sessionOptions.env',
type='text',
[(model)]='profile.sessionOptions.env',
)
.form-group
label Tab color
input.form-control(
type='text',
autofocus,
[(ngModel)]='profile.color',
placeholder='#000000'
)
.modal-footer

View File

@@ -1,12 +1,13 @@
.mb-2.d-flex.align-items-center(*ngFor='let pair of vars')
.input-group.w-50
input.form-control([(ngModel)]='pair.key', (blur)='emitUpdate()', placeholder='Variable name')
.input-group-append
.input-group
input.form-control.w-25([(ngModel)]='pair.key', (blur)='emitUpdate()', placeholder='Variable name')
.input-group-append
.input-group-text =
input.form-control.w-50.mr-1([(ngModel)]='pair.value', (blur)='emitUpdate()', placeholder='Value')
button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
i.fas.fa-trash
input.form-control.w-50([(ngModel)]='pair.value', (blur)='emitUpdate()', placeholder='Value')
.input-group-append
button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
i.fas.fa-trash
button.btn.btn-secondary((click)='addEnvironmentVar()')
i.fas.fa-plus.mr-2
span Add

View File

@@ -2,7 +2,7 @@
input.search-input.form-control(
type='search',
[(ngModel)]='query',
(ngModelChange)='notFound = false',
(ngModelChange)='onQueryChange()',
[class.text-danger]='notFound',
(click)='$event.stopPropagation()',
(keyup.enter)='findNext()',
@@ -10,31 +10,27 @@
placeholder='Search...'
)
.input-group-append
.btn-group
button.btn.btn-outline-primary(
.input-group-text
a(
(click)='options.caseSensitive = !options.caseSensitive',
[class.active]='options.caseSensitive',
[class.text-info]='options.caseSensitive',
ngbTooltip='Case sensitivity',
placement='bottom'
)
i.fa.fa-fw.fa-font
button.btn.btn-outline-primary(
a(
(click)='options.regex = !options.regex',
[class.active]='options.regex',
[class.text-info]='options.regex',
ngbTooltip='Regular expression',
placement='bottom'
)
i.fa.fa-fw.fa-asterisk
button.btn.btn-outline-primary(
a(
(click)='options.wholeWord = !options.wholeWord',
[class.active]='options.wholeWord',
[class.text-info]='options.wholeWord',
ngbTooltip='Whole word',
placement='bottom'
)
i.fa.fa-fw.fa-text-width
button.btn.btn-outline(
(click)='close.emit()',
ngbTooltip='Close',
placement='bottom'
)
i.fa.fa-fw.fa-times
button.close.text-light.pl-3.pr-2((click)='close.emit()') &times;

View File

@@ -1,9 +1,20 @@
:host {
position: fixed;
width: 400px;
align-self: center;
right: 50px;
z-index: 5;
padding: 10px;
border-radius: 0 0 3px 3px;
background: rgba(0, 0, 0, .75);
border: 1px solid rgba(0, 0, 0, .5);
border-top: 0;
display: flex;
a {
padding-left: 10px;
&:first-child {
padding-left: 0;
}
}
}

View File

@@ -11,7 +11,9 @@ export class SearchPanelComponent {
@Input() query: string
@Input() frontend: Frontend
notFound = false
options: SearchOptions = {}
options: SearchOptions = {
incremental: true,
}
@Output() close = new EventEmitter()
@@ -19,8 +21,13 @@ export class SearchPanelComponent {
private toastr: ToastrService,
) { }
findNext () {
if (!this.frontend.findNext(this.query, this.options)) {
onQueryChange () {
this.notFound = false
this.findNext(true)
}
findNext (incremental = false) {
if (!this.frontend.findNext(this.query, { ...this.options, incremental: incremental || undefined })) {
this.notFound = true
this.toastr.error('Not found')
}

View File

@@ -14,20 +14,20 @@ h3.mb-3 Shell
[ngValue]='slug(profile.name).toLowerCase()'
) {{profile.name}}
.form-line(*ngIf='isConPTYAvailable')
.header
.title Use ConPTY
.description Enables the experimental Windows ConPTY API
toggle(
[(ngModel)]='config.store.terminal.useConPTY',
(ngModelChange)='config.save()'
)
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.useConPTY && isConPTYAvailable && !isConPTYStable')
.mr-auto Windows 10 build 18309 or above is recommended for ConPTY
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.profile.startsWith("WSL") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)')
.mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend
@@ -50,15 +50,17 @@ h3.mb-3 Shell
placeholder='Home directory',
[(ngModel)]='config.store.terminal.workingDirectory',
(ngModelChange)='config.save()',
)
.input-group-btn
)
.input-group-append
button.btn.btn-secondary((click)='pickWorkingDirectory()')
i.fas.fa-folder-open
.form-line
.header
.title Always Use Working Directory
.description By default, new terminals will open where the previous terminal was working. Enabling this option will always launch new terminals in the working directory specified above.
.description
div By default, new terminals will open where the previous terminal was working.
div Enabling this option will always launch new terminals in the working directory specified above.
toggle(
[(ngModel)]='config.store.terminal.alwaysUseWorkingDirectory',
@@ -69,7 +71,7 @@ h3.mb-3 Shell
.header
.title Environment
.description Inject additional environment variables
environment-editor([(model)]='this.config.store.terminal.environment')
h3.mt-3 Saved Profiles
@@ -78,16 +80,16 @@ h3.mt-3 Saved Profiles
.list-group-item.list-group-item-action.d-flex.align-items-center(
*ngFor='let profile of config.store.terminal.profiles',
(click)='editProfile(profile)',
)
)
.mr-auto
div {{profile.name}}
.text-muted {{profile.sessionOptions.command}}
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)')
i.fas.fa-trash
div(ngbDropdown, placement='top-left')
button.btn.btn-primary(ngbDropdownToggle)
button.btn.btn-primary(ngbDropdownToggle)
i.fas.fa-fw.fa-plus
| New profile
| New profile
div(ngbDropdownMenu)
button.dropdown-item(*ngFor='let shell of shells', (click)='newProfile(shell)') {{shell.name}}

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