mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-28 17:58:33 +00:00
Compare commits
139 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
76892c4f5c | ||
![]() |
d1ac265d79 | ||
![]() |
030ddc721d | ||
![]() |
645531acc0 | ||
![]() |
555c8c18ee | ||
![]() |
5caa4d14f5 | ||
![]() |
2b12f89f31 | ||
![]() |
e63c87df72 | ||
![]() |
a5c94707d4 | ||
![]() |
25c20e834c | ||
![]() |
b08604a5df | ||
![]() |
d6860d75c2 | ||
![]() |
a02ce88925 | ||
![]() |
e18b84afed | ||
![]() |
57feb1f3cc | ||
![]() |
907ee4ccb5 | ||
![]() |
e6b210dad5 | ||
![]() |
177a988292 | ||
![]() |
fdca83ff27 | ||
![]() |
1598dab025 | ||
![]() |
9e3d952d90 | ||
![]() |
50304d151a | ||
![]() |
589da576a0 | ||
![]() |
b934a34be5 | ||
![]() |
4fa6bb398b | ||
![]() |
a2929309d9 | ||
![]() |
a78fec0a6f | ||
![]() |
81e1757ae9 | ||
![]() |
3eb4bd53a9 | ||
![]() |
bf893551c8 | ||
![]() |
303c59cecc | ||
![]() |
6c5c670315 | ||
![]() |
2bea7f3881 | ||
![]() |
27a162c903 | ||
![]() |
c5ee39e4a1 | ||
![]() |
ea2251532b | ||
![]() |
077c3ced39 | ||
![]() |
65ee7b755a | ||
![]() |
a43ca24ba6 | ||
![]() |
a1199da883 | ||
![]() |
c845412fdf | ||
![]() |
0ba3de45a4 | ||
![]() |
9e0808fca3 | ||
![]() |
45b7391e89 | ||
![]() |
0eb1e8117c | ||
![]() |
be951cc9ce | ||
![]() |
c88b02fa91 | ||
![]() |
f9bf1e5644 | ||
![]() |
6c61f12584 | ||
![]() |
1efae39d9a | ||
![]() |
6d76874045 | ||
![]() |
0180fb0134 | ||
![]() |
90f97d6669 | ||
![]() |
f27f52dd72 | ||
![]() |
60a48ec2a5 | ||
![]() |
c64654991b | ||
![]() |
1fc531ecf4 | ||
![]() |
4c7e7f5fae | ||
![]() |
7b07a67947 | ||
![]() |
fe5193d9f1 | ||
![]() |
b6a3af80fa | ||
![]() |
46a9b655fc | ||
![]() |
762ee85773 | ||
![]() |
650e362c42 | ||
![]() |
136ec1035b | ||
![]() |
f27e1ec62d | ||
![]() |
c736a84835 | ||
![]() |
b3a07e5f99 | ||
![]() |
c408154137 | ||
![]() |
c0988e58b4 | ||
![]() |
d6e906c107 | ||
![]() |
d77a91b3e1 | ||
![]() |
80f82296a0 | ||
![]() |
6e9f497d22 | ||
![]() |
50f01b6794 | ||
![]() |
b068070825 | ||
![]() |
194342d6fa | ||
![]() |
d7eeac6af7 | ||
![]() |
98a08b92a2 | ||
![]() |
fef8638ade | ||
![]() |
34ff0c45cb | ||
![]() |
1896155ad9 | ||
![]() |
bbcbad0e77 | ||
![]() |
ce435056a2 | ||
![]() |
fe9b14ad9c | ||
![]() |
fc72e5005c | ||
![]() |
f5c428d73b | ||
![]() |
b396060965 | ||
![]() |
c752a18f3c | ||
![]() |
805ee0af09 | ||
![]() |
ad9ad4d418 | ||
![]() |
d5c4088cc1 | ||
![]() |
483a0472b9 | ||
![]() |
1bbf9d4294 | ||
![]() |
10c8502fbd | ||
![]() |
8f3f6f591d | ||
![]() |
656d275801 | ||
![]() |
9c53503c0f | ||
![]() |
9ea99f1ace | ||
![]() |
126d14dfb7 | ||
![]() |
68803b5f14 | ||
![]() |
e0273126de | ||
![]() |
0ced498b6e | ||
![]() |
510682438e | ||
![]() |
762874c400 | ||
![]() |
b7e2e0875e | ||
![]() |
9cfd02bff6 | ||
![]() |
9082fe5c06 | ||
![]() |
43786fda83 | ||
![]() |
1677285ea9 | ||
![]() |
aaa0a0f69a | ||
![]() |
cb8832fbad | ||
![]() |
e39321c8cb | ||
![]() |
3ef7697be8 | ||
![]() |
8927717654 | ||
![]() |
3a8168917a | ||
![]() |
9249c48ecc | ||
![]() |
6d1150d08a | ||
![]() |
b234300bd8 | ||
![]() |
be3bae3a6f | ||
![]() |
767f9f3215 | ||
![]() |
d6e69f5bf5 | ||
![]() |
5c644e5e23 | ||
![]() |
5b905af5d3 | ||
![]() |
28f4a052d7 | ||
![]() |
948251e326 | ||
![]() |
2203661f19 | ||
![]() |
8f4e28fba4 | ||
![]() |
a413bbaf07 | ||
![]() |
4e05adeb66 | ||
![]() |
59ac4a858e | ||
![]() |
55ae5b27b9 | ||
![]() |
b0aa20b387 | ||
![]() |
bb00f2f033 | ||
![]() |
e80c3ce693 | ||
![]() |
b9b6c63d57 | ||
![]() |
bee62f3001 | ||
![]() |
2f35ae203d | ||
![]() |
604e5e37a8 |
@@ -599,6 +599,33 @@
|
||||
"contributions": [
|
||||
"infra"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mwz",
|
||||
"name": "Michael Wizner",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1190768?v=4",
|
||||
"profile": "https://github.com/mwz",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mgrulich",
|
||||
"name": "Martin",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/781036?v=4",
|
||||
"profile": "https://github.com/mgrulich",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "piersandro",
|
||||
"name": "Piersandro Guerrera",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/19996309?v=4",
|
||||
"profile": "https://github.com/piersandro",
|
||||
"contributions": [
|
||||
"translation"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@@ -2,7 +2,7 @@ name: Package-Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
Lint:
|
||||
runs-on: macos-11.0
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
run: yarn run lint
|
||||
|
||||
macOS-Build:
|
||||
runs-on: macos-11.0
|
||||
runs-on: macos-11
|
||||
needs: Lint
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -54,10 +54,10 @@ jobs:
|
||||
run: |
|
||||
sudo npm i -g yarn@1.22.1
|
||||
cd app
|
||||
yarn
|
||||
yarn --network-timeout 1000000
|
||||
cd ..
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
yarn --network-timeout 1000000
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
@@ -149,10 +149,10 @@ jobs:
|
||||
sudo apt-get install libarchive-tools zsh
|
||||
npm i -g yarn@1.19.1
|
||||
cd app
|
||||
yarn
|
||||
yarn --network-timeout 1000000
|
||||
cd ..
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
yarn --network-timeout 1000000
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
@@ -266,7 +266,7 @@ jobs:
|
||||
shell: powershell
|
||||
run: |
|
||||
npm i -g yarn@1.19.1
|
||||
yarn
|
||||
yarn --network-timeout 1000000
|
||||
node scripts/build-native.js
|
||||
yarn run build
|
||||
node scripts/prepackage-plugins.js
|
||||
|
@@ -227,6 +227,9 @@ Pull requests and plugins are welcome!
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/JasonCubic"><img src="https://avatars.githubusercontent.com/u/8921015?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JasonCubic</b></sub></a><br /><a href="#design-JasonCubic" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/MaxWaldorf"><img src="https://avatars.githubusercontent.com/u/15877853?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MaxWaldorf</b></sub></a><br /><a href="#infra-MaxWaldorf" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/mwz"><img src="https://avatars.githubusercontent.com/u/1190768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Wizner</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mwz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mgrulich"><img src="https://avatars.githubusercontent.com/u/781036?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mgrulich" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piersandro"><img src="https://avatars.githubusercontent.com/u/19996309?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piersandro Guerrera</b></sub></a><br /><a href="#translation-piersandro" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@@ -232,6 +232,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/JasonCubic"><img src="https://avatars.githubusercontent.com/u/8921015?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JasonCubic</b></sub></a><br /><a href="#design-JasonCubic" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/MaxWaldorf"><img src="https://avatars.githubusercontent.com/u/15877853?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MaxWaldorf</b></sub></a><br /><a href="#infra-MaxWaldorf" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/mwz"><img src="https://avatars.githubusercontent.com/u/1190768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Wizner</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mwz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mgrulich"><img src="https://avatars.githubusercontent.com/u/781036?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mgrulich" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piersandro"><img src="https://avatars.githubusercontent.com/u/19996309?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piersandro Guerrera</b></sub></a><br /><a href="#translation-piersandro" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@@ -233,6 +233,9 @@ Pull-запросы и плагины приветствуются!
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/JasonCubic"><img src="https://avatars.githubusercontent.com/u/8921015?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JasonCubic</b></sub></a><br /><a href="#design-JasonCubic" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/MaxWaldorf"><img src="https://avatars.githubusercontent.com/u/15877853?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MaxWaldorf</b></sub></a><br /><a href="#infra-MaxWaldorf" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/mwz"><img src="https://avatars.githubusercontent.com/u/1190768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Wizner</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mwz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mgrulich"><img src="https://avatars.githubusercontent.com/u/781036?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mgrulich" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piersandro"><img src="https://avatars.githubusercontent.com/u/19996309?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piersandro Guerrera</b></sub></a><br /><a href="#translation-piersandro" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@@ -232,6 +232,9 @@
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/JasonCubic"><img src="https://avatars.githubusercontent.com/u/8921015?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JasonCubic</b></sub></a><br /><a href="#design-JasonCubic" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/MaxWaldorf"><img src="https://avatars.githubusercontent.com/u/15877853?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MaxWaldorf</b></sub></a><br /><a href="#infra-MaxWaldorf" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/mwz"><img src="https://avatars.githubusercontent.com/u/1190768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Wizner</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mwz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mgrulich"><img src="https://avatars.githubusercontent.com/u/781036?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=mgrulich" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piersandro"><img src="https://avatars.githubusercontent.com/u/19996309?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piersandro Guerrera</b></sub></a><br /><a href="#translation-piersandro" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@@ -93,6 +93,10 @@ export class Application {
|
||||
app.commandLine.appendSwitch(flag[0], flag[1])
|
||||
}
|
||||
|
||||
app.on('before-quit', () => {
|
||||
this.quitRequested = true
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (this.quitRequested || process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
|
@@ -25,6 +25,9 @@ export function parseArgs (argv: string[], cwd: string): any {
|
||||
type: 'string',
|
||||
})
|
||||
})
|
||||
.command('recent [index]', 'open a tab with a recent profile', {
|
||||
profileNumber: { type: 'number' },
|
||||
})
|
||||
.version(app.getVersion())
|
||||
.option('debug', {
|
||||
alias: 'd',
|
||||
|
@@ -135,6 +135,8 @@ export class Window {
|
||||
|
||||
this.window.webContents.setVisualZoomLevelLimits(1, 1)
|
||||
this.window.webContents.setZoomFactor(1)
|
||||
this.window.webContents.session.setPermissionCheckHandler(() => true)
|
||||
this.window.webContents.session.setDevicePermissionHandler(() => true)
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
this.touchBarControl = new TouchBar.TouchBarSegmentedControl({
|
||||
|
@@ -15,18 +15,17 @@
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/cdk": "^12.2.9",
|
||||
"@electron/remote": "2.0.1",
|
||||
"@tabby-gang/node-pty": "^0.11.0-beta.200",
|
||||
"any-promise": "^1.3.0",
|
||||
"electron-config": "2.0.0",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-promise-ipc": "^2.2.4",
|
||||
"electron-updater": "^4.6.1",
|
||||
"electron-updater": "^4.6.5",
|
||||
"fontmanager-redux": "1.1.0",
|
||||
"glasstron": "0.0.7",
|
||||
"js-yaml": "4.1.0",
|
||||
"keytar": "^7.7.0",
|
||||
"keytar": "^7.9.0",
|
||||
"mz": "^2.7.0",
|
||||
"native-process-working-directory": "^1.0.2",
|
||||
"npm": "6",
|
||||
@@ -38,7 +37,8 @@
|
||||
"optionalDependencies": {
|
||||
"@tabby-gang/windows-blurbehind": "^3.0.0",
|
||||
"macos-native-processlist": "^2.0.0",
|
||||
"serialport": "^10.0.2",
|
||||
"serialport": "10.2.2",
|
||||
"serialport-binding-webserialapi": "^1.0.3",
|
||||
"windows-native-registry": "^3.1.0",
|
||||
"windows-process-tree": "^0.3.2"
|
||||
},
|
||||
|
@@ -21,6 +21,8 @@ const builtinPluginsPath = process.env.TABBY_DEV ? path.dirname(remote.app.getAp
|
||||
|
||||
const cachedBuiltinModules = {
|
||||
'@angular/animations': require('@angular/animations'),
|
||||
'@angular/cdk/drag-drop': require('@angular/cdk/drag-drop'),
|
||||
'@angular/cdk/clipboard': require('@angular/cdk/clipboard'),
|
||||
'@angular/common': require('@angular/common'),
|
||||
'@angular/compiler': require('@angular/compiler'),
|
||||
'@angular/core': require('@angular/core'),
|
||||
@@ -64,18 +66,23 @@ export type ProgressCallback = (current: number, total: number) => void
|
||||
export function initModuleLookup (userPluginsPath: string): void {
|
||||
global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
|
||||
nodeModule.globalPaths.unshift(path.join(userPluginsPath, 'node_modules'))
|
||||
const paths = []
|
||||
paths.unshift(path.join(userPluginsPath, 'node_modules'))
|
||||
paths.unshift(path.join(remote.app.getAppPath(), 'node_modules'))
|
||||
|
||||
if (process.env.TABBY_DEV) {
|
||||
nodeModule.globalPaths.unshift(path.dirname(remote.app.getAppPath()))
|
||||
paths.unshift(path.dirname(remote.app.getAppPath()))
|
||||
}
|
||||
|
||||
nodeModule.globalPaths.unshift(builtinPluginsPath)
|
||||
// nodeModule.globalPaths.unshift(path.join((process as any).resourcesPath, 'app.asar', 'node_modules'))
|
||||
paths.unshift(builtinPluginsPath)
|
||||
// paths.unshift(path.join((process as any).resourcesPath, 'app.asar', 'node_modules'))
|
||||
if (process.env.TABBY_PLUGINS) {
|
||||
process.env.TABBY_PLUGINS.split(':').map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
process.env.TABBY_PLUGINS.split(':').map(x => paths.push(normalizePath(x)))
|
||||
}
|
||||
|
||||
process.env.NODE_PATH += path.delimiter + paths.join(path.delimiter)
|
||||
nodeModule._initPaths()
|
||||
|
||||
builtinModules.forEach(m => {
|
||||
if (!cachedBuiltinModules[m]) {
|
||||
cachedBuiltinModules[m] = nodeRequire(m)
|
||||
|
301
app/yarn.lock
301
app/yarn.lock
@@ -2,15 +2,6 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@angular/cdk@^12.2.9":
|
||||
version "12.2.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-12.2.9.tgz#f39e4d7cdb3568ad8e1d412e3500772e2d4c605c"
|
||||
integrity sha512-9Wgj69iGAZ4teQqW/zPbVg2RGna+m9i3v0zkWGx/+Uo95rikJCUZBQM4bfeOe+bSJrS77jV5EisBWG7ayNUSzQ==
|
||||
dependencies:
|
||||
tslib "^2.2.0"
|
||||
optionalDependencies:
|
||||
parse5 "^5.0.0"
|
||||
|
||||
"@electron/remote@2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron/remote/-/remote-2.0.1.tgz#810cbc595a21f0f94641eb2d7e8264063a3f84de"
|
||||
@@ -25,73 +16,101 @@
|
||||
update-notifier "^2.2.0"
|
||||
yargs "^8.0.2"
|
||||
|
||||
"@serialport/binding-abstract@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-10.0.1.tgz#fc5a69b05d364fa7db872b3fe64ae85aaa3030a5"
|
||||
integrity sha512-FWD/uNrz8V3kaTILQTK05Z1LB/LZin8XZelmX/wd1NNlRFAj6V64MIESWhwUy3iPnL1QriFR1k7URHHx3RRgfg==
|
||||
"@serialport/binding-abstract@^9.0.2":
|
||||
version "9.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz#e7dd273357b6a698af7ad58db6f57f62443a0acb"
|
||||
integrity sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==
|
||||
dependencies:
|
||||
debug "^4.3.2"
|
||||
|
||||
"@serialport/binding-mock@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-mock/-/binding-mock-10.0.1.tgz#b70747c897b861fe7d090f0350f0dc5a37f36b70"
|
||||
integrity sha512-cU+UtCaQI1ZOWzIa4uT7Z0ymgAyQMSwEBF/BM87LtQ9QFjLwCgmuouy3vcsryWNEN3Lg0GwhQzl9ZuDw4bs/qw==
|
||||
"@serialport/binding-mock@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-mock/-/binding-mock-10.2.2.tgz#d322a8116a97806addda13c62f50e73d16125874"
|
||||
integrity sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==
|
||||
dependencies:
|
||||
"@serialport/binding-abstract" "10.0.1"
|
||||
debug "^4.3.2"
|
||||
"@serialport/bindings-interface" "^1.2.1"
|
||||
debug "^4.3.3"
|
||||
|
||||
"@serialport/bindings-cpp@^10.2.1":
|
||||
version "10.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/bindings-cpp/-/bindings-cpp-10.2.1.tgz#e44a246142c11c83f0e4fd0cd16491702e6c3202"
|
||||
integrity sha512-PCnMBdy53/DLYx8dJg4e8Na1hMVGxE0d60IU6i03+k5SEmtPblixvIyytcllFhMRGQmH2zHHjP/2Big2Rjddwg==
|
||||
"@serialport/bindings-cpp@10.6.2":
|
||||
version "10.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/bindings-cpp/-/bindings-cpp-10.6.2.tgz#2ecb0a958d69d9d9e72cbf46481472937954adb5"
|
||||
integrity sha512-vhId2K4Y4WOgy/UJE8NOHX6GZpozORCCMh6GM5UQeIzXihoYLxt4eomgl1eXasFipcRs06n71lAToqixb7NPpA==
|
||||
dependencies:
|
||||
"@serialport/binding-abstract" "10.0.1"
|
||||
"@serialport/parser-readline" "10.0.1"
|
||||
"@serialport/bindings-interface" "1.2.1"
|
||||
"@serialport/parser-readline" "^10.2.1"
|
||||
debug "^4.3.2"
|
||||
node-addon-api "4.2.0"
|
||||
node-addon-api "^4.3.0"
|
||||
node-gyp-build "^4.3.0"
|
||||
|
||||
"@serialport/parser-byte-length@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-10.0.1.tgz#c9038449e82e2f36093e7d3efe3ca16c6e357f3d"
|
||||
integrity sha512-uOQa0KEGT7IIGSWCN53NE5ZYaWoeeGLDCSX+ssDadyQxy47hMHuP/JotdWqHg7lDwxUHe0tDl4SOEeEnDx1l6A==
|
||||
"@serialport/bindings-interface@1.2.1", "@serialport/bindings-interface@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/bindings-interface/-/bindings-interface-1.2.1.tgz#1ee80b0951ef4e4fd8a5a186621feff046aa2faf"
|
||||
integrity sha512-63Dyqz2gtryRDDckFusOYqLYhR3Hq/M4sEdbF9i/VsvDb6T+tNVgoAKUZ+FMrXXKnCSu+hYbk+MTc0XQANszxw==
|
||||
|
||||
"@serialport/parser-cctalk@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-10.0.1.tgz#df3c26886e920a45e17aba563b44324f5c1906b8"
|
||||
integrity sha512-boVr8akjX/7iCtMHeFT16ek4m0/oV9YA6A2mstVCpKle2op42qByx3jY5RzQ52c13oQvq1E6tG0lWJrzdTK+Yw==
|
||||
"@serialport/parser-byte-length@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-10.2.2.tgz#10129fb83fb0bd5e4c673d866534ea714022708e"
|
||||
integrity sha512-3xqaRbNiqDo8Gf1jPgrZr2nObKfAjhFihINZLJfPG7skWXfDKuF0zXuStzixre26N8GYWnkn4j/oEnI0RZjVDA==
|
||||
|
||||
"@serialport/parser-delimiter@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-10.0.1.tgz#bb0a04e140bf428d5b49e7838b9f136c40b4a091"
|
||||
integrity sha512-B0c6dm9UCpRU/LhkvRFL3OSbs69VqWU7mjW7tM109JDNS+vw8uJPumXz8Giub6D0xl90J7euH6tBTqERk7048Q==
|
||||
"@serialport/parser-cctalk@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-10.2.2.tgz#7009b245cf7f6d9fa0e1a8039fcf2ed4292199da"
|
||||
integrity sha512-WK+82D10y+vL2Rv1Hs2MRNKeY18uVC0+eH9QCfD9e2o+4+jPHfN2boJQFxVGtrlss8j5DmQ5Sc5Qe6Ep+f20/Q==
|
||||
|
||||
"@serialport/parser-inter-byte-timeout@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-10.0.1.tgz#bbae1835a0ad0ea6e79dcb27f159231b7051a73a"
|
||||
integrity sha512-awX0bekMZkjb+kjBHsnizAXNfc/grxIqEKdy9Etc6KhgSmratRnjGa7J0rPFP4bTzYWp5sOqlI0ALwBnWCXedA==
|
||||
"@serialport/parser-delimiter@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-10.2.2.tgz#e305ad321ebc6dd2739cc919b66602c6c5bc4f8c"
|
||||
integrity sha512-VsepMDIjbHbANMxH4IkXIJY0Tds8XsDo0mgtWK3DrV+IJGXp+2b0pHOuQlSLSfEUmdw7F5drI17fkxc9mxn+pg==
|
||||
|
||||
"@serialport/parser-readline@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-10.0.1.tgz#c4f7f047d4779c908cfb66d14c0ca0abd7e11f25"
|
||||
integrity sha512-jdKPNka/Nn17k89T5UIyis39EaZHQCmq+83s0icBt2iPBlX8+BrJAUBe8myFpuT22qskTVNzFoTMPOp8pjK/yw==
|
||||
"@serialport/parser-inter-byte-timeout@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-10.2.2.tgz#22293882c9bd7ae9b18be9a30ca2fcd7a0617dc9"
|
||||
integrity sha512-J9895aJ+3cHp2Q9qMH3UulfaifHDbDHjLPbO2H0vqjI8gZemL0DGql5ooFI6zsgJStXYT1MjqIhIb8dBIE0nxA==
|
||||
|
||||
"@serialport/parser-packet-length@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-packet-length/-/parser-packet-length-10.2.2.tgz#24790ba057090b8c7f5067a229b98d273fa6b71f"
|
||||
integrity sha512-AEh/4pOoolUgCwg7ZW5M81isPjOhSf+Fq7OdyaR0GEHHrRgaY7ma2xkyp+sgjcYoeBzlxe3pPdi7LGtBJEFDnw==
|
||||
|
||||
"@serialport/parser-readline@10.2.2", "@serialport/parser-readline@^10.2.1":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-10.2.2.tgz#94bfbf4a76760141ce8c7efddbc76d00dfe6dd55"
|
||||
integrity sha512-OcWoTsUJeLKWw+rdTuqXFZhii2liE6LeoFK2rtS6L00pB0cd2FGt2Rsx76oTCTyrub6AAUqaS9PRrAI+AUJJpg==
|
||||
dependencies:
|
||||
"@serialport/parser-delimiter" "10.0.1"
|
||||
"@serialport/parser-delimiter" "10.2.2"
|
||||
|
||||
"@serialport/parser-ready@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-10.0.1.tgz#497c4ae0bcc1866b488d8c4f9d6b4e98c4f08aa3"
|
||||
integrity sha512-4hVDrKNJBd0wcCfa1qQAk+MM6mVWc9oIbUPEKJkWdBrrWOqYacx2UpvQWd+3YGJ04hFqEv1feOSaH3/1hUifEg==
|
||||
"@serialport/parser-ready@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-10.2.2.tgz#5d057f7d65fece8ea3c7f2cacf4026768a34e53d"
|
||||
integrity sha512-Y5NA/kMb27afeFvSHhQ0Ov7PUt6vPSUqm7y+u6gajMpYOhKMjbLyQHuYMkgtGgk/PsryaOerd4OCVaYCEj0C+Q==
|
||||
|
||||
"@serialport/parser-regex@10.0.1":
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-10.0.1.tgz#bcb302dda0a9d07ce9b3e554e3d2a41abf3fb5c5"
|
||||
integrity sha512-l8ECuUsan33x5pirQZodlmw0q70Jcxy+oHnXJaqchBTRCbtXlE7+PMFJnmNoIHGqDwt0XALbwpvKcnNBrgvT1g==
|
||||
"@serialport/parser-regex@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-10.2.2.tgz#0275c207485f7cbd4787ef54e835eab6a7126b15"
|
||||
integrity sha512-+fAchSfl65Ix1BbyNPBu0SreZg2Tc2JJkvXsKsWFpoaOEsuxbCthrNmyvjt3AZ228pay6kKvF2PkRd/z+BFSfw==
|
||||
|
||||
"@serialport/stream@10.0.2":
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-10.0.2.tgz#3a242ea8a42356af9e4fb0924ca4a4a0efd36e37"
|
||||
integrity sha512-ZlC1M8/+hIO4JYI+cwJMAL2gkdf6Ahcen5gHJhM1Ibj40fRPOtxIWR1vgGFY1a/TKADDUZorE4RVYxmbheeZYw==
|
||||
"@serialport/parser-slip-encoder@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-slip-encoder/-/parser-slip-encoder-10.2.2.tgz#ba3b4d3d6f172b0a22b82b86db5e1cd00e3ef22f"
|
||||
integrity sha512-cDJvco/exmQ7xgISVNbNb73r8l0j7eQDTVXxa8whUt8tdkf/J5y8jZLZgboh/iXbEcrNtohwUhIfb633NotNxg==
|
||||
|
||||
"@serialport/parser-spacepacket@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-spacepacket/-/parser-spacepacket-10.2.2.tgz#e0b9186d6239f97a615cb8990db153e1bb564bf7"
|
||||
integrity sha512-TdfDYfIg41lXXuFsbdTZ2IHKhb3MgLJMMRhutoc/q6wX7LFhFD7FhdlkX3w85x15p1Et+iekGW5I/b48s47gXQ==
|
||||
|
||||
"@serialport/stream@10.2.2":
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-10.2.2.tgz#80e3acd7a54c5da16659b3c34d419ca7302eff14"
|
||||
integrity sha512-xKO5f73KbqZYadKYbtlDHE5RUwqSK8dF2brQRA6dikeyHWbVNhjwNtjWglwgzPl4SLB1A1uT97hMxrBrSCs6/w==
|
||||
dependencies:
|
||||
"@serialport/bindings-interface" "1.2.1"
|
||||
debug "^4.3.2"
|
||||
|
||||
"@serialport/stream@^9.0.2":
|
||||
version "9.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-9.2.4.tgz#9fce093d0b46ed4599953b4fae81718e050d2b33"
|
||||
integrity sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==
|
||||
dependencies:
|
||||
debug "^4.3.2"
|
||||
|
||||
@@ -385,10 +404,10 @@ buffer@^5.5.0:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builder-util-runtime@8.9.1:
|
||||
version "8.9.1"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.1.tgz#25f066b3fbc20b3e6236a9b956b1ebb0e33ff66a"
|
||||
integrity sha512-c8a8J3wK6BIVLW7ls+7TRK9igspTbzWmUqxFbgK0m40Ggm6efUbxtWVCGIjc+dtchyr5qAMAUL6iEGRdS/6vwg==
|
||||
builder-util-runtime@8.9.2:
|
||||
version "8.9.2"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz#a9669ae5b5dcabfe411ded26678e7ae997246c28"
|
||||
integrity sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==
|
||||
dependencies:
|
||||
debug "^4.3.2"
|
||||
sax "^1.2.4"
|
||||
@@ -738,6 +757,13 @@ debug@^4.0.1, debug@^4.3.2:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^4.3.3:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debuglog@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz"
|
||||
@@ -753,12 +779,12 @@ decode-uri-component@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||
|
||||
decompress-response@^4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz"
|
||||
integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
|
||||
decompress-response@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
|
||||
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
|
||||
dependencies:
|
||||
mimic-response "^2.0.0"
|
||||
mimic-response "^3.1.0"
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
@@ -794,10 +820,10 @@ detect-indent@~5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
|
||||
integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
detect-libc@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.0.tgz#c528bc09bc6d1aa30149228240917c225448f204"
|
||||
integrity sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==
|
||||
|
||||
detect-newline@^2.1.0:
|
||||
version "2.1.0"
|
||||
@@ -897,13 +923,13 @@ electron-promise-ipc@^2.2.4:
|
||||
serialize-error "^5.0.0"
|
||||
uuid "^3.0.1"
|
||||
|
||||
electron-updater@^4.6.1:
|
||||
version "4.6.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.1.tgz#80ca805c4f51b2e682aac29d18fed75d6a533d32"
|
||||
integrity sha512-YsU1mHqXLrXXmBMsxhxy24PrbaB8rnpZDPmFa2gOkTYk/Ch13+R0fjsRSpPYvqtskVVY0ux8fu+HnUkVkqc7og==
|
||||
electron-updater@^4.6.5:
|
||||
version "4.6.5"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.5.tgz#e9a75458bbfd6bb41a58a829839e150ad2eb2d3d"
|
||||
integrity sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA==
|
||||
dependencies:
|
||||
"@types/semver" "^7.3.6"
|
||||
builder-util-runtime "8.9.1"
|
||||
builder-util-runtime "8.9.2"
|
||||
fs-extra "^10.0.0"
|
||||
js-yaml "^4.1.0"
|
||||
lazy-val "^1.0.5"
|
||||
@@ -1743,13 +1769,13 @@ keyboardevents-areequal@^0.2.1:
|
||||
resolved "https://registry.npmjs.org/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz"
|
||||
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
|
||||
|
||||
keytar@^7.7.0:
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.7.0.tgz#3002b106c01631aa79b1aa9ee0493b94179bbbd2"
|
||||
integrity sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==
|
||||
keytar@^7.9.0:
|
||||
version "7.9.0"
|
||||
resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.9.0.tgz#4c6225708f51b50cbf77c5aae81721964c2918cb"
|
||||
integrity sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==
|
||||
dependencies:
|
||||
node-addon-api "^3.0.0"
|
||||
prebuild-install "^6.0.0"
|
||||
node-addon-api "^4.3.0"
|
||||
prebuild-install "^7.0.1"
|
||||
|
||||
klaw-sync@^6.0.0:
|
||||
version "6.0.0"
|
||||
@@ -2101,10 +2127,10 @@ mimic-fn@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
||||
integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
|
||||
|
||||
mimic-response@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz"
|
||||
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
|
||||
mimic-response@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
@@ -2232,28 +2258,35 @@ nice-try@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-abi@^2.20.0, node-abi@^2.7.0:
|
||||
node-abi@^2.20.0:
|
||||
version "2.30.1"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf"
|
||||
integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==
|
||||
dependencies:
|
||||
semver "^5.4.1"
|
||||
|
||||
node-abi@^3.3.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.8.0.tgz#679957dc8e7aa47b0a02589dbfde4f77b29ccb32"
|
||||
integrity sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw==
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
node-addon-api@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz"
|
||||
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
|
||||
|
||||
node-addon-api@4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.2.0.tgz#117cbb5a959dff0992e1c586ae0393573e4d2a87"
|
||||
integrity sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q==
|
||||
|
||||
node-addon-api@^3.0.0, node-addon-api@^3.0.2, node-addon-api@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz"
|
||||
integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
|
||||
|
||||
node-addon-api@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
|
||||
integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==
|
||||
|
||||
node-fetch-npm@^2.0.2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4"
|
||||
@@ -2285,11 +2318,6 @@ node-gyp@^5.0.2, node-gyp@^5.1.0:
|
||||
tar "^4.4.12"
|
||||
which "^1.3.1"
|
||||
|
||||
noop-logger@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz"
|
||||
integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
|
||||
|
||||
nopt@^4.0.1, nopt@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
|
||||
@@ -2758,11 +2786,6 @@ parse-json@^2.2.0:
|
||||
dependencies:
|
||||
error-ex "^1.2.0"
|
||||
|
||||
parse5@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
|
||||
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
|
||||
|
||||
patch-package@^6.4.7:
|
||||
version "6.4.7"
|
||||
resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148"
|
||||
@@ -2841,26 +2864,24 @@ pkg-up@^2.0.0:
|
||||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
prebuild-install@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.0.1.tgz#5902172f7a40eb67305b96c2a695db32636ee26d"
|
||||
integrity sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==
|
||||
prebuild-install@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.0.1.tgz#c10075727c318efe72412f333e0ef625beaf3870"
|
||||
integrity sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg==
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
detect-libc "^2.0.0"
|
||||
expand-template "^2.0.3"
|
||||
github-from-package "0.0.0"
|
||||
minimist "^1.2.3"
|
||||
mkdirp-classic "^0.5.3"
|
||||
napi-build-utils "^1.0.1"
|
||||
node-abi "^2.7.0"
|
||||
noop-logger "^0.1.1"
|
||||
node-abi "^3.3.0"
|
||||
npmlog "^4.0.1"
|
||||
pump "^3.0.0"
|
||||
rc "^1.2.7"
|
||||
simple-get "^3.0.3"
|
||||
simple-get "^4.0.0"
|
||||
tar-fs "^2.0.0"
|
||||
tunnel-agent "^0.6.0"
|
||||
which-pm-runs "^1.0.0"
|
||||
|
||||
prepend-http@^1.0.1:
|
||||
version "1.0.4"
|
||||
@@ -3235,21 +3256,32 @@ serialize-error@^5.0.0:
|
||||
dependencies:
|
||||
type-fest "^0.8.0"
|
||||
|
||||
serialport@^10.0.2:
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/serialport/-/serialport-10.0.2.tgz#64150fd2cd4cec35a88e0b8af66614a42b06e577"
|
||||
integrity sha512-hFQ6V/LFh0G4FmQsPjQCLqofalpHRWznXVA3lKlA19kUkdQrOmsz3CHQ72mPglbY+1PGGHZwXHPdTROtWP4qsA==
|
||||
serialport-binding-webserialapi@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/serialport-binding-webserialapi/-/serialport-binding-webserialapi-1.0.3.tgz#cf4348c075da2de8f6cf9936c0b95645f3ae657b"
|
||||
integrity sha512-TS7dsvetVoTeiWlzpsT/akjtljiYPO56FoJWSFyJSoO/E8icYJ2neQ7CW5NW/sHZDnMqAxULyAny47UFhWz9oQ==
|
||||
dependencies:
|
||||
"@serialport/binding-mock" "10.0.1"
|
||||
"@serialport/bindings-cpp" "^10.2.1"
|
||||
"@serialport/parser-byte-length" "10.0.1"
|
||||
"@serialport/parser-cctalk" "10.0.1"
|
||||
"@serialport/parser-delimiter" "10.0.1"
|
||||
"@serialport/parser-inter-byte-timeout" "10.0.1"
|
||||
"@serialport/parser-readline" "10.0.1"
|
||||
"@serialport/parser-ready" "10.0.1"
|
||||
"@serialport/parser-regex" "10.0.1"
|
||||
"@serialport/stream" "10.0.2"
|
||||
"@serialport/binding-abstract" "^9.0.2"
|
||||
"@serialport/stream" "^9.0.2"
|
||||
|
||||
serialport@10.2.2:
|
||||
version "10.2.2"
|
||||
resolved "https://registry.yarnpkg.com/serialport/-/serialport-10.2.2.tgz#ab12a423046df6b64cb3144fdb2d00fb3062ab75"
|
||||
integrity sha512-yYp8UM915g8C3+lYZ7GU1Em1BnMeaH9c2bN2/A8ptQH5ttD7E+k9PuDEVOuyxONuyiBOp+vHfIPnje1evnslEw==
|
||||
dependencies:
|
||||
"@serialport/binding-mock" "10.2.2"
|
||||
"@serialport/bindings-cpp" "10.6.2"
|
||||
"@serialport/parser-byte-length" "10.2.2"
|
||||
"@serialport/parser-cctalk" "10.2.2"
|
||||
"@serialport/parser-delimiter" "10.2.2"
|
||||
"@serialport/parser-inter-byte-timeout" "10.2.2"
|
||||
"@serialport/parser-packet-length" "10.2.2"
|
||||
"@serialport/parser-readline" "10.2.2"
|
||||
"@serialport/parser-ready" "10.2.2"
|
||||
"@serialport/parser-regex" "10.2.2"
|
||||
"@serialport/parser-slip-encoder" "10.2.2"
|
||||
"@serialport/parser-spacepacket" "10.2.2"
|
||||
"@serialport/stream" "10.2.2"
|
||||
debug "^4.3.2"
|
||||
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
@@ -3286,12 +3318,12 @@ simple-concat@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz"
|
||||
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
|
||||
|
||||
simple-get@^3.0.3:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz"
|
||||
integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
|
||||
simple-get@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
|
||||
integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==
|
||||
dependencies:
|
||||
decompress-response "^4.2.0"
|
||||
decompress-response "^6.0.0"
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
@@ -3661,7 +3693,7 @@ tough-cookie@~2.5.0:
|
||||
psl "^1.1.28"
|
||||
punycode "^2.1.1"
|
||||
|
||||
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.2.0:
|
||||
tslib@^2.0.0, tslib@^2.1.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
@@ -3832,11 +3864,6 @@ which-module@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz"
|
||||
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||
|
||||
which-pm-runs@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz"
|
||||
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
|
||||
|
||||
which@^1.2.9, which@^1.3.0, which@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
|
980
locale/app.pot
980
locale/app.pot
File diff suppressed because it is too large
Load Diff
2159
locale/bg-BG.po
Normal file
2159
locale/bg-BG.po
Normal file
File diff suppressed because it is too large
Load Diff
2159
locale/da-DK.po
Normal file
2159
locale/da-DK.po
Normal file
File diff suppressed because it is too large
Load Diff
3587
locale/de-DE.po
3587
locale/de-DE.po
File diff suppressed because it is too large
Load Diff
5
locale/en-US.po
Normal file
5
locale/en-US.po
Normal file
@@ -0,0 +1,5 @@
|
||||
msgid "id.port-forwarding.dynamic"
|
||||
msgstr "Dynamic"
|
||||
|
||||
msgid "id.tab-width.dynamic"
|
||||
msgstr "Dynamic"
|
3614
locale/es-ES.po
3614
locale/es-ES.po
File diff suppressed because it is too large
Load Diff
3614
locale/fr-FR.po
3614
locale/fr-FR.po
File diff suppressed because it is too large
Load Diff
3585
locale/hr-HR.po
3585
locale/hr-HR.po
File diff suppressed because it is too large
Load Diff
2159
locale/it-IT.po
Normal file
2159
locale/it-IT.po
Normal file
File diff suppressed because it is too large
Load Diff
2159
locale/ja-JP.po
Normal file
2159
locale/ja-JP.po
Normal file
File diff suppressed because it is too large
Load Diff
3587
locale/pl-PL.po
3587
locale/pl-PL.po
File diff suppressed because it is too large
Load Diff
3587
locale/ru-RU.po
3587
locale/ru-RU.po
File diff suppressed because it is too large
Load Diff
3614
locale/zh-CN.po
3614
locale/zh-CN.po
File diff suppressed because it is too large
Load Diff
3612
locale/zh-TW.po
3612
locale/zh-TW.po
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@angular/animations": "^12.0.0",
|
||||
"@angular/cdk": "^12.2.9",
|
||||
"@angular/common": "^12.0.0",
|
||||
"@angular/compiler": "^12.0.0",
|
||||
"@angular/core": "^12.0.0",
|
||||
"@angular/forms": "^12.0.0",
|
||||
"@angular/platform-browser": "^12.0.0",
|
||||
"@angular/platform-browser-dynamic": "^12.0.0",
|
||||
"@biesbjerg/ngx-translate-extract": "^7.0.4",
|
||||
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
|
||||
"@fortawesome/fontawesome-free": "^6.0.0-beta3",
|
||||
"@fortawesome/fontawesome-free": "^6.0.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "^10.0.0",
|
||||
"@sentry/cli": "^1.71.0",
|
||||
"@sentry/cli": "^1.72.1",
|
||||
"@sentry/electron": "^2.5.4",
|
||||
"@tabby-gang/to-string-loader": "^1.1.7-beta.2",
|
||||
"@types/deep-equal": "1.0.1",
|
||||
"@types/electron-config": "^3.2.2",
|
||||
"@types/electron-debug": "^2.1.0",
|
||||
"@types/fs-extra": "^9.0.12",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/node": "16.0.1",
|
||||
"@types/sortablejs": "^1.10.7",
|
||||
@@ -25,22 +25,23 @@
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"apply-loader": "2.0.0",
|
||||
"axios": "^0.21.2",
|
||||
"axios": "^0.25.0",
|
||||
"browserify-sign": "^4.2.1",
|
||||
"clone-deep": "^4.0.1",
|
||||
"compare-versions": "^4",
|
||||
"core-js": "^3.18.2",
|
||||
"core-js": "^3.20.3",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "^6.5.1",
|
||||
"deep-equal": "2.0.5",
|
||||
"electron": "16.0.8",
|
||||
"electron-builder": "^22.14.5",
|
||||
"electron": "17.0.1",
|
||||
"electron-builder": "^22.14.13",
|
||||
"electron-download": "^4.1.1",
|
||||
"electron-installer-snap": "^5.1.0",
|
||||
"electron-notarize": "^1.1.1",
|
||||
"electron-rebuild": "^3.2.7",
|
||||
"eslint": "^7.32.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"gettext-extractor": "^3.5.4",
|
||||
"graceful-fs": "^4.2.9",
|
||||
"html-loader": "2.1.2",
|
||||
"json-loader": "^0.5.7",
|
||||
@@ -48,7 +49,7 @@
|
||||
"macos-release": "^3.0.1",
|
||||
"ngx-sortablejs": "^11.1.0",
|
||||
"ngx-toastr": "^14.0.0",
|
||||
"node-abi": "^3.2.0",
|
||||
"node-abi": "^3.8.0",
|
||||
"node-sass": "^7.0.1",
|
||||
"npmlog": "6.0.0",
|
||||
"npx": "^10.2.2",
|
||||
@@ -69,16 +70,16 @@
|
||||
"source-code-pro": "^2.38.0",
|
||||
"source-map-loader": "^3.0.1",
|
||||
"source-sans-pro": "3.6.0",
|
||||
"ssh2": "^1.5.0",
|
||||
"ssh2": "^1.6.0",
|
||||
"style-loader": "^3.2.1",
|
||||
"svg-inline-loader": "^0.8.2",
|
||||
"ts-loader": "^9.2.3",
|
||||
"tslib": "^2.3.1",
|
||||
"typedoc": "^0.22.10",
|
||||
"typedoc": "^0.22.12",
|
||||
"typescript": "^4.3.5",
|
||||
"utils-decorators": "^1.10.4",
|
||||
"val-loader": "4.0.0",
|
||||
"webpack": "^5.67.0",
|
||||
"webpack": "^5.69.1",
|
||||
"webpack-bundle-analyzer": "^4.5.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"yaml-loader": "0.6.0",
|
||||
|
@@ -3,6 +3,9 @@ const sh = require('shelljs')
|
||||
const fs = require('fs/promises')
|
||||
const vars = require('./vars')
|
||||
const log = require('npmlog')
|
||||
const { GettextExtractor, JsExtractors, HtmlExtractors } = require('gettext-extractor')
|
||||
|
||||
let extractor = new GettextExtractor()
|
||||
|
||||
const tempOutput = 'locale/app.new.pot'
|
||||
const pot = 'locale/app.pot'
|
||||
@@ -11,17 +14,40 @@ const tempHtml = 'locale/tmp-html'
|
||||
;(async () => {
|
||||
sh.mkdir('-p', tempHtml)
|
||||
for (const plugin of vars.builtinPlugins) {
|
||||
log.info('extract-pug', plugin)
|
||||
log.info('compile-pug', plugin)
|
||||
|
||||
sh.exec(`yarn pug --doctype html -s --pretty -O '{require: function(){}}' -o ${tempHtml}/${plugin} ${plugin}`, { fatal: true })
|
||||
|
||||
log.info('extract-ts', plugin)
|
||||
sh.exec(`node node_modules/.bin/ngx-translate-extract -i ${plugin}/src -m -s -f pot -o ${tempOutput}`, { fatal: true })
|
||||
}
|
||||
|
||||
log.info('extract-ts')
|
||||
extractor.createJsParser([
|
||||
JsExtractors.callExpression('this.translate.instant', {
|
||||
arguments: { text: 0 },
|
||||
}),
|
||||
JsExtractors.callExpression('translate.instant', {
|
||||
arguments: { text: 0 },
|
||||
}),
|
||||
JsExtractors.callExpression('_', {
|
||||
arguments: { text: 0 },
|
||||
}),
|
||||
]).parseFilesGlob('./tabby-*/src/**/*.ts')
|
||||
|
||||
log.info('extract-pug')
|
||||
sh.exec(`node node_modules/.bin/ngx-translate-extract -i ${tempHtml} -f pot -s -o ${tempOutput}`, { fatal: true })
|
||||
const options = {
|
||||
attributes: {
|
||||
context: 'translatecontext',
|
||||
},
|
||||
}
|
||||
extractor.createHtmlParser([
|
||||
HtmlExtractors.elementContent('translate, [translate=""]', options),
|
||||
HtmlExtractors.elementAttribute('[translate*=" "]', 'translate', options),
|
||||
]).parseFilesGlob(`${tempHtml}/**/*.html`)
|
||||
|
||||
extractor.savePotFile(tempOutput)
|
||||
extractor.printStats()
|
||||
|
||||
sh.rm('-r', tempHtml)
|
||||
sh.exec(`msgcat -s ${tempOutput} > ${pot}`, { fatal: true })
|
||||
|
||||
await fs.rename(tempOutput, pot)
|
||||
})()
|
||||
|
@@ -9,18 +9,18 @@ sh.exec(`yarn patch-package`, { fatal: true })
|
||||
log.info('deps', 'app')
|
||||
|
||||
sh.cd('app')
|
||||
sh.exec(`yarn install --force`, { fatal: true })
|
||||
sh.exec(`yarn install --force --network-timeout 1000000`, { fatal: true })
|
||||
sh.cd('..')
|
||||
|
||||
sh.cd('web')
|
||||
sh.exec(`yarn install --force`, { fatal: true })
|
||||
sh.exec(`yarn install --force --network-timeout 1000000`, { fatal: true })
|
||||
sh.exec(`yarn patch-package`, { fatal: true })
|
||||
sh.cd('..')
|
||||
|
||||
vars.allPackages.forEach(plugin => {
|
||||
log.info('deps', plugin)
|
||||
sh.cd(plugin)
|
||||
sh.exec(`yarn install --force`, { fatal: true })
|
||||
sh.exec(`yarn install --force --network-timeout 1000000`, { fatal: true })
|
||||
sh.cd('..')
|
||||
})
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-community-color-schemes",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Community color schemes for Tabby",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-core",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Tabby core",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -4,6 +4,7 @@ import { NewTabParameters } from '../services/tabs.service'
|
||||
export interface RecoveryToken {
|
||||
[_: string]: any
|
||||
type: string
|
||||
tabIcon?: string|null
|
||||
tabColor?: string|null
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,10 @@ export class ProfileCLIHandler extends CLIHandler {
|
||||
this.handleOpenProfile(event.argv.profileName)
|
||||
return true
|
||||
}
|
||||
if (op === 'recent') {
|
||||
this.handleOpenRecentProfile(event.argv.profileNumber)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -35,6 +39,15 @@ export class ProfileCLIHandler extends CLIHandler {
|
||||
this.profiles.openNewTabForProfile(profile)
|
||||
this.hostWindow.bringToFront()
|
||||
}
|
||||
|
||||
private async handleOpenRecentProfile (profileNumber: number) {
|
||||
const profiles = this.profiles.getRecentProfiles()
|
||||
if (profileNumber >= profiles.length) {
|
||||
return
|
||||
}
|
||||
this.profiles.openNewTabForProfile(profiles[profileNumber])
|
||||
this.hostWindow.bringToFront()
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
|
@@ -112,6 +112,12 @@ export class AppRootComponent {
|
||||
if (hotkey === 'duplicate-tab') {
|
||||
this.app.duplicateTab(this.app.activeTab)
|
||||
}
|
||||
if (hotkey === 'explode-tab' && this.app.activeTab instanceof SplitTabComponent) {
|
||||
this.app.explodeTab(this.app.activeTab)
|
||||
}
|
||||
if (hotkey === 'combine-tabs' && this.app.activeTab instanceof SplitTabComponent) {
|
||||
this.app.combineTabsInto(this.app.activeTab)
|
||||
}
|
||||
}
|
||||
if (hotkey === 'reopen-tab') {
|
||||
this.app.reopenLastTab()
|
||||
@@ -215,7 +221,7 @@ export class AppRootComponent {
|
||||
}
|
||||
|
||||
@HostBinding('class.vibrant') get isVibrant () {
|
||||
return this.config.store.appearance.vibrancy
|
||||
return this.config.store?.appearance.vibrancy
|
||||
}
|
||||
|
||||
private getToolbarButtons (aboveZero: boolean): ToolbarButton[] {
|
||||
|
@@ -51,6 +51,13 @@ export abstract class BaseTabComponent extends BaseComponent {
|
||||
set color (value: string|null) { this._color = value }
|
||||
private _color: string|null = null
|
||||
|
||||
/**
|
||||
* icon override for the tab's header
|
||||
*/
|
||||
get icon (): string|null { return this._icon }
|
||||
set icon (value: string|null) { this._icon = value }
|
||||
private _icon: string|null = null
|
||||
|
||||
hasFocus = false
|
||||
|
||||
/**
|
||||
|
@@ -82,6 +82,18 @@ export class SplitContainer {
|
||||
this.ratios = this.ratios.map(x => x / s)
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes all tabs have the same size
|
||||
*/
|
||||
equalize (): void {
|
||||
for (const child of this.children) {
|
||||
if (child instanceof SplitContainer) {
|
||||
child.equalize()
|
||||
}
|
||||
}
|
||||
this.ratios.fill(1 / this.ratios.length)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the left/top side offset for the given element index (between 0 and 1)
|
||||
*/
|
||||
@@ -158,7 +170,6 @@ export type SplitDropZoneInfo = {
|
||||
></split-tab-spanner>
|
||||
<split-tab-drop-zone
|
||||
*ngFor='let dropZone of _dropZones'
|
||||
[enabled]='dropZonesEnabled'
|
||||
[parent]='this'
|
||||
[dropZone]='dropZone'
|
||||
(tabDropped)='onTabDropped($event, dropZone)'
|
||||
@@ -450,6 +461,8 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
this.attachTabView(tab)
|
||||
this.onAfterTabAdded(tab)
|
||||
}
|
||||
|
||||
this.root.normalize()
|
||||
}
|
||||
|
||||
removeTab (tab: BaseTabComponent): void {
|
||||
@@ -604,10 +617,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
this.tabAdopted.next(tab)
|
||||
}
|
||||
|
||||
get dropZonesEnabled (): boolean {
|
||||
return this.getAllTabs().length > 1
|
||||
}
|
||||
|
||||
destroy (): void {
|
||||
super.destroy()
|
||||
for (const x of this.getAllTabs()) {
|
||||
@@ -629,6 +638,16 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
super.clearActivity()
|
||||
}
|
||||
|
||||
get icon (): string|null {
|
||||
return this.getFocusedTab()?.icon ?? null
|
||||
}
|
||||
|
||||
set icon (icon: string|null) {
|
||||
for (const t of this.getAllTabs()) {
|
||||
t.icon = icon
|
||||
}
|
||||
}
|
||||
|
||||
get color (): string|null {
|
||||
return this.getFocusedTab()?.color ?? null
|
||||
}
|
||||
@@ -639,8 +658,13 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
}
|
||||
|
||||
equalize (): void {
|
||||
this.root.normalize()
|
||||
this.root.equalize()
|
||||
}
|
||||
|
||||
private updateTitle (): void {
|
||||
this.setTitle(this.getAllTabs().map(x => x.title).join(' | '))
|
||||
this.setTitle([...new Set(this.getAllTabs().map(x => x.title))].join(' | '))
|
||||
}
|
||||
|
||||
private attachTabView (tab: BaseTabComponent) {
|
||||
|
@@ -3,7 +3,7 @@ import { Component, Input, HostBinding, ElementRef, Output, EventEmitter } from
|
||||
import { AppService } from '../services/app.service'
|
||||
import { BaseTabComponent } from './baseTab.component'
|
||||
import { SelfPositioningComponent } from './selfPositioning.component'
|
||||
import { SplitDropZoneInfo } from './splitTab.component'
|
||||
import { SplitDropZoneInfo, SplitTabComponent } from './splitTab.component'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
@@ -22,31 +22,31 @@ import { SplitDropZoneInfo } from './splitTab.component'
|
||||
})
|
||||
export class SplitTabDropZoneComponent extends SelfPositioningComponent {
|
||||
@Input() dropZone: SplitDropZoneInfo
|
||||
@Input() parent: BaseTabComponent
|
||||
@Input() enabled = false
|
||||
@Input() parent: SplitTabComponent
|
||||
@Output() tabDropped = new EventEmitter<BaseTabComponent>()
|
||||
@HostBinding('class.active') isActive = false
|
||||
@HostBinding('class.highlighted') isHighlighted = false
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||
constructor (
|
||||
element: ElementRef,
|
||||
app: AppService,
|
||||
) {
|
||||
super(element)
|
||||
this.subscribeUntilDestroyed(app.tabDragActive$, tab => {
|
||||
this.isActive = !!(tab && this.canActivateFor(tab))
|
||||
this.isActive = !!tab && this.canActivateFor(tab)
|
||||
this.layout()
|
||||
})
|
||||
}
|
||||
|
||||
canActivateFor (tab: BaseTabComponent) {
|
||||
if (tab === this.parent || !this.enabled) {
|
||||
return false
|
||||
}
|
||||
if (this.dropZone.type === 'absolute' && tab === this.dropZone.container.children[this.dropZone.position]) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
canActivateFor (tab: BaseTabComponent): boolean {
|
||||
const allTabs = this.parent.getAllTabs()
|
||||
return !(
|
||||
tab === this.parent ||
|
||||
allTabs.length === 1 && allTabs.includes(tab) ||
|
||||
this.dropZone.type === 'relative' && tab === this.dropZone.relativeTo ||
|
||||
this.dropZone.type === 'absolute' && tab === this.dropZone.container.children[this.dropZone.position]
|
||||
)
|
||||
}
|
||||
|
||||
ngOnChanges () {
|
||||
|
@@ -13,7 +13,8 @@
|
||||
div {
|
||||
background: rgba(0, 0, 0, .7);
|
||||
padding: 20px 30px;
|
||||
font-size: 18px;
|
||||
margin: 20px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@@ -20,4 +20,7 @@ footer.d-flex.align-items-center
|
||||
i.fas.fa-bug
|
||||
span(translate) Report a problem
|
||||
|
||||
.form-control-static.selectable.no-drag {{ 'Version: {version}'|translate:{ version: this.homeBase.appVersion } }}
|
||||
.form-control-static.selectable.no-drag(
|
||||
translate='Version: {version}',
|
||||
[translateParams]='{ version: this.homeBase.appVersion }'
|
||||
)
|
||||
|
@@ -5,6 +5,12 @@
|
||||
.index(*ngIf='!config.store.terminal.hideTabIndex && hostApp.platform === Platform.macOS', cdkDragHandle) {{index + 1}}
|
||||
.index(*ngIf='!config.store.terminal.hideTabIndex && hostApp.platform !== Platform.macOS') {{index + 1}}
|
||||
|
||||
.icon(
|
||||
*ngIf='config.store.terminal.showTabProfileIcon && tab.icon',
|
||||
[ngClass]='tab.icon',
|
||||
[style.color]='tab.color'
|
||||
)
|
||||
|
||||
.name(
|
||||
[title]='tab.customTitle || tab.title',
|
||||
[class.no-hover]='config.store.terminal.hideCloseButton'
|
||||
|
@@ -26,7 +26,8 @@ $tabs-height: 38px;
|
||||
height: $tabs-height;
|
||||
}
|
||||
|
||||
.index {
|
||||
.index,
|
||||
.icon {
|
||||
flex: none;
|
||||
font-weight: bold;
|
||||
-webkit-app-region: no-drag;
|
||||
@@ -40,6 +41,11 @@ $tabs-height: 38px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 13px;
|
||||
margin: 1px 4px 0 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: auto;
|
||||
margin-top: 1px;
|
||||
|
@@ -4,8 +4,10 @@
|
||||
.ml-auto(ngbDropdown, placement='bottom-right')
|
||||
button.btn.btn-link(ngbDropdownToggle, (click)='$event.stopPropagation()')
|
||||
span(
|
||||
*ngIf='rememberFor'
|
||||
) {{ 'Remember for {time}'|translate:{time: getRememberForDisplay(rememberFor)} }}
|
||||
*ngIf='rememberFor',
|
||||
translate='Remember for {time}',
|
||||
[translateParams]='{time: getRememberForDisplay(rememberFor)}'
|
||||
)
|
||||
span(*ngIf='!rememberFor', translate) Do not remember
|
||||
div(ngbDropdownMenu)
|
||||
button.dropdown-item(
|
||||
|
@@ -13,8 +13,8 @@
|
||||
option([ngValue]='null', translate) Automatic
|
||||
option(
|
||||
[value]='lang.code',
|
||||
*ngFor='let lang of locale.allLanguages'
|
||||
) {{lang.name|translate}}
|
||||
*ngFor='let lang of allLanguages'
|
||||
) {{lang.name}}
|
||||
|
||||
.form-line
|
||||
.header
|
||||
|
@@ -13,6 +13,7 @@ import { LocaleService } from '../services/locale.service'
|
||||
})
|
||||
export class WelcomeTabComponent extends BaseTabComponent {
|
||||
enableGlobalHotkey = true
|
||||
allLanguages = LocaleService.allLanguages
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
|
@@ -21,6 +21,10 @@ hotkeys:
|
||||
rearrange-panes:
|
||||
- 'Ctrl-Shift'
|
||||
duplicate-tab: []
|
||||
explode-tab:
|
||||
- 'Ctrl-Shift-.'
|
||||
combine-tabs:
|
||||
- 'Ctrl-Shift-,'
|
||||
tab-1:
|
||||
- 'Alt-1'
|
||||
tab-2:
|
||||
|
@@ -39,6 +39,10 @@ hotkeys:
|
||||
tab-10:
|
||||
- '⌘-0'
|
||||
duplicate-tab: []
|
||||
explode-tab:
|
||||
- '⌘-Shift-.'
|
||||
combine-tabs:
|
||||
- '⌘-Shift-,'
|
||||
tab-11: []
|
||||
tab-12: []
|
||||
tab-13: []
|
||||
|
@@ -22,6 +22,10 @@ hotkeys:
|
||||
rearrange-panes:
|
||||
- 'Ctrl-Shift'
|
||||
duplicate-tab: []
|
||||
explode-tab:
|
||||
- 'Ctrl-Shift-.'
|
||||
combine-tab:
|
||||
- 'Ctrl-Shift-,'
|
||||
tab-1:
|
||||
- 'Alt-1'
|
||||
tab-2:
|
||||
|
@@ -56,6 +56,14 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
||||
id: 'duplicate-tab',
|
||||
name: this.translate.instant('Duplicate tab'),
|
||||
},
|
||||
{
|
||||
id: 'explode-tab',
|
||||
name: this.translate.instant('Turn current tab\'s panes into separate tabs'),
|
||||
},
|
||||
{
|
||||
id: 'combine-tabs',
|
||||
name: this.translate.instant('Combine all tabs into the current tab'),
|
||||
},
|
||||
{
|
||||
id: 'tab-1',
|
||||
name: this.translate.instant('Tab {number}', { number: 1 }),
|
||||
|
@@ -82,7 +82,7 @@ const PROVIDERS = [
|
||||
},
|
||||
{
|
||||
provide: MESSAGE_FORMAT_CONFIG,
|
||||
useValue: LocaleService.allLocales,
|
||||
useValue: LocaleService.allLanguages.map(x => x.code),
|
||||
},
|
||||
{
|
||||
provide: TranslateService,
|
||||
|
@@ -399,4 +399,40 @@ export class AppService {
|
||||
showSelector <T> (name: string, options: SelectorOption<T>[]): Promise<T> {
|
||||
return this.selector.show(name, options)
|
||||
}
|
||||
|
||||
explodeTab (tab: SplitTabComponent): SplitTabComponent[] {
|
||||
const result: SplitTabComponent[] = []
|
||||
for (const child of tab.getAllTabs().slice(1)) {
|
||||
tab.removeTab(child)
|
||||
result.push(this.wrapAndAddTab(child))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
combineTabsInto (into: SplitTabComponent): void {
|
||||
this.explodeTab(into)
|
||||
|
||||
let allChildren: BaseTabComponent[] = []
|
||||
for (const tab of this.tabs) {
|
||||
if (into === tab) {
|
||||
continue
|
||||
}
|
||||
let children = [tab]
|
||||
if (tab instanceof SplitTabComponent) {
|
||||
children = tab.getAllTabs()
|
||||
}
|
||||
allChildren = allChildren.concat(children)
|
||||
}
|
||||
|
||||
let x = 1
|
||||
let previous: BaseTabComponent|null = null
|
||||
const stride = Math.ceil(Math.sqrt(allChildren.length + 1))
|
||||
for (const child of allChildren) {
|
||||
into.add(child, x ? previous : null, x ? 'r' : 'b')
|
||||
previous = child
|
||||
x = (x + 1) % stride
|
||||
}
|
||||
|
||||
into.equalize()
|
||||
}
|
||||
}
|
||||
|
@@ -3,10 +3,14 @@ import { registerLocaleData } from '@angular/common'
|
||||
import { TranslateService } from '@ngx-translate/core'
|
||||
|
||||
import localeEN from '@angular/common/locales/en'
|
||||
import localeBG from '@angular/common/locales/bg'
|
||||
import localeDA from '@angular/common/locales/da'
|
||||
import localeDE from '@angular/common/locales/de'
|
||||
import localeES from '@angular/common/locales/es'
|
||||
import localeFR from '@angular/common/locales/fr'
|
||||
import localeHR from '@angular/common/locales/hr'
|
||||
import localeIT from '@angular/common/locales/it'
|
||||
import localeJA from '@angular/common/locales/ja'
|
||||
import localePL from '@angular/common/locales/pl'
|
||||
import localeRU from '@angular/common/locales/ru'
|
||||
import localeZH from '@angular/common/locales/zh'
|
||||
@@ -16,20 +20,42 @@ import { ConfigService } from './config.service'
|
||||
import { LogService, Logger } from './log.service'
|
||||
|
||||
registerLocaleData(localeEN)
|
||||
registerLocaleData(localeBG)
|
||||
registerLocaleData(localeDA)
|
||||
registerLocaleData(localeDE)
|
||||
registerLocaleData(localeES)
|
||||
registerLocaleData(localeFR)
|
||||
registerLocaleData(localeHR)
|
||||
registerLocaleData(localeIT)
|
||||
registerLocaleData(localeJA)
|
||||
registerLocaleData(localePL)
|
||||
registerLocaleData(localeRU)
|
||||
registerLocaleData(localeZH)
|
||||
|
||||
function flattenMessageFormatTranslation (po: any) {
|
||||
const translation = {}
|
||||
po = po.translations['']
|
||||
for (const k of Object.keys(po)) {
|
||||
translation[k] = po[k].msgstr[0] || k
|
||||
}
|
||||
return translation
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TranslateServiceWrapper extends TranslateService {
|
||||
private _defaultTranslation: Record<string, string>|null
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
getParsedResult (translations: any, key: any, interpolateParams?: any): any {
|
||||
this.translations[this.defaultLang][key] ??= this.compiler.compile(key, this.defaultLang)
|
||||
return super.getParsedResult(translations, key, interpolateParams)
|
||||
if (!this._defaultTranslation) {
|
||||
const po = require(`../../../locale/en-US.po`)
|
||||
this._defaultTranslation = flattenMessageFormatTranslation(po)
|
||||
}
|
||||
this.translations[this.defaultLang][key] ??= this.compiler.compile(
|
||||
this._defaultTranslation[key] || key,
|
||||
this.defaultLang
|
||||
)
|
||||
return super.getParsedResult(translations, key, interpolateParams ?? {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,20 +63,61 @@ export class TranslateServiceWrapper extends TranslateService {
|
||||
export class LocaleService {
|
||||
private logger: Logger
|
||||
|
||||
static readonly allLocales = [
|
||||
'en-US',
|
||||
'de-DE',
|
||||
'es-ES',
|
||||
'fr-FR',
|
||||
'hr-HR',
|
||||
'pl-PL',
|
||||
'ru-RU',
|
||||
'zh-CN',
|
||||
'zh-TW',
|
||||
static allLanguages = [
|
||||
{
|
||||
code: 'da-DK',
|
||||
name: 'Dansk',
|
||||
},
|
||||
{
|
||||
code: 'de-DE',
|
||||
name: 'Deutsch',
|
||||
},
|
||||
{
|
||||
code: 'en-US',
|
||||
name: 'English',
|
||||
},
|
||||
{
|
||||
code: 'es-ES',
|
||||
name: 'Español',
|
||||
},
|
||||
{
|
||||
code: 'fr-FR',
|
||||
name: 'Français',
|
||||
},
|
||||
{
|
||||
code: 'hr-HR',
|
||||
name: 'Hrvatski',
|
||||
},
|
||||
{
|
||||
code: 'it-IT',
|
||||
name: 'Italiano',
|
||||
},
|
||||
{
|
||||
code: 'pl-PL',
|
||||
name: 'Polski',
|
||||
},
|
||||
{
|
||||
code: 'bg-BG',
|
||||
name: 'Български',
|
||||
},
|
||||
{
|
||||
code: 'ru-RU',
|
||||
name: 'Русский',
|
||||
},
|
||||
{
|
||||
code: 'ja-JP',
|
||||
name: '日本語',
|
||||
},
|
||||
{
|
||||
code: 'zh-CN',
|
||||
name: '中文(简体)',
|
||||
},
|
||||
{
|
||||
code: 'zh-TW',
|
||||
name: '中文 (繁體)',
|
||||
},
|
||||
]
|
||||
|
||||
readonly allLanguages: { code: string, name: string }[]
|
||||
|
||||
get localeChanged$ (): Observable<string> {
|
||||
return this.localeChanged.pipe(distinctUntilChanged())
|
||||
}
|
||||
@@ -70,54 +137,13 @@ export class LocaleService {
|
||||
config.ready$.subscribe(() => {
|
||||
this.refresh()
|
||||
})
|
||||
|
||||
this.allLanguages = [
|
||||
{
|
||||
code: 'en-US',
|
||||
name: translate.instant('English'),
|
||||
},
|
||||
{
|
||||
code: 'zh-CN',
|
||||
name: translate.instant('Chinese (simplified)'),
|
||||
},
|
||||
{
|
||||
code: 'zh-TW',
|
||||
name: translate.instant('Chinese (traditional)'),
|
||||
},
|
||||
{
|
||||
code: 'hr-HR',
|
||||
name: translate.instant('Croatian'),
|
||||
},
|
||||
{
|
||||
code: 'de-DE',
|
||||
name: translate.instant('German'),
|
||||
},
|
||||
{
|
||||
code: 'fr-FR',
|
||||
name: translate.instant('French'),
|
||||
},
|
||||
{
|
||||
code: 'pl-PL',
|
||||
name: translate.instant('Polish'),
|
||||
},
|
||||
{
|
||||
code: 'ru-RU',
|
||||
name: translate.instant('Russian'),
|
||||
},
|
||||
{
|
||||
code: 'es-ES',
|
||||
name: translate.instant('Spanish'),
|
||||
},
|
||||
]
|
||||
|
||||
this.translate.setTranslation('en-US', {})
|
||||
}
|
||||
|
||||
refresh (): void {
|
||||
let lang = this.config.store.language
|
||||
if (!lang) {
|
||||
for (const systemLanguage of navigator.languages) {
|
||||
if (!lang && this.allLanguages.some(x => x.code === systemLanguage)) {
|
||||
if (!lang && LocaleService.allLanguages.some(x => x.code === systemLanguage)) {
|
||||
lang = systemLanguage
|
||||
}
|
||||
}
|
||||
@@ -127,15 +153,11 @@ export class LocaleService {
|
||||
}
|
||||
|
||||
async setLocale (lang: string): Promise<void> {
|
||||
if (!this.translate.langs.includes(lang) && lang !== 'en-US') {
|
||||
if (!this.translate.langs.includes(lang)) {
|
||||
this.translate.addLangs([lang])
|
||||
|
||||
const po = require(`../../../locale/${lang}.po`).translations['']
|
||||
const translation = {}
|
||||
for (const k of Object.keys(po)) {
|
||||
translation[k] = po[k].msgstr[0] || k
|
||||
}
|
||||
|
||||
const po = require(`../../../locale/${lang}.po`)
|
||||
const translation = flattenMessageFormatTranslation(po)
|
||||
this.translate.setTranslation(lang, translation)
|
||||
}
|
||||
|
||||
|
@@ -54,6 +54,9 @@ export class ProfilesService {
|
||||
if (fullProfile.color) {
|
||||
params.inputs['color'] = fullProfile.color
|
||||
}
|
||||
if (fullProfile.icon) {
|
||||
params.inputs['icon'] = fullProfile.icon
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
@@ -35,6 +35,9 @@ export class TabRecoveryService {
|
||||
if (token) {
|
||||
token.tabTitle = tab.title
|
||||
token.tabCustomTitle = tab.customTitle
|
||||
if (tab.icon) {
|
||||
token.tabIcon = tab.icon
|
||||
}
|
||||
if (tab.color) {
|
||||
token.tabColor = tab.color
|
||||
}
|
||||
@@ -51,6 +54,7 @@ export class TabRecoveryService {
|
||||
}
|
||||
const tab = await provider.recover(token)
|
||||
tab.inputs = tab.inputs ?? {}
|
||||
tab.inputs.icon = token.tabIcon ?? null
|
||||
tab.inputs.color = token.tabColor ?? null
|
||||
tab.inputs.title = token.tabTitle || ''
|
||||
tab.inputs.customTitle = token.tabCustomTitle || ''
|
||||
|
@@ -62,6 +62,10 @@ app-root {
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.icon {
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
button {
|
||||
color: $body-color;
|
||||
border: none;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-electron",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Electron-specific bindings",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { PlatformService, LogService, UpdaterService, DockingService, HostAppService, ThemesService, Platform, AppService, ConfigService, WIN_BUILD_FLUENT_BG_SUPPORTED, isWindowsBuild, HostWindowService, HotkeyProvider, ConfigProvider, FileProvider } from 'tabby-core'
|
||||
import { TerminalColorSchemeProvider } from 'tabby-terminal'
|
||||
import { SFTPContextMenuItemProvider, SSHProfileImporter } from 'tabby-ssh'
|
||||
import { SFTPContextMenuItemProvider, SSHProfileImporter, AutoPrivateKeyLocator } from 'tabby-ssh'
|
||||
import { auditTime } from 'rxjs'
|
||||
|
||||
import { HyperColorSchemes } from './colorSchemes'
|
||||
@@ -17,7 +17,7 @@ import { ElectronService } from './services/electron.service'
|
||||
import { ElectronHotkeyProvider } from './hotkeys'
|
||||
import { ElectronConfigProvider } from './config'
|
||||
import { EditSFTPContextMenu } from './sftpContextMenu'
|
||||
import { OpenSSHImporter } from './openSSHImport'
|
||||
import { OpenSSHImporter, PrivateKeyLocator, StaticFileImporter } from './sshImporters'
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
@@ -32,7 +32,9 @@ import { OpenSSHImporter } from './openSSHImport'
|
||||
{ provide: ConfigProvider, useClass: ElectronConfigProvider, multi: true },
|
||||
{ provide: FileProvider, useClass: ElectronFileProvider, multi: true },
|
||||
{ provide: SFTPContextMenuItemProvider, useClass: EditSFTPContextMenu, multi: true },
|
||||
{ provide: SSHProfileImporter, useClass: OpenSSHImporter, multi: true },
|
||||
{ provide: SSHProfileImporter, useExisting: OpenSSHImporter, multi: true },
|
||||
{ provide: SSHProfileImporter, useExisting: StaticFileImporter, multi: true },
|
||||
{ provide: AutoPrivateKeyLocator, useExisting: PrivateKeyLocator, multi: true },
|
||||
],
|
||||
})
|
||||
export default class ElectronModule {
|
||||
|
@@ -45,26 +45,26 @@ export class ElectronDockingService extends DockingService {
|
||||
const [minWidth, minHeight] = this.hostWindow.getWindow().getMinimumSize()
|
||||
|
||||
if (dockSide === 'left' || dockSide === 'right') {
|
||||
newBounds.width = Math.max(minWidth, Math.round(fill * display.bounds.width))
|
||||
newBounds.height = Math.round(display.bounds.height * space)
|
||||
newBounds.width = Math.max(minWidth, Math.round(fill * display.workArea.width))
|
||||
newBounds.height = Math.round(display.workArea.height * space)
|
||||
}
|
||||
if (dockSide === 'top' || dockSide === 'bottom') {
|
||||
newBounds.width = Math.round(display.bounds.width * space)
|
||||
newBounds.height = Math.max(minHeight, Math.round(fill * display.bounds.height))
|
||||
newBounds.width = Math.round(display.workArea.width * space)
|
||||
newBounds.height = Math.max(minHeight, Math.round(fill * display.workArea.height))
|
||||
}
|
||||
if (dockSide === 'right') {
|
||||
newBounds.x = display.bounds.x + display.bounds.width - newBounds.width
|
||||
newBounds.x = display.workArea.x + display.workArea.width - newBounds.width
|
||||
} else if (dockSide === 'left') {
|
||||
newBounds.x = display.bounds.x
|
||||
newBounds.x = display.workArea.x
|
||||
} else {
|
||||
newBounds.x = display.bounds.x + Math.round(display.bounds.width / 2 * (1 - space))
|
||||
newBounds.x = display.workArea.x + Math.round(display.workArea.width / 2 * (1 - space))
|
||||
}
|
||||
if (dockSide === 'bottom') {
|
||||
newBounds.y = display.bounds.y + display.bounds.height - newBounds.height
|
||||
newBounds.y = display.workArea.y + display.workArea.height - newBounds.height
|
||||
} else if (dockSide === 'top') {
|
||||
newBounds.y = display.bounds.y
|
||||
newBounds.y = display.workArea.y
|
||||
} else {
|
||||
newBounds.y = display.bounds.y + Math.round(display.bounds.height / 2 * (1 - space))
|
||||
newBounds.y = display.workArea.y + Math.round(display.workArea.height / 2 * (1 - space))
|
||||
}
|
||||
|
||||
const alwaysOnTop = this.config.store.appearance.dockAlwaysOnTop
|
||||
|
@@ -119,7 +119,7 @@ export class ElectronPlatformService extends PlatformService {
|
||||
}
|
||||
|
||||
async _saveConfigInternal (content: string): Promise<void> {
|
||||
const tempPath = this.configPath + '.new'
|
||||
const tempPath = this.configPath + '.new.' + Date.now().toString()
|
||||
await fs.writeFile(tempPath, content, 'utf8')
|
||||
await fs.writeFile(this.configPath + '.backup', content, 'utf8')
|
||||
await promisify(gracefulFS.rename)(tempPath, this.configPath)
|
||||
|
@@ -1,15 +1,20 @@
|
||||
import * as fs from 'fs/promises'
|
||||
import * as fsSync from 'fs'
|
||||
import * as path from 'path'
|
||||
import slugify from 'slugify'
|
||||
import * as yaml from 'js-yaml'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { PartialProfile } from 'tabby-core'
|
||||
import { SSHProfileImporter, PortForwardType, SSHProfile, SSHProfileOptions } from 'tabby-ssh'
|
||||
import { SSHProfileImporter, PortForwardType, SSHProfile, SSHProfileOptions, AutoPrivateKeyLocator } from 'tabby-ssh'
|
||||
|
||||
function deriveID (name: string): string {
|
||||
return 'openssh-config:' + slugify(name)
|
||||
}
|
||||
import { ElectronService } from './services/electron.service'
|
||||
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class OpenSSHImporter extends SSHProfileImporter {
|
||||
async getProfiles (): Promise<PartialProfile<SSHProfile>[]> {
|
||||
const deriveID = name => 'openssh-config:' + slugify(name)
|
||||
|
||||
const results: PartialProfile<SSHProfile>[] = []
|
||||
const configPath = path.join(process.env.HOME ?? '~', '.ssh', 'config')
|
||||
try {
|
||||
@@ -127,3 +132,56 @@ export class OpenSSHImporter extends SSHProfileImporter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class StaticFileImporter extends SSHProfileImporter {
|
||||
private configPath: string
|
||||
|
||||
constructor (
|
||||
electron: ElectronService,
|
||||
) {
|
||||
super()
|
||||
this.configPath = path.join(electron.app.getPath('userData'), 'ssh-profiles.yaml')
|
||||
}
|
||||
|
||||
async getProfiles (): Promise<PartialProfile<SSHProfile>[]> {
|
||||
const deriveID = name => 'file-config:' + slugify(name)
|
||||
|
||||
if (!fsSync.existsSync(this.configPath)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const content = await fs.readFile(this.configPath, 'utf8')
|
||||
if (!content) {
|
||||
return []
|
||||
}
|
||||
|
||||
return (yaml.load(content) as PartialProfile<SSHProfile>[]).map(item => ({
|
||||
...item,
|
||||
id: deriveID(item.name),
|
||||
type: 'ssh',
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PrivateKeyLocator extends AutoPrivateKeyLocator {
|
||||
async getKeys (): Promise<[string, Buffer][]> {
|
||||
const results: [string, Buffer][] = []
|
||||
const keysPath = path.join(process.env.HOME!, '.ssh')
|
||||
if (!fsSync.existsSync(keysPath)) {
|
||||
return results
|
||||
}
|
||||
for (const file of await fs.readdir(keysPath)) {
|
||||
if (/^id_[\w\d]+$/.test(file)) {
|
||||
const privateKeyContents = await fs.readFile(
|
||||
path.join(keysPath, file),
|
||||
{ encoding: null }
|
||||
)
|
||||
results.push([file, privateKeyContents])
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
}
|
@@ -2,6 +2,11 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@colors/colors@1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
|
||||
|
||||
"@dabh/diagnostics@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
|
||||
@@ -11,10 +16,10 @@
|
||||
enabled "2.0.x"
|
||||
kuler "^2.0.0"
|
||||
|
||||
async@^3.1.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
|
||||
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
|
||||
async@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9"
|
||||
integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
@@ -70,11 +75,6 @@ color@3.0.x:
|
||||
color-convert "^1.9.1"
|
||||
color-string "^1.5.2"
|
||||
|
||||
colors@^1.2.1:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
colorspace@1.1.x:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
|
||||
@@ -88,11 +88,6 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
define-properties@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
@@ -146,11 +141,6 @@ es-to-primitive@^1.2.1:
|
||||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
fast-safe-stringify@^2.0.4:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
|
||||
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
|
||||
|
||||
fecha@^4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce"
|
||||
@@ -217,7 +207,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3, inherits@~2.0.3:
|
||||
inherits@2, inherits@^2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@@ -289,25 +279,20 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||
dependencies:
|
||||
has-symbols "^1.0.2"
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
kuler@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
|
||||
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
|
||||
|
||||
logform@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
|
||||
integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==
|
||||
logform@^2.3.2, logform@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe"
|
||||
integrity sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw==
|
||||
dependencies:
|
||||
colors "^1.2.1"
|
||||
fast-safe-stringify "^2.0.4"
|
||||
"@colors/colors" "1.5.0"
|
||||
fecha "^4.2.0"
|
||||
ms "^2.1.1"
|
||||
safe-stable-stringify "^2.3.1"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
@@ -371,25 +356,7 @@ path-is-absolute@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
readable-stream@^2.3.7:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.4.0:
|
||||
readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
@@ -405,16 +372,16 @@ rimraf@^3.0.0:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
safe-stable-stringify@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73"
|
||||
integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==
|
||||
|
||||
serialize-error@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac"
|
||||
@@ -457,13 +424,6 @@ string_decoder@^1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
text-hex@1.0.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
|
||||
@@ -483,7 +443,7 @@ tmp@^0.2.0:
|
||||
dependencies:
|
||||
rimraf "^3.0.0"
|
||||
|
||||
triple-beam@^1.2.0, triple-beam@^1.3.0:
|
||||
triple-beam@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
|
||||
@@ -503,7 +463,7 @@ unbox-primitive@^1.0.0:
|
||||
has-symbols "^1.0.2"
|
||||
which-boxed-primitive "^1.0.2"
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
@@ -524,28 +484,30 @@ which-boxed-primitive@^1.0.2:
|
||||
is-string "^1.0.5"
|
||||
is-symbol "^1.0.3"
|
||||
|
||||
winston-transport@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
|
||||
integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
|
||||
winston-transport@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa"
|
||||
integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==
|
||||
dependencies:
|
||||
readable-stream "^2.3.7"
|
||||
triple-beam "^1.2.0"
|
||||
logform "^2.3.2"
|
||||
readable-stream "^3.6.0"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
winston@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
|
||||
integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/winston/-/winston-3.6.0.tgz#be32587a099a292b88c49fac6fa529d478d93fb6"
|
||||
integrity sha512-9j8T75p+bcN6D00sF/zjFVmPp+t8KMPB1MzbbzYjeN9VWxdsYnTB40TkbNUEXAmILEfChMvAMgidlX64OG3p6w==
|
||||
dependencies:
|
||||
"@dabh/diagnostics" "^2.0.2"
|
||||
async "^3.1.0"
|
||||
async "^3.2.3"
|
||||
is-stream "^2.0.0"
|
||||
logform "^2.2.0"
|
||||
logform "^2.4.0"
|
||||
one-time "^1.0.0"
|
||||
readable-stream "^3.4.0"
|
||||
safe-stable-stringify "^2.3.1"
|
||||
stack-trace "0.0.x"
|
||||
triple-beam "^1.3.0"
|
||||
winston-transport "^4.4.0"
|
||||
winston-transport "^4.5.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-linkifier",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Makes URLs, IPs and file paths clickable in Tabby",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-local",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Tabby's local shell plugin",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||
import { Component, Input, Injector } from '@angular/core'
|
||||
import { BaseTabProcess, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild, GetRecoveryTokenOptions } from 'tabby-core'
|
||||
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
||||
@@ -109,12 +110,12 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
||||
{
|
||||
type: 'warning',
|
||||
message: this.translate.instant(
|
||||
'"{command}" is still running. Close?',
|
||||
_('"{command}" is still running. Close?'),
|
||||
children[0],
|
||||
),
|
||||
buttons: [
|
||||
this.translate.instant('Kill'),
|
||||
this.translate.instant('Cancel'),
|
||||
this.translate.instant(_('Kill')),
|
||||
this.translate.instant(_('Cancel')),
|
||||
],
|
||||
defaultId: 0,
|
||||
cancelId: 1,
|
||||
|
@@ -8,8 +8,8 @@ export class DockMenuService {
|
||||
appVersion: string
|
||||
|
||||
private constructor (
|
||||
config: ConfigService,
|
||||
private electron: ElectronService,
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
private zone: NgZone,
|
||||
private profilesService: ProfilesService,
|
||||
@@ -18,29 +18,45 @@ export class DockMenuService {
|
||||
config.changed$.subscribe(() => this.update())
|
||||
}
|
||||
|
||||
update (): void {
|
||||
async update (): Promise<void> {
|
||||
const profiles = await this.profilesService.getProfiles()
|
||||
|
||||
if (this.hostApp.platform === Platform.Windows) {
|
||||
this.electron.app.setJumpList(this.config.store.profiles.length ? [{
|
||||
type: 'custom',
|
||||
name: this.translate.instant('Profiles'),
|
||||
items: this.config.store.profiles.map(profile => ({
|
||||
type: 'task',
|
||||
program: process.execPath,
|
||||
args: `profile "${profile.name}"`,
|
||||
title: profile.name,
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
})),
|
||||
}] : null)
|
||||
this.electron.app.setJumpList([
|
||||
{
|
||||
type: 'custom',
|
||||
name: this.translate.instant('Recent'),
|
||||
items: this.profilesService.getRecentProfiles().map((profile, index) => ({
|
||||
type: 'task',
|
||||
program: process.execPath,
|
||||
args: `recent ${index}`,
|
||||
title: profile.name,
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
})),
|
||||
},
|
||||
{
|
||||
type: 'custom',
|
||||
name: this.translate.instant('Profiles'),
|
||||
items: profiles.map(profile => ({
|
||||
type: 'task',
|
||||
program: process.execPath,
|
||||
args: `profile "${profile.name}"`,
|
||||
title: profile.name,
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
})),
|
||||
},
|
||||
])
|
||||
}
|
||||
if (this.hostApp.platform === Platform.macOS) {
|
||||
this.electron.app.dock.setMenu(this.electron.Menu.buildFromTemplate(
|
||||
this.config.store.profiles.map(profile => ({
|
||||
[...this.profilesService.getRecentProfiles(), ...profiles].map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
this.profilesService.openNewTabForProfile(profile)
|
||||
}),
|
||||
}))
|
||||
})),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,14 @@ export class POSIXShellsProvider extends ShellProvider {
|
||||
if (this.hostApp.platform === Platform.Windows) {
|
||||
return []
|
||||
}
|
||||
return (await fs.readFile('/etc/shells', { encoding: 'utf-8' }))
|
||||
let shellListPath = '/etc/shells'
|
||||
try {
|
||||
await fs.stat(shellListPath)
|
||||
} catch {
|
||||
// Solus Linux
|
||||
shellListPath = '/usr/share/defaults/etc/shells'
|
||||
}
|
||||
return (await fs.readFile(shellListPath, { encoding: 'utf-8' }))
|
||||
.split('\n')
|
||||
.map(x => x.trim())
|
||||
.filter(x => x && !x.startsWith('#'))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-plugin-manager",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Tabby's plugin manager",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -5,7 +5,10 @@
|
||||
span(translate) Plugins folder
|
||||
|
||||
.alert.alert-danger(*ngIf='errorMessage')
|
||||
strong {{ 'Error in {plugin}:'|translate:{plugin: erroredPlugin} }}
|
||||
strong(
|
||||
translate='Error in {plugin}:',
|
||||
[translateParams]='{plugin: erroredPlugin}'
|
||||
)
|
||||
pre {{errorMessage}}
|
||||
|
||||
ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
|
||||
@@ -75,7 +78,10 @@ ul.nav-tabs.mb-2(ngbNav, #nav='ngbNav')
|
||||
)
|
||||
i.fas.fa-fw.fa-arrow-up(*ngIf='busy.get(plugin.name) != BusyState.Installing')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Installing')
|
||||
span {{ 'Upgrade to {version}'|translate:{version: knownUpgrades[plugin.name].version} }}
|
||||
span(
|
||||
translate='Upgrade to {version}',
|
||||
[translateParams]='{version: knownUpgrades[plugin.name].version}'
|
||||
)
|
||||
|
||||
ng-template(ngbPanelContent)
|
||||
.row
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-serial",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Serial connections for Tabby",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
@@ -18,8 +18,7 @@
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "14.14.14",
|
||||
"ansi-colors": "^4.1.1",
|
||||
"serialport-binding-webserialapi": "^1.0.3"
|
||||
"ansi-colors": "^4.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": "^9.1.9",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import stripAnsi from 'strip-ansi'
|
||||
import SerialPort from 'serialport'
|
||||
import { SerialPortStream } from '@serialport/stream'
|
||||
import { LogService, NotificationsService, Profile } from 'tabby-core'
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
import { Injector, NgZone } from '@angular/core'
|
||||
@@ -41,7 +41,7 @@ class SlowFeedMiddleware extends SessionMiddleware {
|
||||
}
|
||||
|
||||
export class SerialSession extends BaseSession {
|
||||
serial: SerialPort
|
||||
serial: SerialPortStream|null
|
||||
|
||||
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
||||
private serviceMessage = new Subject<string>()
|
||||
@@ -72,11 +72,13 @@ export class SerialSession extends BaseSession {
|
||||
this.profile.options.port = (await this.serialService.listPorts())[0].name
|
||||
}
|
||||
|
||||
this.serial = new SerialPort(this.profile.options.port, {
|
||||
const serial = this.serial = new SerialPortStream({
|
||||
binding: this.serialService.detectBinding(),
|
||||
path: this.profile.options.port,
|
||||
autoOpen: false,
|
||||
baudRate: parseInt(this.profile.options.baudrate as any),
|
||||
dataBits: this.profile.options.databits ?? 8,
|
||||
stopBits: this.profile.options.stopbits ?? 1,
|
||||
dataBits: this.profile.options.databits ?? 8 as any,
|
||||
stopBits: this.profile.options.stopbits ?? 1 as any,
|
||||
parity: this.profile.options.parity ?? 'none',
|
||||
rtscts: this.profile.options.rtscts ?? false,
|
||||
xon: this.profile.options.xon ?? false,
|
||||
@@ -85,27 +87,27 @@ export class SerialSession extends BaseSession {
|
||||
})
|
||||
let connected = false
|
||||
await new Promise(async (resolve, reject) => {
|
||||
this.serial.on('open', () => {
|
||||
serial.on('open', () => {
|
||||
connected = true
|
||||
this.zone.run(resolve)
|
||||
})
|
||||
this.serial.on('error', error => {
|
||||
serial.on('error', error => {
|
||||
this.zone.run(() => {
|
||||
if (connected) {
|
||||
this.notifications.error(error.toString())
|
||||
this.notifications.error(error.message)
|
||||
} else {
|
||||
reject(error)
|
||||
}
|
||||
this.destroy()
|
||||
})
|
||||
})
|
||||
this.serial.on('close', () => {
|
||||
serial.on('close', () => {
|
||||
this.emitServiceMessage('Port closed')
|
||||
this.destroy()
|
||||
})
|
||||
|
||||
try {
|
||||
this.serial.open()
|
||||
serial.open()
|
||||
} catch (e) {
|
||||
this.notifications.error(e.message)
|
||||
reject(e)
|
||||
@@ -115,11 +117,11 @@ export class SerialSession extends BaseSession {
|
||||
this.open = true
|
||||
setTimeout(() => this.streamProcessor.start())
|
||||
|
||||
this.serial.on('readable', () => {
|
||||
this.emitOutput(this.serial.read())
|
||||
serial.on('readable', () => {
|
||||
this.emitOutput(serial.read())
|
||||
})
|
||||
|
||||
this.serial.on('end', () => {
|
||||
serial.on('end', () => {
|
||||
this.logger.info('Shell session ended')
|
||||
if (this.open) {
|
||||
this.destroy()
|
||||
@@ -144,7 +146,7 @@ export class SerialSession extends BaseSession {
|
||||
}
|
||||
|
||||
kill (_?: string): void {
|
||||
this.serial.close()
|
||||
this.serial?.close()
|
||||
}
|
||||
|
||||
emitServiceMessage (msg: string): void {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||
import colors from 'ansi-colors'
|
||||
import { Component, Injector } from '@angular/core'
|
||||
import { first } from 'rxjs'
|
||||
@@ -68,12 +69,12 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
const session = new SerialSession(this.injector, this.profile)
|
||||
this.setSession(session)
|
||||
|
||||
this.startSpinner(this.translate.instant('Connecting'))
|
||||
this.startSpinner(this.translate.instant(_('Connecting')))
|
||||
|
||||
try {
|
||||
await this.session!.start()
|
||||
this.stopSpinner()
|
||||
session.emitServiceMessage(this.translate.instant('Port opened'))
|
||||
session.emitServiceMessage(this.translate.instant(_('Port opened')))
|
||||
} catch (e) {
|
||||
this.stopSpinner()
|
||||
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
|
||||
@@ -88,7 +89,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
this.session?.resize(this.size.columns, this.size.rows)
|
||||
})
|
||||
this.attachSessionHandler(this.session!.destroyed$, () => {
|
||||
this.write(this.translate.instant('Press any key to reconnect') + '\r\n')
|
||||
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
||||
this.input$.pipe(first()).subscribe(() => {
|
||||
if (!this.session?.open) {
|
||||
this.reconnect()
|
||||
@@ -114,7 +115,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
|
||||
async changeBaudRate () {
|
||||
const rate = await this.selector.show(
|
||||
this.translate.instant('Baud rate'),
|
||||
this.translate.instant(_('Baud rate')),
|
||||
BAUD_RATES.map(x => ({
|
||||
name: x.toString(), result: x,
|
||||
})),
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import slugify from 'slugify'
|
||||
import SerialPort from 'serialport'
|
||||
import WSABinding from 'serialport-binding-webserialapi'
|
||||
import deepClone from 'clone-deep'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ProfileProvider, NewTabParameters, SelectorService, HostAppService, Platform, TranslateService } from 'tabby-core'
|
||||
@@ -41,9 +39,6 @@ export class SerialProfilesService extends ProfileProvider<SerialProfile> {
|
||||
private translate: TranslateService,
|
||||
) {
|
||||
super()
|
||||
if (hostApp.platform === Platform.Web) {
|
||||
SerialPort.Binding = WSABinding
|
||||
}
|
||||
}
|
||||
|
||||
async getBuiltinProfiles (): Promise<SerialProfile[]> {
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import SerialPort from 'serialport'
|
||||
import { PartialProfile, ProfilesService } from 'tabby-core'
|
||||
import WSABinding from 'serialport-binding-webserialapi'
|
||||
import AbstractBinding from '@serialport/binding-abstract'
|
||||
import { autoDetect } from '@serialport/bindings-cpp'
|
||||
import { HostAppService, PartialProfile, Platform, ProfilesService } from 'tabby-core'
|
||||
import { SerialPortInfo, SerialProfile } from '../api'
|
||||
import { SerialTabComponent } from '../components/serialTab.component'
|
||||
|
||||
@@ -8,13 +10,23 @@ import { SerialTabComponent } from '../components/serialTab.component'
|
||||
export class SerialService {
|
||||
private constructor (
|
||||
private profilesService: ProfilesService,
|
||||
private hostApp: HostAppService,
|
||||
) { }
|
||||
|
||||
detectBinding (): typeof AbstractBinding {
|
||||
return this.hostApp.platform === Platform.Web ? WSABinding : autoDetect()
|
||||
}
|
||||
|
||||
async listPorts (): Promise<SerialPortInfo[]> {
|
||||
return (await SerialPort.list()).map(x => ({
|
||||
name: x.path,
|
||||
description: x.manufacturer || x.serialNumber ? `${x.manufacturer || ''} ${x.serialNumber || ''}` : undefined,
|
||||
}))
|
||||
try {
|
||||
return (await this.detectBinding().list()).map(x => ({
|
||||
name: x.path,
|
||||
description: `${x.manufacturer ?? ''} ${x.serialNumber ?? ''}`.trim() || undefined,
|
||||
}))
|
||||
} catch (err) {
|
||||
console.error('Failed to list serial ports', err)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
quickConnect (query: string): Promise<SerialTabComponent|null> {
|
||||
|
@@ -2,20 +2,6 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@serialport/binding-abstract@^9.0.2":
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-9.0.7.tgz#d2c7ecea0f100bdf20187bfc0d34ba90f5504e1e"
|
||||
integrity sha512-g1ncCMIG9rMsxo/28ObYmXZcHThlvtZygsCANmyMUuFS7SwXY4+PhcEnt2+ZcMkEDNRiOklT+ngtIVx5GGpt/A==
|
||||
dependencies:
|
||||
debug "^4.3.1"
|
||||
|
||||
"@serialport/stream@^9.0.2":
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-9.0.7.tgz#0bf023eb0233a714fcc5a86de09e381e466d9882"
|
||||
integrity sha512-c/h7HPAeFiryD9iTGlaSvPqHFHSZ0NMQHxC4rcmKS2Vu3qJuEtkBdTLABwsMp7iWEiSnI4KC3s7bHapaXP06FQ==
|
||||
dependencies:
|
||||
debug "^4.3.1"
|
||||
|
||||
"@types/node@14.14.14":
|
||||
version "14.14.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
|
||||
@@ -25,23 +11,3 @@ 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==
|
||||
|
||||
debug@^4.3.1:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
serialport-binding-webserialapi@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/serialport-binding-webserialapi/-/serialport-binding-webserialapi-1.0.3.tgz#cf4348c075da2de8f6cf9936c0b95645f3ae657b"
|
||||
integrity sha512-TS7dsvetVoTeiWlzpsT/akjtljiYPO56FoJWSFyJSoO/E8icYJ2neQ7CW5NW/sHZDnMqAxULyAny47UFhWz9oQ==
|
||||
dependencies:
|
||||
"@serialport/binding-abstract" "^9.0.2"
|
||||
"@serialport/stream" "^9.0.2"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-settings",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "Tabby terminal settings page",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
@@ -17,6 +17,7 @@
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/marked": "^4.0.2",
|
||||
"marked": "^4.0.8",
|
||||
"ngx-infinite-scroll": "^10.0.1"
|
||||
},
|
||||
|
@@ -59,7 +59,10 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
i.fas.fa-fw.fa-file
|
||||
.ml-2.d-flex.flex-column.align-items-start
|
||||
div {{cfg.name}}
|
||||
small.text-muted {{ 'Modified on {date}'|translate:{date: cfg.modified_at|date:"medium"} }}
|
||||
small.text-muted(
|
||||
translate='Modified on {date}',
|
||||
[translateParams]='{date: cfg.modified_at|date:"medium"}'
|
||||
)
|
||||
.mr-auto
|
||||
button.btn.btn-link.ml-1(
|
||||
(click)='uploadAndSync(cfg)',
|
||||
|
@@ -2,7 +2,10 @@
|
||||
h3.m-0 {{profile.name}}
|
||||
|
||||
.modal-header(*ngIf='defaultsMode')
|
||||
h3.m-0 {{ 'Defaults for {type}'|translate:{type: profileProvider.name} }}
|
||||
h3.m-0(
|
||||
translate='Defaults for {type}',
|
||||
[translateParams]='{type: profileProvider.name}'
|
||||
)
|
||||
|
||||
.modal-body
|
||||
.row
|
||||
|
@@ -21,7 +21,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
[ngValue]='profile.id'
|
||||
) {{profile.name}}
|
||||
|
||||
.d-flex.mb-3.mt-4
|
||||
.d-flex.mb-3
|
||||
.input-group
|
||||
.input-group-prepend
|
||||
.input-group-text
|
||||
@@ -68,8 +68,8 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
*ngIf='iconIsSVG(profile.icon)'
|
||||
)
|
||||
|
||||
div {{profile.name}}
|
||||
.text-muted.ml-2 {{getDescription(profile)}}
|
||||
.no-wrap {{profile.name}}
|
||||
.text-muted.no-wrap.ml-2 {{getDescription(profile)}}
|
||||
|
||||
.mr-auto
|
||||
|
||||
@@ -90,7 +90,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
li(ngbNavItem)
|
||||
a(ngbNavLink, translate) Advanced
|
||||
ng-template(ngbNavContent)
|
||||
.form-line(*ngIf='config.store.profiles.length > 0')
|
||||
.form-line.content-box(*ngIf='config.store.profiles.length > 0')
|
||||
.header
|
||||
.title(translate) Show recent profiles in selector
|
||||
.description(translate) Set to 0 to disable recent profiles
|
||||
@@ -103,7 +103,7 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
(ngModelChange)='config.save()'
|
||||
)
|
||||
|
||||
.form-line(*ngIf='config.store.profiles.length > 0')
|
||||
.form-line.content-box(*ngIf='config.store.profiles.length > 0')
|
||||
.header
|
||||
.title(translate) Show built-in profiles in selector
|
||||
.description(translate) If disabled, only custom profiles will show up in the profile selector
|
||||
@@ -113,12 +113,12 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
(ngModelChange)='config.save()'
|
||||
)
|
||||
|
||||
.form-line
|
||||
.form-line.content-box
|
||||
.header
|
||||
.title(translate) Default profile settings
|
||||
.description(translate) These apply to all profiles of a given type
|
||||
|
||||
.list-group.mt-3.mb-3
|
||||
.list-group.mt-3.mb-3.content-box
|
||||
a.list-group-item.list-group-item-action(
|
||||
(click)='editDefaults(provider)',
|
||||
*ngFor='let provider of profileProviders'
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import slugify from 'slugify'
|
||||
import deepClone from 'clone-deep'
|
||||
import { Component, HostBinding, Inject } from '@angular/core'
|
||||
import { Component, Inject } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService } from 'tabby-core'
|
||||
import { EditProfileModalComponent } from './editProfileModal.component'
|
||||
@@ -13,6 +14,8 @@ interface ProfileGroup {
|
||||
collapsed: boolean
|
||||
}
|
||||
|
||||
_('Ungrouped')
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
template: require('./profilesSettingsTab.component.pug'),
|
||||
@@ -25,8 +28,6 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
|
||||
profileGroups: ProfileGroup[]
|
||||
filter = ''
|
||||
|
||||
@HostBinding('class.content-box') true
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
public hostApp: HostAppService,
|
||||
@@ -197,7 +198,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
|
||||
if ((await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: this.translate.instant(`Delete the group's profiles?`),
|
||||
message: this.translate.instant('Delete the group\'s profiles?'),
|
||||
buttons: [
|
||||
this.translate.instant('Move to "Ungrouped"'),
|
||||
this.translate.instant('Delete'),
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||
import axios from 'axios'
|
||||
import { marked } from 'marked'
|
||||
import { Component } from '@angular/core'
|
||||
@@ -23,7 +24,7 @@ export class ReleaseNotesComponent extends BaseTabComponent {
|
||||
|
||||
constructor (translate: TranslateService) {
|
||||
super()
|
||||
this.setTitle(translate.instant('Release notes'))
|
||||
this.setTitle(translate.instant(_('Release notes')))
|
||||
this.loadReleases(1)
|
||||
}
|
||||
|
||||
|
@@ -73,8 +73,8 @@
|
||||
option([ngValue]='null', translate) Automatic
|
||||
option(
|
||||
[value]='lang.code',
|
||||
*ngFor='let lang of locale.allLanguages'
|
||||
) {{lang.name|translate}}
|
||||
*ngFor='let lang of allLanguages'
|
||||
) {{lang.name}}
|
||||
|
||||
.form-line(*ngIf='platform.isShellIntegrationSupported()')
|
||||
.header
|
||||
@@ -107,9 +107,9 @@
|
||||
|
||||
ng-container(*ngFor='let provider of settingsProviders')
|
||||
li(*ngIf='provider.prioritized', [ngbNavItem]='provider.id')
|
||||
a(ngbNavLink)
|
||||
a.d-flex.align-items-center(ngbNavLink)
|
||||
i(class='fas fa-fw mr-2 fa-{{provider.icon}}')
|
||||
span(translate) {{provider.title}}
|
||||
span {{provider.title|translate}}
|
||||
ng-template(ngbNavContent)
|
||||
settings-tab-body([provider]='provider')
|
||||
|
||||
@@ -117,14 +117,14 @@
|
||||
|
||||
ng-container(*ngFor='let provider of settingsProviders')
|
||||
li(*ngIf='!provider.prioritized', [ngbNavItem]='provider.id')
|
||||
a(ngbNavLink)
|
||||
a.d-flex.align-items-center(ngbNavLink)
|
||||
i(class='fas fa-fw mr-2 fa-{{provider.icon || "puzzle-piece"}}')
|
||||
span(translate) {{provider.title}}
|
||||
span {{provider.title|translate}}
|
||||
ng-template(ngbNavContent)
|
||||
settings-tab-body([provider]='provider')
|
||||
|
||||
li(ngbNavItem='config-file')
|
||||
a(ngbNavLink)
|
||||
a.d-flex.align-items-center(ngbNavLink)
|
||||
i.fas.fa-fw.fa-code.mr-2
|
||||
span(translate) Config file
|
||||
ng-template.test(ngbNavContent)
|
||||
|
@@ -2,6 +2,7 @@
|
||||
display: flex;
|
||||
flex: auto;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
|
||||
>.btn-block {
|
||||
margin: 20px;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||
import * as yaml from 'js-yaml'
|
||||
import { debounce } from 'utils-decorators/dist/esm/debounce/debounce'
|
||||
import { Component, Inject, Input, HostBinding, NgZone } from '@angular/core'
|
||||
@@ -36,6 +37,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
||||
checkingForUpdate = false
|
||||
updateAvailable = false
|
||||
showConfigDefaults = false
|
||||
allLanguages = LocaleService.allLanguages
|
||||
@HostBinding('class.pad-window-controls') padWindowControls = false
|
||||
|
||||
constructor (
|
||||
@@ -52,7 +54,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
||||
translate: TranslateService,
|
||||
) {
|
||||
super()
|
||||
this.setTitle(translate.instant('Settings'))
|
||||
this.setTitle(translate.instant(_('Settings')))
|
||||
this.settingsProviders = config.enabledServices(this.settingsProviders)
|
||||
this.settingsProviders = this.settingsProviders.filter(x => !!x.getComponentType())
|
||||
this.settingsProviders.sort((a, b) => a.weight - b.weight + a.title.localeCompare(b.title))
|
||||
@@ -112,7 +114,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
||||
try {
|
||||
yaml.load(this.configFile)
|
||||
return true
|
||||
} catch (_) {
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@@ -268,7 +268,7 @@ h3.mt-4(translate) Tabs
|
||||
ngbButton,
|
||||
[value]='true'
|
||||
)
|
||||
span(translate) Dynamic
|
||||
span(translate, translateComment='[Dynamic] tab width') id.tab-width.dynamic
|
||||
label.btn.btn-secondary(ngbButtonLabel)
|
||||
input(
|
||||
type='radio',
|
||||
@@ -286,6 +286,15 @@ h3.mt-4(translate) Tabs
|
||||
(ngModelChange)='config.save();',
|
||||
)
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title(translate) Show profile icon on tab
|
||||
|
||||
toggle(
|
||||
[(ngModel)]='config.store.terminal.showTabProfileIcon',
|
||||
(ngModelChange)='config.save();',
|
||||
)
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title(translate) Hide tab close button
|
||||
@@ -295,7 +304,7 @@ h3.mt-4(translate) Tabs
|
||||
(ngModelChange)='config.save();',
|
||||
)
|
||||
|
||||
h3.mt-4 Hacks
|
||||
h3.mt-4(translate) Hacks
|
||||
|
||||
.form-line
|
||||
.header
|
||||
|
@@ -14,6 +14,11 @@ export class SettingsConfigProvider extends ConfigProvider {
|
||||
vault: true,
|
||||
},
|
||||
},
|
||||
hotkeys: {
|
||||
'settings-tab': {
|
||||
__nonStructural: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
platformDefaults = {
|
||||
[Platform.macOS]: {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Inject, Injectable } from '@angular/core'
|
||||
import { HotkeyDescription, HotkeyProvider, TranslateService } from 'tabby-core'
|
||||
import { SettingsTabProvider } from './api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
@@ -11,9 +12,18 @@ export class SettingsHotkeyProvider extends HotkeyProvider {
|
||||
},
|
||||
]
|
||||
|
||||
constructor (private translate: TranslateService) { super() }
|
||||
constructor (
|
||||
private translate: TranslateService,
|
||||
@Inject(SettingsTabProvider) private settingsProviders: SettingsTabProvider[],
|
||||
) { super() }
|
||||
|
||||
async provide (): Promise<HotkeyDescription[]> {
|
||||
return this.hotkeys
|
||||
return [
|
||||
...this.hotkeys,
|
||||
...this.settingsProviders.map(provider => ({
|
||||
id: `settings-tab.${provider.id}`,
|
||||
name: this.translate.instant('Open settings tab: {tab}', { tab: provider.title }),
|
||||
})),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll'
|
||||
|
||||
import TabbyCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider } from 'tabby-core'
|
||||
import TabbyCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider, HotkeysService, AppService } from 'tabby-core'
|
||||
|
||||
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
||||
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
|
||||
@@ -74,7 +74,21 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabP
|
||||
],
|
||||
})
|
||||
export default class SettingsModule {
|
||||
constructor (public configSync: ConfigSyncService) { }
|
||||
constructor (
|
||||
public configSync: ConfigSyncService,
|
||||
app: AppService,
|
||||
hotkeys: HotkeysService,
|
||||
) {
|
||||
hotkeys.hotkey$.subscribe(async hotkey => {
|
||||
if (hotkey.startsWith('settings-tab.')) {
|
||||
const id = hotkey.substring(hotkey.indexOf('.') + 1)
|
||||
app.openNewTabRaw({
|
||||
type: SettingsTabComponent,
|
||||
inputs: { activeTab: id },
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export * from './api'
|
||||
|
@@ -7,10 +7,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.1.1.tgz#d8b9f20037b3a37dbf8dcdc4b3b72f9285bfce35"
|
||||
integrity sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ==
|
||||
|
||||
"@types/marked@^4.0.2":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.2.tgz#cb2dbf10da2f41cf20bd91fb5f89b67540c282f7"
|
||||
integrity sha512-auNrZ/c0w6wsM9DccwVxWHssrMDezHUAXNesdp2RQrCVCyrQbOiSq7yqdJKrUQQpw9VTm7CGYJH2A/YG7jjrjQ==
|
||||
|
||||
marked@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.8.tgz#ef127626ac65786460f9420d57cc8d5ffdcacbed"
|
||||
integrity sha512-dkpJMIlJpc833hbjjg8jraw1t51e/eKDoG8TFOgc5O0Z77zaYKigYekTDop5AplRoKFGIaoazhYEhGkMtU3IeA==
|
||||
version "4.0.12"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
|
||||
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
|
||||
|
||||
ngx-infinite-scroll@^10.0.1:
|
||||
version "10.0.1"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabby-ssh",
|
||||
"version": "1.0.170-nightly.0",
|
||||
"version": "1.0.171-nightly.3",
|
||||
"description": "SSH connections for Tabby",
|
||||
"keywords": [
|
||||
"tabby-builtin-plugin"
|
||||
|
@@ -4,3 +4,7 @@ import { SSHProfile } from './interfaces'
|
||||
export abstract class SSHProfileImporter {
|
||||
abstract getProfiles (): Promise<PartialProfile<SSHProfile>[]>
|
||||
}
|
||||
|
||||
export abstract class AutoPrivateKeyLocator {
|
||||
abstract getKeys (): Promise<[string, Buffer][]>
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
export * from './contextMenu'
|
||||
export * from './interfaces'
|
||||
export * from './importer'
|
||||
export * from './proxyStream'
|
||||
|
@@ -32,6 +32,8 @@ export interface SSHProfileOptions extends LoginScriptsOptions {
|
||||
forwardedPorts?: ForwardedPortConfig[]
|
||||
socksProxyHost?: string
|
||||
socksProxyPort?: number
|
||||
httpProxyHost?: string
|
||||
httpProxyPort?: number
|
||||
reuseSession?: boolean
|
||||
}
|
||||
|
||||
|
61
tabby-ssh/src/api/proxyStream.ts
Normal file
61
tabby-ssh/src/api/proxyStream.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { Duplex } from 'stream'
|
||||
|
||||
export class SSHProxyStreamSocket extends Duplex {
|
||||
constructor (private parent: SSHProxyStream) {
|
||||
super({
|
||||
allowHalfOpen: false,
|
||||
})
|
||||
}
|
||||
|
||||
_read (size: number): void {
|
||||
this.parent.requestData(size)
|
||||
}
|
||||
|
||||
_write (chunk: Buffer, _encoding: string, callback: (error?: Error | null) => void): void {
|
||||
this.parent.consumeInput(chunk).then(() => callback(null), e => callback(e))
|
||||
}
|
||||
|
||||
_destroy (error: Error|null, callback: (error: Error|null) => void): void {
|
||||
this.parent.handleStopRequest(error).then(() => callback(null), e => callback(e))
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class SSHProxyStream {
|
||||
get message$ (): Observable<string> { return this.message }
|
||||
get destroyed$ (): Observable<Error|null> { return this.destroyed }
|
||||
get socket (): SSHProxyStreamSocket|null { return this._socket }
|
||||
private message = new Subject<string>()
|
||||
private destroyed = new Subject<Error|null>()
|
||||
private _socket: SSHProxyStreamSocket|null = null
|
||||
|
||||
async start (): Promise<SSHProxyStreamSocket> {
|
||||
if (!this._socket) {
|
||||
this._socket = new SSHProxyStreamSocket(this)
|
||||
}
|
||||
return this._socket
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
abstract requestData (size: number): void
|
||||
|
||||
abstract consumeInput (data: Buffer): Promise<void>
|
||||
|
||||
protected emitMessage (message: string): void {
|
||||
this.message.next(message)
|
||||
}
|
||||
|
||||
protected emitOutput (data: Buffer): void {
|
||||
this._socket?.push(data)
|
||||
}
|
||||
|
||||
async handleStopRequest (error: Error|null): Promise<void> {
|
||||
this.destroyed.next(error)
|
||||
this.destroyed.complete()
|
||||
this.message.complete()
|
||||
}
|
||||
|
||||
stop (error?: Error): void {
|
||||
this._socket?.destroy(error)
|
||||
}
|
||||
}
|
@@ -32,8 +32,8 @@ export class HostKeyPromptModalComponent {
|
||||
this.modalInstance.close(true)
|
||||
}
|
||||
|
||||
acceptAndSave () {
|
||||
this.knownHosts.store(this.selector, this.digest)
|
||||
async acceptAndSave () {
|
||||
await this.knownHosts.store(this.selector, this.digest)
|
||||
this.accept()
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import * as C from 'constants'
|
||||
import { posix as path } from 'path'
|
||||
import { Component, Input, Output, EventEmitter, Inject, Optional } from '@angular/core'
|
||||
import { FileUpload, MenuItemOptions, PlatformService } from 'tabby-core'
|
||||
import { FileUpload, MenuItemOptions, NotificationsService, PlatformService } from 'tabby-core'
|
||||
import { SFTPSession, SFTPFile } from '../session/sftp'
|
||||
import { SSHSession } from '../session/ssh'
|
||||
import { SFTPContextMenuItemProvider } from '../api'
|
||||
@@ -27,6 +27,7 @@ export class SFTPPanelComponent {
|
||||
|
||||
constructor (
|
||||
private platform: PlatformService,
|
||||
private notifications: NotificationsService,
|
||||
@Optional() @Inject(SFTPContextMenuItemProvider) protected contextMenuProviders: SFTPContextMenuItemProvider[],
|
||||
) {
|
||||
this.contextMenuProviders.sort((a, b) => a.weight - b.weight)
|
||||
@@ -38,11 +39,13 @@ export class SFTPPanelComponent {
|
||||
await this.navigate(this.path)
|
||||
} catch (error) {
|
||||
console.warn('Could not navigate to', this.path, ':', error)
|
||||
this.notifications.error(error.message)
|
||||
await this.navigate('/')
|
||||
}
|
||||
}
|
||||
|
||||
async navigate (newPath: string): Promise<void> {
|
||||
async navigate (newPath: string, fallbackOnError = true): Promise<void> {
|
||||
const previousPath = this.path
|
||||
this.path = newPath
|
||||
this.pathChange.next(this.path)
|
||||
|
||||
@@ -57,7 +60,15 @@ export class SFTPPanelComponent {
|
||||
}
|
||||
|
||||
this.fileList = null
|
||||
this.fileList = await this.sftp.readdir(this.path)
|
||||
try {
|
||||
this.fileList = await this.sftp.readdir(this.path)
|
||||
} catch (error) {
|
||||
this.notifications.error(error.message)
|
||||
if (previousPath && fallbackOnError) {
|
||||
this.navigate(previousPath, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const dirKey = a => a.isDirectory ? 1 : 0
|
||||
this.fileList.sort((a, b) =>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
.ms-2.d-flex.align-items-center
|
||||
strong(*ngIf='fw.type === PortForwardType.Local', translate) Local
|
||||
strong(*ngIf='fw.type === PortForwardType.Remote', translate) Remote
|
||||
strong(*ngIf='fw.type === PortForwardType.Dynamic', translate) Dynamic
|
||||
strong(*ngIf='fw.type === PortForwardType.Dynamic', translate, translateContext='[Dynamic] port forwarding') id.port-forwarding.dynamic
|
||||
.ml-3 {{fw.host}}:{{fw.port}}
|
||||
.ml-2 →
|
||||
.ml-2(*ngIf='fw.type !== PortForwardType.Dynamic') {{fw.targetAddress}}:{{fw.targetPort}}
|
||||
@@ -64,7 +64,7 @@ h5(translate) Add a port forward
|
||||
ngbButton,
|
||||
[value]='PortForwardType.Dynamic'
|
||||
)
|
||||
span(translate) Dynamic
|
||||
span(translate, translateContext='[Dynamic] port forwarding') id.port-forwarding.dynamic
|
||||
|
||||
button.btn.btn-primary((click)='addForward()')
|
||||
i.fas.fa-check.mr-2
|
||||
|
@@ -29,6 +29,11 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
)
|
||||
div(translate) SOCKS proxy
|
||||
.text-muted(translate) Connect through a proxy server
|
||||
button.dropdown-item(
|
||||
(click)='connectionMode = "httpProxy"',
|
||||
)
|
||||
div(translate) HTTP proxy
|
||||
.text-muted(translate) Using CONNECT method
|
||||
|
||||
.form-group.w-100(*ngIf='connectionMode === "proxyCommand"')
|
||||
label(translate) Proxy command
|
||||
@@ -75,6 +80,22 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
[(ngModel)]='profile.options.socksProxyPort',
|
||||
)
|
||||
|
||||
.d-flex.w-100(*ngIf='connectionMode === "httpProxy"')
|
||||
.form-group.w-100.mr-2
|
||||
label(translate) HTTP proxy host
|
||||
input.form-control(
|
||||
type='text',
|
||||
[(ngModel)]='profile.options.httpProxyHost',
|
||||
)
|
||||
|
||||
.form-group
|
||||
label(translate) HTTP proxy port
|
||||
input.form-control(
|
||||
type='number',
|
||||
placeholder='5000',
|
||||
[(ngModel)]='profile.options.httpProxyPort',
|
||||
)
|
||||
|
||||
.form-group
|
||||
label(translate) Username
|
||||
input.form-control(
|
||||
|
@@ -17,7 +17,7 @@ export class SSHProfileSettingsComponent {
|
||||
profile: SSHProfile
|
||||
hasSavedPassword: boolean
|
||||
|
||||
connectionMode: 'direct'|'proxyCommand'|'jumpHost'|'socksProxy' = 'direct'
|
||||
connectionMode: 'direct'|'proxyCommand'|'jumpHost'|'socksProxy'|'httpProxy' = 'direct'
|
||||
|
||||
supportedAlgorithms = supportedAlgorithms
|
||||
algorithms: Record<string, Record<string, boolean>> = {}
|
||||
@@ -50,6 +50,8 @@ export class SSHProfileSettingsComponent {
|
||||
this.connectionMode = 'jumpHost'
|
||||
} else if (this.profile.options.socksProxyHost) {
|
||||
this.connectionMode = 'socksProxy'
|
||||
} else if (this.profile.options.httpProxyHost) {
|
||||
this.connectionMode = 'httpProxy'
|
||||
}
|
||||
|
||||
if (this.profile.options.user) {
|
||||
@@ -109,6 +111,10 @@ export class SSHProfileSettingsComponent {
|
||||
this.profile.options.socksProxyHost = undefined
|
||||
this.profile.options.socksProxyPort = undefined
|
||||
}
|
||||
if (this.connectionMode !== 'httpProxy') {
|
||||
this.profile.options.httpProxyHost = undefined
|
||||
this.profile.options.httpProxyPort = undefined
|
||||
}
|
||||
|
||||
this.loginScriptsSettings?.save()
|
||||
}
|
||||
@@ -128,6 +134,7 @@ export class SSHProfileSettingsComponent {
|
||||
proxyCommand: 'Proxy command',
|
||||
jumpHost: 'Jump host',
|
||||
socksProxy: 'SOCKS proxy',
|
||||
httpProxy: 'HTTP proxy',
|
||||
}[this.connectionMode]
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||
import colors from 'ansi-colors'
|
||||
import { Component, Injector, HostListener } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
@@ -140,7 +141,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
if (!session.open) {
|
||||
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ` Connecting to ${session.profile.options.host}\r\n`)
|
||||
|
||||
this.startSpinner(this.translate.instant('Connecting'))
|
||||
this.startSpinner(this.translate.instant(_('Connecting')))
|
||||
|
||||
try {
|
||||
await session.start()
|
||||
@@ -172,7 +173,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
this.write('\r\n' + colors.black.bgWhite(' SSH ') + ` ${this.sshSession?.profile.options.host}: session closed\r\n`)
|
||||
if (!this.reconnectOffered) {
|
||||
this.reconnectOffered = true
|
||||
this.write(this.translate.instant('Press any key to reconnect') + '\r\n')
|
||||
this.write(this.translate.instant(_('Press any key to reconnect')) + '\r\n')
|
||||
this.input$.pipe(first()).subscribe(() => {
|
||||
if (!this.session?.open && this.reconnectOffered) {
|
||||
this.reconnect()
|
||||
@@ -199,13 +200,12 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
}
|
||||
|
||||
const session = new SSHShellSession(this.injector, this.sshSession)
|
||||
|
||||
this.setSession(session)
|
||||
this.attachSessionHandler(session.serviceMessage$, msg => {
|
||||
this.write(`\r${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
|
||||
session.resize(this.size.columns, this.size.rows)
|
||||
})
|
||||
|
||||
this.setSession(session)
|
||||
await session.start()
|
||||
this.session?.resize(this.size.columns, this.size.rows)
|
||||
}
|
||||
@@ -239,10 +239,10 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
return (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: this.translate.instant('Disconnect from {host}?', this.profile?.options),
|
||||
message: this.translate.instant(_('Disconnect from {host}?'), this.profile?.options),
|
||||
buttons: [
|
||||
this.translate.instant('Disconnect'),
|
||||
this.translate.instant('Do not close'),
|
||||
this.translate.instant(_('Disconnect')),
|
||||
this.translate.instant(_('Do not close')),
|
||||
],
|
||||
defaultId: 0,
|
||||
cancelId: 1,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user