mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-23 09:41:55 +00:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
39732908a3 |
@@ -225,52 +225,6 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "LeSeulArtichaut",
|
||||
"name": "LeSeulArtichaut",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/38361244?v=4",
|
||||
"profile": "https://github.com/LeSeulArtichaut",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "CyrilTaylor",
|
||||
"name": "Cyril Taylor",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/12631466?v=4",
|
||||
"profile": "https://github.com/CyrilTaylor",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nstefanou",
|
||||
"name": "nstefanou",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/51129173?v=4",
|
||||
"profile": "https://github.com/nstefanou",
|
||||
"contributions": [
|
||||
"code",
|
||||
"plugin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "orin220444",
|
||||
"name": "orin220444",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/30747229?v=4",
|
||||
"profile": "https://github.com/orin220444",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Goobles",
|
||||
"name": "Gobius Dolhain",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/8776771?v=4",
|
||||
"profile": "https://github.com/Goobles",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
@@ -278,6 +232,5 @@
|
||||
"projectOwner": "Eugeny",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"commitConvention": "none",
|
||||
"skipCi": true
|
||||
"commitConvention": "none"
|
||||
}
|
||||
|
@@ -79,7 +79,6 @@ rules:
|
||||
args: after-used
|
||||
argsIgnorePattern: ^_
|
||||
no-undef: error
|
||||
no-var: error
|
||||
object-curly-spacing:
|
||||
- error
|
||||
- always
|
||||
@@ -99,8 +98,3 @@ rules:
|
||||
'@typescript-eslint/restrict-template-expressions': off
|
||||
'@typescript-eslint/no-dynamic-delete': off
|
||||
'@typescript-eslint/prefer-nullish-coalescing': off
|
||||
'@typescript-eslint/prefer-readonly-parameter-types': off
|
||||
'@typescript-eslint/no-unsafe-member-access': off
|
||||
'@typescript-eslint/no-unsafe-call': off
|
||||
'@typescript-eslint/no-unsafe-return': off
|
||||
'@typescript-eslint/no-base-to-string': off # broken in typescript-eslint
|
||||
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
version: 10
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
version: 10
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
|
5
.github/workflows/linux.yml
vendored
5
.github/workflows/linux.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
version: 10
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
@@ -25,6 +25,9 @@ jobs:
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
|
||||
- name: Build typings
|
||||
run: yarn run build:typings
|
||||
|
||||
- name: Webpack
|
||||
run: yarn run build
|
||||
|
||||
|
11
.github/workflows/macos.yml
vendored
11
.github/workflows/macos.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
version: 10
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
@@ -25,24 +25,23 @@ jobs:
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
|
||||
- name: Build typings
|
||||
run: yarn run build:typings
|
||||
|
||||
- name: Webpack
|
||||
run: yarn run build
|
||||
|
||||
- name: Prepackage plugins
|
||||
run: scripts/prepackage-plugins.js
|
||||
|
||||
- run: sed -i '' 's/updateInfo = await/\/\/updateInfo = await/g' node_modules/app-builder-lib/out/targets/ArchiveTarget.js
|
||||
|
||||
- name: Build and sign packages
|
||||
run: scripts/build-macos.js
|
||||
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
|
||||
env:
|
||||
#DEBUG: electron-builder,electron-builder:*
|
||||
DEBUG: electron-builder,electron-builder:*
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
CSC_LINK: ${{ secrets.CSC_LINK }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
||||
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
|
||||
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
|
||||
|
||||
- name: Build packages without signing
|
||||
run: scripts/build-macos.js
|
||||
|
4
.github/workflows/windows.yml
vendored
4
.github/workflows/windows.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
version: 10
|
||||
|
||||
- name: Build
|
||||
shell: powershell
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
mkdir artifact-setup
|
||||
mv dist/*-setup.exe artifact-setup/
|
||||
mkdir artifact-portable
|
||||
mv dist/*-portable.zip artifact-portable/
|
||||
mv dist/*-portable.exe artifact-portable/
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload installer
|
||||
|
68
README.md
68
README.md
@@ -13,13 +13,12 @@
|
||||
|
||||
**Terminus** is a highly configurable terminal emulator for Windows, macOS and Linux
|
||||
|
||||
* Integrated SSH client and connection manager
|
||||
* Theming and color schemes
|
||||
* Fully configurable shortcuts
|
||||
* Split panes
|
||||
* Remembers your tabs
|
||||
* PowerShell (and PS Core), WSL, Git-Bash, Cygwin, Cmder and CMD support
|
||||
* Direct file transfer from/to SSH sessions via Zmodem
|
||||
* Integrated SSH client and connection manager
|
||||
* Full Unicode support including double-width characters
|
||||
* Doesn't choke on fast-flowing outputs
|
||||
* Proper shell experience on Windows including tab completion (via Clink)
|
||||
@@ -35,15 +34,12 @@
|
||||
|
||||
---
|
||||
|
||||
# Portable
|
||||
|
||||
For portable in windows, user can create folder `data` at the same directory as `Terminal.exe` to save the settings.
|
||||
|
||||
# Plugins
|
||||
|
||||
Plugins and themes can be installed directly from the Settings view inside Terminus.
|
||||
|
||||
* [clickable-links](https://github.com/Eugeny/terminus-clickable-links) - makes paths and URLs in the terminal clickable
|
||||
* [shell-selector](https://github.com/Eugeny/terminus-shell-selector) - a quick shell selector pane
|
||||
* [title-control](https://github.com/kbjr/terminus-title-control) - allows modifying the title of the terminal tabs by providing a prefix, suffix, and/or strings to be removed
|
||||
* [quick-cmds](https://github.com/Domain/terminus-quick-cmds) - quickly send commands to one or all terminal tabs
|
||||
* [save-output](https://github.com/Eugeny/terminus-save-output) - record terminal output into a file
|
||||
@@ -70,52 +66,42 @@ See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) and
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<!-- prettier-ignore -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt="Russell Myers"/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt="Austin Warren"/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt="Felicia Hummel"/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt="Mike MacCana"/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt="Yacine Kanzari"/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt="BBJip"/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt="Futagirl"/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt="Levin Rickert"/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt="OJ Kwon"/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt="domain"/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt="James Brumond"/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt="Daniel Imms"/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt="Florian Bachmann"/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt="Michael Kühnel"/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt="Tilmann Meyer"/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt="PM Extra"/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt="Jonathan"/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt="Hans Koch"/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt="Dak Smyth"/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt="Wang Zhi"/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt="jack1142"/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt="Howie Douglas"/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt="Chris Kaczor"/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt="Johannes Kadak"/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
@@ -8,15 +8,17 @@ html
|
||||
window.nodeRequire = require
|
||||
script(src='./preload.js')
|
||||
script(src='./bundle.js', defer)
|
||||
style#custom-css
|
||||
style.
|
||||
body { transition: 0.5s background; }
|
||||
body
|
||||
style#custom-css
|
||||
app-root
|
||||
.preload-logo
|
||||
div
|
||||
.terminus-logo
|
||||
h1.terminus-title Terminus
|
||||
sup α
|
||||
sup α
|
||||
.progress
|
||||
.bar(style='width: 0%')
|
||||
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { app, ipcMain, Menu, Tray, shell, globalShortcut } from 'electron'
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { app, ipcMain, Menu, Tray, shell } from 'electron'
|
||||
import * as electron from 'electron'
|
||||
import { loadConfig } from './config'
|
||||
import { Window, WindowOptions } from './window'
|
||||
@@ -9,38 +8,25 @@ export class Application {
|
||||
private windows: Window[] = []
|
||||
|
||||
constructor () {
|
||||
ipcMain.on('app:config-change', (_event, config) => {
|
||||
this.broadcast('host:config-change', config)
|
||||
})
|
||||
|
||||
ipcMain.on('app:register-global-hotkey', (_event, specs) => {
|
||||
globalShortcut.unregisterAll()
|
||||
for (let spec of specs) {
|
||||
globalShortcut.register(spec, () => {
|
||||
this.onGlobalHotkey()
|
||||
})
|
||||
}
|
||||
ipcMain.on('app:config-change', () => {
|
||||
this.broadcast('host:config-change')
|
||||
})
|
||||
|
||||
const configData = loadConfig()
|
||||
if (process.platform === 'linux') {
|
||||
app.commandLine.appendSwitch('no-sandbox')
|
||||
if (((configData.appearance || {}).opacity || 1) !== 1) {
|
||||
app.commandLine.appendSwitch('enable-transparent-visuals')
|
||||
app.disableHardwareAcceleration()
|
||||
}
|
||||
if (process.platform === 'linux' && ((configData.appearance || {}).opacity || 1) !== 1) {
|
||||
app.commandLine.appendSwitch('enable-transparent-visuals')
|
||||
app.disableHardwareAcceleration()
|
||||
}
|
||||
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
app.commandLine.appendSwitch('lang', 'EN')
|
||||
app.allowRendererProcessReuse = false
|
||||
|
||||
for (const flag of configData.flags || [['force_discrete_gpu', '0']]) {
|
||||
app.commandLine.appendSwitch(flag[0], flag[1])
|
||||
}
|
||||
}
|
||||
|
||||
init (): void {
|
||||
init () {
|
||||
electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
|
||||
}
|
||||
|
||||
@@ -54,9 +40,6 @@ export class Application {
|
||||
this.enableTray()
|
||||
}
|
||||
})
|
||||
window.closed$.subscribe(() => {
|
||||
this.windows = this.windows.filter(x => x !== window)
|
||||
})
|
||||
if (process.platform === 'darwin') {
|
||||
this.setupMenu()
|
||||
}
|
||||
@@ -64,38 +47,20 @@ export class Application {
|
||||
return window
|
||||
}
|
||||
|
||||
onGlobalHotkey (): void {
|
||||
if (this.windows.some(x => x.isFocused())) {
|
||||
for (let window of this.windows) {
|
||||
window.hide()
|
||||
}
|
||||
} else {
|
||||
for (let window of this.windows) {
|
||||
window.present()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
presentAllWindows (): void {
|
||||
broadcast (event, ...args) {
|
||||
for (let window of this.windows) {
|
||||
window.present()
|
||||
}
|
||||
}
|
||||
|
||||
broadcast (event: string, ...args): void {
|
||||
for (const window of this.windows) {
|
||||
window.send(event, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
async send (event: string, ...args): Promise<void> {
|
||||
async send (event, ...args) {
|
||||
if (!this.hasWindows()) {
|
||||
await this.newWindow()
|
||||
}
|
||||
this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args)
|
||||
}
|
||||
|
||||
enableTray (): void {
|
||||
enableTray () {
|
||||
if (this.tray) {
|
||||
return
|
||||
}
|
||||
@@ -106,7 +71,7 @@ export class Application {
|
||||
this.tray = new Tray(`${app.getAppPath()}/assets/tray.png`)
|
||||
}
|
||||
|
||||
this.tray.on('click', () => setTimeout(() => this.focus()))
|
||||
this.tray.on('click', () => setTimeout(() => this.focus()));
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([{
|
||||
label: 'Show',
|
||||
@@ -120,30 +85,23 @@ export class Application {
|
||||
this.tray.setToolTip(`Terminus ${app.getVersion()}`)
|
||||
}
|
||||
|
||||
disableTray (): void {
|
||||
disableTray () {
|
||||
if (this.tray) {
|
||||
this.tray.destroy()
|
||||
this.tray = null
|
||||
}
|
||||
}
|
||||
|
||||
hasWindows (): boolean {
|
||||
hasWindows () {
|
||||
return !!this.windows.length
|
||||
}
|
||||
|
||||
focus (): void {
|
||||
focus () {
|
||||
for (let window of this.windows) {
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
|
||||
handleSecondInstance (argv: string[], cwd: string): void {
|
||||
this.presentAllWindows()
|
||||
for (let window of this.windows) {
|
||||
window.handleSecondInstance(argv, cwd)
|
||||
}
|
||||
}
|
||||
|
||||
private setupMenu () {
|
||||
let template: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
@@ -224,7 +182,7 @@ export class Application {
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { app } from 'electron'
|
||||
|
||||
export function parseArgs (argv: string[], cwd: string): any {
|
||||
export function parseArgs (argv, cwd) {
|
||||
if (argv[0].includes('node')) {
|
||||
argv = argv.slice(1)
|
||||
}
|
||||
@@ -20,25 +20,25 @@ export function parseArgs (argv: string[], cwd: string): any {
|
||||
return yargs.option('escape', {
|
||||
alias: 'e',
|
||||
type: 'boolean',
|
||||
describe: 'Perform shell escaping',
|
||||
describe: 'Perform shell escaping'
|
||||
}).positional('text', {
|
||||
type: 'string',
|
||||
type: 'string'
|
||||
})
|
||||
})
|
||||
.version('version', '', app.getVersion())
|
||||
.option('debug', {
|
||||
alias: 'd',
|
||||
describe: 'Show DevTools on start',
|
||||
type: 'boolean',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('hidden', {
|
||||
describe: 'Start minimized',
|
||||
type: 'boolean',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('version', {
|
||||
alias: 'v',
|
||||
describe: 'Show version and exit',
|
||||
type: 'boolean',
|
||||
type: 'boolean'
|
||||
})
|
||||
.help('help')
|
||||
.parse(argv.slice(1))
|
||||
|
@@ -1,10 +1,9 @@
|
||||
import './portable'
|
||||
import './sentry'
|
||||
import './lru'
|
||||
import { app, ipcMain, Menu } from 'electron'
|
||||
import { parseArgs } from './cli'
|
||||
import { Application } from './app'
|
||||
import electronDebug = require('electron-debug')
|
||||
import * as electronDebug from 'electron-debug'
|
||||
|
||||
if (!process.env.TERMINUS_PLUGINS) {
|
||||
process.env.TERMINUS_PLUGINS = ''
|
||||
@@ -34,7 +33,7 @@ process.on('uncaughtException' as any, err => {
|
||||
})
|
||||
|
||||
app.on('second-instance', (_event, argv, cwd) => {
|
||||
application.handleSecondInstance(argv, cwd)
|
||||
application.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
||||
})
|
||||
|
||||
const argv = parseArgs(process.argv, process.cwd())
|
||||
@@ -59,8 +58,8 @@ app.on('ready', () => {
|
||||
label: 'New window',
|
||||
click () {
|
||||
this.app.newWindow()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
]))
|
||||
}
|
||||
application.init()
|
||||
|
@@ -1,15 +1,13 @@
|
||||
import * as createLRU from 'lru-cache'
|
||||
import * as fs from 'fs'
|
||||
const lru = createLRU({ max: 256, maxAge: 250 })
|
||||
const origLstat = fs.realpathSync.bind(fs)
|
||||
let lru = require('lru-cache')({ max: 256, maxAge: 250 })
|
||||
|
||||
let fs = require('fs')
|
||||
let origLstat = fs.realpathSync.bind(fs)
|
||||
|
||||
// NB: The biggest offender of thrashing realpathSync is the node module system
|
||||
// itself, which we can't get into via any sane means.
|
||||
require('fs').realpathSync = function (p) {
|
||||
let r = lru.get(p)
|
||||
if (r) {
|
||||
return r
|
||||
}
|
||||
if (r) return r
|
||||
|
||||
r = origLstat(p)
|
||||
lru.set(p, r)
|
||||
|
@@ -1,24 +0,0 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
let appPath: string | null = null
|
||||
try {
|
||||
appPath = path.dirname(require('electron').app.getPath('exe'))
|
||||
} catch {
|
||||
appPath = path.dirname(require('electron').remote.app.getPath('exe'))
|
||||
}
|
||||
|
||||
if (null != appPath) {
|
||||
if(fs.existsSync(path.join(appPath, 'terminus-data'))) {
|
||||
fs.renameSync(path.join(appPath, 'terminus-data'), path.join(appPath, 'data'))
|
||||
}
|
||||
const portableData = path.join(appPath, 'data')
|
||||
if (fs.existsSync(portableData)) {
|
||||
console.log('reset user data to ' + portableData)
|
||||
try {
|
||||
require('electron').app.setPath('userData', portableData)
|
||||
} catch {
|
||||
require('electron').remote.app.setPath('userData', portableData)
|
||||
}
|
||||
}
|
||||
}
|
17
app/lib/sentry.ts
Executable file → Normal file
17
app/lib/sentry.ts
Executable file → Normal file
@@ -1,5 +1,4 @@
|
||||
const { init } = process.type === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer')
|
||||
import * as isDev from 'electron-is-dev'
|
||||
|
||||
|
||||
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
|
||||
@@ -10,12 +9,10 @@ try {
|
||||
release = require('electron').remote.app.getVersion()
|
||||
}
|
||||
|
||||
if (!isDev) {
|
||||
init({
|
||||
dsn: SENTRY_DSN,
|
||||
release,
|
||||
integrations (integrations) {
|
||||
return integrations.filter(integration => integration.name !== 'Breadcrumbs')
|
||||
},
|
||||
})
|
||||
}
|
||||
init({
|
||||
dsn: SENTRY_DSN,
|
||||
release,
|
||||
integrations (integrations) {
|
||||
return integrations.filter(integration => integration.name !== 'Breadcrumbs')
|
||||
},
|
||||
})
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
import { debounceTime } from 'rxjs/operators'
|
||||
import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen } from 'electron'
|
||||
import ElectronConfig = require('electron-config')
|
||||
import { BrowserWindow, app, ipcMain, Rectangle, screen } from 'electron'
|
||||
import * as ElectronConfig from 'electron-config'
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
|
||||
import { parseArgs } from './cli'
|
||||
import { loadConfig } from './config'
|
||||
|
||||
let SetWindowCompositionAttribute: any
|
||||
@@ -24,20 +23,15 @@ export interface WindowOptions {
|
||||
export class Window {
|
||||
ready: Promise<void>
|
||||
private visible = new Subject<boolean>()
|
||||
private closed = new Subject<void>()
|
||||
private window: BrowserWindow
|
||||
private windowConfig: ElectronConfig
|
||||
private windowBounds: Rectangle
|
||||
private closing = false
|
||||
private lastVibrancy: {enabled: boolean, type?: string} | null = null
|
||||
private disableVibrancyWhileDragging = false
|
||||
private configStore: any
|
||||
|
||||
get visible$ (): Observable<boolean> { return this.visible }
|
||||
get closed$ (): Observable<void> { return this.closed }
|
||||
|
||||
constructor (options?: WindowOptions) {
|
||||
this.configStore = loadConfig()
|
||||
let configData = loadConfig()
|
||||
|
||||
options = options || {}
|
||||
|
||||
@@ -54,7 +48,6 @@ export class Window {
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
preload: path.join(__dirname, 'sentry.js'),
|
||||
backgroundThrottling: false,
|
||||
},
|
||||
frame: false,
|
||||
show: false,
|
||||
@@ -63,18 +56,18 @@ export class Window {
|
||||
|
||||
if (this.windowBounds) {
|
||||
Object.assign(bwOptions, this.windowBounds)
|
||||
const closestDisplay = screen.getDisplayNearestPoint( { x: this.windowBounds.x, y: this.windowBounds.y } )
|
||||
const closestDisplay = screen.getDisplayNearestPoint( {x: this.windowBounds.x, y: this.windowBounds.y} )
|
||||
|
||||
const [left1, top1, right1, bottom1] = [this.windowBounds.x, this.windowBounds.y, this.windowBounds.x + this.windowBounds.width, this.windowBounds.y + this.windowBounds.height]
|
||||
const [left2, top2, right2, bottom2] = [closestDisplay.bounds.x, closestDisplay.bounds.y, closestDisplay.bounds.x + closestDisplay.bounds.width, closestDisplay.bounds.y + closestDisplay.bounds.height]
|
||||
const [left1, top1, right1, bottom1] = [this.windowBounds.x, this.windowBounds.y, this.windowBounds.x + this.windowBounds.width, this.windowBounds.y + this.windowBounds.height];
|
||||
const [left2, top2, right2, bottom2] = [closestDisplay.bounds.x, closestDisplay.bounds.y, closestDisplay.bounds.x + closestDisplay.bounds.width, closestDisplay.bounds.y + closestDisplay.bounds.height];
|
||||
|
||||
if ((left2 > right1 || right2 < left1 || top2 > bottom1 || bottom2 < top1) && !maximized) {
|
||||
bwOptions.x = closestDisplay.bounds.width / 2 - bwOptions.width / 2
|
||||
bwOptions.y = closestDisplay.bounds.height / 2 - bwOptions.height / 2
|
||||
bwOptions.x = closestDisplay.bounds.width / 2 - bwOptions.width / 2;
|
||||
bwOptions.y = closestDisplay.bounds.height / 2 - bwOptions.height / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((this.configStore.appearance || {}).frame === 'native') {
|
||||
if ((configData.appearance || {}).frame === 'native') {
|
||||
bwOptions.frame = true
|
||||
} else {
|
||||
if (process.platform === 'darwin') {
|
||||
@@ -90,7 +83,7 @@ export class Window {
|
||||
this.window.once('ready-to-show', () => {
|
||||
if (process.platform === 'darwin') {
|
||||
this.window.setVibrancy('window')
|
||||
} else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) {
|
||||
} else if (process.platform === 'win32' && (configData.appearance || {}).vibrancy) {
|
||||
this.setVibrancy(true)
|
||||
}
|
||||
|
||||
@@ -101,13 +94,6 @@ export class Window {
|
||||
this.window.show()
|
||||
}
|
||||
this.window.focus()
|
||||
this.window.moveTop()
|
||||
}
|
||||
})
|
||||
|
||||
this.window.on('blur', () => {
|
||||
if (this.configStore.appearance?.dockHideOnBlur) {
|
||||
this.hide()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -130,13 +116,12 @@ export class Window {
|
||||
})
|
||||
}
|
||||
|
||||
setVibrancy (enabled: boolean, type?: string): void {
|
||||
this.lastVibrancy = { enabled, type }
|
||||
setVibrancy (enabled: boolean, type?: string) {
|
||||
if (process.platform === 'win32') {
|
||||
if (parseFloat(os.release()) >= 10) {
|
||||
let attribValue = AccentState.ACCENT_DISABLED
|
||||
if (enabled) {
|
||||
if (type === 'fluent') {
|
||||
if (parseInt(os.release().split('.')[2]) >= 17063 && type === 'fluent') {
|
||||
attribValue = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND
|
||||
} else {
|
||||
attribValue = AccentState.ACCENT_ENABLE_BLURBEHIND
|
||||
@@ -146,77 +131,26 @@ export class Window {
|
||||
} else {
|
||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||
}
|
||||
} else {
|
||||
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
|
||||
}
|
||||
}
|
||||
|
||||
show (): void {
|
||||
show () {
|
||||
this.window.show()
|
||||
this.window.moveTop()
|
||||
}
|
||||
|
||||
focus (): void {
|
||||
focus () {
|
||||
this.window.focus()
|
||||
}
|
||||
|
||||
send (event: string, ...args): void {
|
||||
send (event, ...args) {
|
||||
if (!this.window) {
|
||||
return
|
||||
}
|
||||
this.window.webContents.send(event, ...args)
|
||||
if (event === 'host:config-change') {
|
||||
this.configStore = args[0]
|
||||
}
|
||||
}
|
||||
|
||||
isDestroyed (): boolean {
|
||||
return !this.window || this.window.isDestroyed()
|
||||
}
|
||||
|
||||
isFocused (): boolean {
|
||||
return this.window.isFocused()
|
||||
}
|
||||
|
||||
hide (): void {
|
||||
if (process.platform === 'darwin') {
|
||||
// Lose focus
|
||||
Menu.sendActionToFirstResponder('hide:')
|
||||
}
|
||||
this.window.blur()
|
||||
if (process.platform !== 'darwin') {
|
||||
this.window.hide()
|
||||
}
|
||||
}
|
||||
|
||||
present (): void {
|
||||
if (!this.window.isVisible()) {
|
||||
// unfocused, invisible
|
||||
this.window.show()
|
||||
this.window.focus()
|
||||
} else {
|
||||
if (!this.configStore.appearance?.dock || this.configStore.appearance?.dock === 'off') {
|
||||
// not docked, visible
|
||||
setTimeout(() => {
|
||||
this.window.show()
|
||||
this.window.focus()
|
||||
})
|
||||
} else {
|
||||
if (this.configStore.appearance?.dockAlwaysOnTop) {
|
||||
// docked, visible, on top
|
||||
this.window.hide()
|
||||
} else {
|
||||
// docked, visible, not on top
|
||||
this.window.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleSecondInstance (argv: string[], cwd: string): void {
|
||||
if (!this.configStore.appearance?.dock) {
|
||||
this.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
||||
}
|
||||
isDestroyed () {
|
||||
return !this.window || this.window.isDestroyed();
|
||||
}
|
||||
|
||||
private setupWindowManagement () {
|
||||
@@ -268,10 +202,6 @@ export class Window {
|
||||
}
|
||||
})
|
||||
|
||||
this.window.on('focus', () => {
|
||||
this.send('host:window-focused')
|
||||
})
|
||||
|
||||
ipcMain.on('window-focus', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
@@ -359,35 +289,10 @@ export class Window {
|
||||
})
|
||||
|
||||
this.window.webContents.on('new-window', event => event.preventDefault())
|
||||
|
||||
ipcMain.on('window-set-disable-vibrancy-while-dragging', (_event, value) => {
|
||||
this.disableVibrancyWhileDragging = value
|
||||
})
|
||||
|
||||
this.window.on('will-move', () => {
|
||||
if (!this.lastVibrancy?.enabled || !this.disableVibrancyWhileDragging) {
|
||||
return
|
||||
}
|
||||
let timeout: number|null = null
|
||||
const oldVibrancy = this.lastVibrancy
|
||||
this.setVibrancy(false)
|
||||
const onMove = () => {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
timeout = setTimeout(() => {
|
||||
this.window.off('move', onMove)
|
||||
this.setVibrancy(oldVibrancy.enabled, oldVibrancy.type)
|
||||
}, 500)
|
||||
}
|
||||
this.window.on('move', onMove)
|
||||
})
|
||||
}
|
||||
|
||||
private destroy () {
|
||||
this.window = null
|
||||
this.closed.next()
|
||||
this.visible.complete()
|
||||
this.closed.complete()
|
||||
}
|
||||
}
|
||||
|
@@ -13,43 +13,43 @@
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "9.1.9",
|
||||
"@angular/common": "9.1.9",
|
||||
"@angular/compiler": "9.1.9",
|
||||
"@angular/core": "9.1.9",
|
||||
"@angular/forms": "9.1.9",
|
||||
"@angular/platform-browser": "9.1.9",
|
||||
"@angular/platform-browser-dynamic": "9.1.9",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||
"@angular/animations": "9.0.0-rc.5",
|
||||
"@angular/common": "9.0.0-rc.5",
|
||||
"@angular/compiler": "9.0.0-rc.5",
|
||||
"@angular/core": "9.0.0-rc.5",
|
||||
"@angular/forms": "9.0.0-rc.5",
|
||||
"@angular/platform-browser": "9.0.0-rc.5",
|
||||
"@angular/platform-browser-dynamic": "9.0.0-rc.5",
|
||||
"@ng-bootstrap/ng-bootstrap": "^5.1.4",
|
||||
"devtron": "1.4.0",
|
||||
"electron-config": "2.0.0",
|
||||
"electron-debug": "^3.0.1",
|
||||
"electron-is-dev": "1.1.0",
|
||||
"electron-updater": "^4.3.1",
|
||||
"electron-updater": "^4.2.0",
|
||||
"fontmanager-redux": "0.4.0",
|
||||
"js-yaml": "3.14.0",
|
||||
"keytar": "^5.6.0",
|
||||
"js-yaml": "3.13.1",
|
||||
"keytar": "^5.0.0",
|
||||
"mz": "^2.7.0",
|
||||
"ngx-toastr": "^12.0.1",
|
||||
"node-pty": "^0.10.0-beta9",
|
||||
"ngx-toastr": "^11.2.1",
|
||||
"node-pty": "^0.10.0-beta2",
|
||||
"npm": "6.9.0",
|
||||
"path": "0.12.7",
|
||||
"rxjs": "^6.5.5",
|
||||
"rxjs-compat": "^6.5.5",
|
||||
"yargs": "^15.3.1",
|
||||
"zone.js": "^0.10.3"
|
||||
"rxjs": "^6.5.3",
|
||||
"rxjs-compat": "^6.5.3",
|
||||
"yargs": "^15.0.2",
|
||||
"zone.js": "^0.10.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"macos-native-processlist": "^1.0.2",
|
||||
"serialport": "^9.0.0",
|
||||
"windows-blurbehind": "^1.0.1",
|
||||
"windows-native-registry": "^1.0.17",
|
||||
"windows-native-registry": "^1.0.16",
|
||||
"windows-process-tree": "^0.2.4",
|
||||
"windows-swca": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/localize": "^9.0.0-rc.7",
|
||||
"@types/mz": "0.0.32",
|
||||
"@types/node": "12.7.12",
|
||||
"node-abi": "^2.17.0"
|
||||
"node-abi": "^2.13.0"
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { NgModule } from '@angular/core'
|
||||
import { NgModule, Compiler, Inject, Injector, ɵcreateInjector as createInjector } from '@angular/core'
|
||||
import '@angular/localize/init'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ToastrModule } from 'ngx-toastr'
|
||||
|
||||
export function getRootModule (plugins: any[]) {
|
||||
const imports = [
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
...plugins,
|
||||
CommonModule,
|
||||
NgbModule,
|
||||
ToastrModule.forRoot({
|
||||
positionClass: 'toast-bottom-center',
|
||||
@@ -15,7 +16,33 @@ export function getRootModule (plugins: any[]) {
|
||||
preventDuplicates: true,
|
||||
extendedTimeOut: 5000,
|
||||
}),
|
||||
]
|
||||
],
|
||||
})
|
||||
export class RootModule {
|
||||
constructor (
|
||||
private compiler: Compiler,
|
||||
private injector: Injector,
|
||||
@Inject('plugins') private plugins: any[],
|
||||
) { }
|
||||
|
||||
async ngDoBootstrap (app) {
|
||||
console.log('bootstrap', app)
|
||||
for (let plugin of this.plugins) {
|
||||
console.log(plugin)
|
||||
// try {
|
||||
const injector = createInjector(plugin, this.injector)
|
||||
console.log(injector)
|
||||
const module = await this.compiler.compileModuleAsync(plugin)
|
||||
console.log(module)
|
||||
// } catch (e) {
|
||||
// console.error('Failed loading', plugin, e)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function setupRootModule (plugins: any[]) {
|
||||
const bootstrap = [
|
||||
...plugins.filter(x => x.bootstrap).map(x => x.bootstrap),
|
||||
]
|
||||
@@ -23,11 +50,4 @@ export function getRootModule (plugins: any[]) {
|
||||
if (bootstrap.length === 0) {
|
||||
throw new Error('Did not find any bootstrap components. Are there any plugins installed?')
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports,
|
||||
bootstrap,
|
||||
}) class RootModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
|
||||
return RootModule
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import '../lib/lru'
|
||||
import 'core-js/proposals/reflect-metadata'
|
||||
import 'source-sans-pro/source-sans-pro.css'
|
||||
import 'source-code-pro/source-code-pro.css'
|
||||
import '@fortawesome/fontawesome-free/css/solid.css'
|
||||
@@ -6,3 +7,71 @@ import '@fortawesome/fontawesome-free/css/brands.css'
|
||||
import '@fortawesome/fontawesome-free/css/fontawesome.css'
|
||||
import 'ngx-toastr/toastr.css'
|
||||
import './preload.scss'
|
||||
import * as path from 'path'
|
||||
|
||||
const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires
|
||||
const nodeRequire = (global as any).require
|
||||
|
||||
|
||||
const builtinModules = [
|
||||
'@angular/animations',
|
||||
'@angular/common',
|
||||
'@angular/compiler',
|
||||
'@angular/core',
|
||||
'@angular/forms',
|
||||
'@angular/localize',
|
||||
'@angular/platform-browser',
|
||||
'@angular/platform-browser-dynamic',
|
||||
'@ng-bootstrap/ng-bootstrap',
|
||||
'ngx-toastr',
|
||||
'rxjs',
|
||||
'rxjs/operators',
|
||||
'rxjs/internal/observable/fromEvent',
|
||||
'rxjs/internal/observable/merge',
|
||||
'rxjs-compat/Subject',
|
||||
'zone.js/dist/zone.js',
|
||||
'terminus-core',
|
||||
// 'terminus-settings',
|
||||
// 'terminus-terminal',
|
||||
]
|
||||
|
||||
const cachedBuiltinModules = {}
|
||||
|
||||
if (process.env.TERMINUS_DEV) {
|
||||
console.info(path.dirname(require('electron').remote.app.getAppPath()))
|
||||
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
|
||||
nodeModule.globalPaths.unshift(path.join(require('electron').remote.app.getAppPath(), 'node_modules'))
|
||||
}
|
||||
|
||||
const originalRequire = (global as any).require
|
||||
;(global as any).require = function (query: string) {
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalRequire.apply(this, arguments)
|
||||
}
|
||||
|
||||
const originalModuleRequire = nodeModule.prototype.require
|
||||
nodeModule.prototype.require = function (query: string) {
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalModuleRequire.call(this, query)
|
||||
}
|
||||
|
||||
global['require'].resolve = originalRequire.resolve
|
||||
nodeModule.prototype.require.resolve = originalModuleRequire.resolve
|
||||
|
||||
builtinModules.forEach(m => {
|
||||
const label = 'Caching ' + m
|
||||
console.time(label)
|
||||
try {
|
||||
console.log(m + '/__ivy_ngcc__/fesm5/' + m.split('/')[1] + '.js')
|
||||
cachedBuiltinModules[m] = nodeRequire(m + '/__ivy_ngcc__/fesm5/' + m.split('/')[1] + '.js')
|
||||
console.log('loaded ivy')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
cachedBuiltinModules[m] = nodeRequire(m)
|
||||
}
|
||||
console.timeEnd(label)
|
||||
})
|
||||
|
@@ -1,17 +1,12 @@
|
||||
import 'zone.js'
|
||||
import 'core-js/proposals/reflect-metadata'
|
||||
import 'rxjs'
|
||||
|
||||
import * as isDev from 'electron-is-dev'
|
||||
|
||||
import './global.scss'
|
||||
import './toastr.scss'
|
||||
|
||||
import { enableProdMode, NgModuleRef, ApplicationRef } from '@angular/core'
|
||||
import { enableDebugTools } from '@angular/platform-browser'
|
||||
import { enableProdMode, NgModuleRef } from '@angular/core'
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
|
||||
|
||||
import { getRootModule } from './app.module'
|
||||
import { setupRootModule, RootModule } from './app.module'
|
||||
import { findPlugins, loadPlugins, PluginInfo } from './plugins'
|
||||
|
||||
// Always land on the start view
|
||||
@@ -33,19 +28,14 @@ async function bootstrap (plugins: PluginInfo[], safeMode = false): Promise<NgMo
|
||||
if (safeMode) {
|
||||
plugins = plugins.filter(x => x.isBuiltin)
|
||||
}
|
||||
const pluginsModules = await loadPlugins(plugins, (current, total) => {
|
||||
const pluginModules = await loadPlugins(plugins, (current, total) => {
|
||||
(document.querySelector('.progress .bar') as HTMLElement).style.width = `${100 * current / total}%` // eslint-disable-line
|
||||
})
|
||||
const module = getRootModule(pluginsModules)
|
||||
window['rootModule'] = module
|
||||
return platformBrowserDynamic().bootstrapModule(module).then(moduleRef => {
|
||||
if (isDev) {
|
||||
const applicationRef = moduleRef.injector.get(ApplicationRef)
|
||||
const componentRef = applicationRef.components[0]
|
||||
enableDebugTools(componentRef)
|
||||
}
|
||||
return moduleRef
|
||||
})
|
||||
setupRootModule(pluginModules)
|
||||
window['rootModule'] = RootModule
|
||||
return platformBrowserDynamic([
|
||||
{ provide: 'plugins', useValue: pluginModules },
|
||||
]).bootstrapModule(RootModule)
|
||||
}
|
||||
|
||||
findPlugins().then(async plugins => {
|
||||
|
@@ -14,14 +14,12 @@ function normalizePath (path: string): string {
|
||||
|
||||
global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
|
||||
if (process.env.TERMINUS_DEV) {
|
||||
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
|
||||
}
|
||||
|
||||
const builtinPluginsPath = process.env.TERMINUS_DEV ? path.dirname(require('electron').remote.app.getAppPath()) : path.join((process as any).resourcesPath, 'builtin-plugins')
|
||||
|
||||
const userPluginsPath = path.join(
|
||||
require('electron').remote.app.getPath('userData'),
|
||||
require('electron').remote.app.getPath('appData'),
|
||||
'terminus',
|
||||
'plugins',
|
||||
)
|
||||
|
||||
@@ -51,49 +49,6 @@ export interface PluginInfo {
|
||||
info?: any
|
||||
}
|
||||
|
||||
const builtinModules = [
|
||||
'@angular/animations',
|
||||
'@angular/common',
|
||||
'@angular/compiler',
|
||||
'@angular/core',
|
||||
'@angular/forms',
|
||||
'@angular/platform-browser',
|
||||
'@angular/platform-browser-dynamic',
|
||||
'@ng-bootstrap/ng-bootstrap',
|
||||
'ngx-toastr',
|
||||
'rxjs',
|
||||
'rxjs/operators',
|
||||
'rxjs-compat/Subject',
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
'zone.js/dist/zone.js',
|
||||
]
|
||||
|
||||
const cachedBuiltinModules = {}
|
||||
builtinModules.forEach(m => {
|
||||
const label = 'Caching ' + m
|
||||
console.time(label)
|
||||
cachedBuiltinModules[m] = nodeRequire(m)
|
||||
console.timeEnd(label)
|
||||
})
|
||||
|
||||
const originalRequire = (global as any).require
|
||||
;(global as any).require = function (query: string) {
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalRequire.apply(this, arguments)
|
||||
}
|
||||
|
||||
const originalModuleRequire = nodeModule.prototype.require
|
||||
nodeModule.prototype.require = function (query: string) {
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalModuleRequire.call(this, query)
|
||||
}
|
||||
|
||||
export async function findPlugins (): Promise<PluginInfo[]> {
|
||||
const paths = nodeModule.globalPaths
|
||||
let foundPlugins: PluginInfo[] = []
|
||||
@@ -166,6 +121,7 @@ export async function loadPlugins (foundPlugins: PluginInfo[], progress: Progres
|
||||
progress(0, 1)
|
||||
let index = 0
|
||||
for (const foundPlugin of foundPlugins) {
|
||||
if (foundPlugin.name !== 'core') continue
|
||||
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
||||
progress(index, foundPlugins.length)
|
||||
try {
|
||||
|
@@ -1,6 +0,0 @@
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<app-root></app-root>',
|
||||
})
|
||||
export class RootComponent { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./src",
|
||||
"module": "commonjs",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2015",
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
@@ -19,7 +20,10 @@
|
||||
"es2015.iterable",
|
||||
"es2017",
|
||||
"es7"
|
||||
]
|
||||
],
|
||||
"paths": {
|
||||
"*": ["../../app/node_modules/*"]
|
||||
}
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"exclude": [
|
||||
@@ -28,5 +32,9 @@
|
||||
"*/node_modules",
|
||||
"terminus*",
|
||||
"platforms"
|
||||
]
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": true,
|
||||
"disableTypeScriptVersionCheck": true
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const { AngularCompilerPlugin } = require('@ngtools/webpack')
|
||||
|
||||
module.exports = {
|
||||
name: 'terminus',
|
||||
@@ -28,13 +29,8 @@ module.exports = {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: {
|
||||
loader: 'awesome-typescript-loader',
|
||||
options: {
|
||||
configFileName: path.resolve(__dirname, 'tsconfig.json'),
|
||||
},
|
||||
},
|
||||
test: /(?:\.ngfactory\.js|\.ngfactory|\.ngstyle\.js|\.ts)$/,
|
||||
loader: '@ngtools/webpack',
|
||||
},
|
||||
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
|
||||
{ test: /\.css$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
|
||||
@@ -82,5 +78,10 @@ module.exports = {
|
||||
new webpack.DefinePlugin({
|
||||
'process.type': '"renderer"'
|
||||
}),
|
||||
new AngularCompilerPlugin({
|
||||
tsConfigPath: path.resolve(__dirname, 'tsconfig.json'),
|
||||
entryModule: 'src/index#default',
|
||||
sourceMap: true,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
663
app/yarn.lock
663
app/yarn.lock
@@ -2,111 +2,172 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@angular/animations@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.1.9.tgz#de54334ea195189402487855c9a98f5618605da4"
|
||||
integrity sha512-qWVi0TxmU6HeXAgEsfpQvFFygh+a0kH2kGe6bWij4XvG6dWfV3xZjlaFwSIYGk+yK4yL0+9+PAXH+ENfxNw+Cw==
|
||||
"@angular/animations@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.0.0-rc.5.tgz#8ed3fa2f5d16c16d1ea013ec71e46365c8336622"
|
||||
integrity sha512-pb1QJjBaBOenSIdKB9h1Ts8yQwdAjjTuH9ckVycjYH3yKDc1cQuaGy4NxEx7TJF8ADo4iKkCvKTyh0dW42TOvg==
|
||||
|
||||
"@angular/common@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.1.9.tgz#16e77b2db675b80e32f1788a20c538150fd09294"
|
||||
integrity sha512-y/tJtkuOJhV2kcaXZyrLZH84i4uQ1r+vaaEHvXj+JZYfYfcMMd/TDqMiPcIkUb3RxqghtZ+q0ZNW5D1Nlru3Pw==
|
||||
"@angular/common@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.0.0-rc.5.tgz#05c6cfeef03d55757bf131c8171fb3bf35daa59f"
|
||||
integrity sha512-Gg24S8dMUwVrmIvVHIz2rWCU+q+4Su41s4oipJWJIW1bCBMWqb2oGtaWMhy7RbUkFq2TeL7tC3dS2FOqvgj9sg==
|
||||
|
||||
"@angular/compiler@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.1.9.tgz#cbf678ee28a0811a8ef3ee7be565d4911ff28ec7"
|
||||
integrity sha512-kjFgaTB2ckr9lgmkS1dOGRT7kmzpQueydxsxXSHWgICNVE6F/u1PHyeSOyJRpxW0GnrkLq3QM2EUFnQGGga5bg==
|
||||
"@angular/compiler@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0-rc.5.tgz#4771e04d8a4c25cfe195232b194dd8ac61bdce42"
|
||||
integrity sha512-0CWPDbpHoWm/ZN40/Y+iPikRQbhd50keoE4xSAYM2SS1pnomJaF2ytIL9xfc3BMGGKgiX3aIk57B0m4yDYTiBw==
|
||||
|
||||
"@angular/core@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.1.9.tgz#db4241f867d6e14b81ed6e7c50334813c6ebfc10"
|
||||
integrity sha512-q/DERgVU6vK2LtTcdVCGGBcoO424WsEfImh3Vcuy+P/ZVmthlDUC/+q+tSKt8MMf4hLpxFDQJE8vUSkktj7QEw==
|
||||
"@angular/core@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0-rc.5.tgz#4d6140e3bf14b7be86e2045bf6a657ec7b4ef211"
|
||||
integrity sha512-g9IhWc5znQGNj056Qtk1OnNYDQAIT8ti++xgcAYJ2Z1Yp0Bkb8gL7WexiuwKxmilHmZxnZiRHsPfSlKl0Hxp5g==
|
||||
|
||||
"@angular/forms@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.1.9.tgz#20c9a79d1dcb2cace45df9e2f304b658e02c1687"
|
||||
integrity sha512-r675yImnb/0pY7K5W3V2ITa7YETu1I2AS+bRfII6UQ6gthyeFFOHb5noa7YneC2yqQiM6E4DQmF5ig3daPuFNg==
|
||||
"@angular/forms@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.0.0-rc.5.tgz#ab8886d865d968ab23b7680e80061c16fef0a5d8"
|
||||
integrity sha512-+K4MHD7EmSbxljKd/+vugyGWUROSy8PAcqV160gCQQbxW9MuYsHJM/BBPaq2H07gE5YHJ/HOSQoepNdXJ3PUSw==
|
||||
|
||||
"@angular/platform-browser-dynamic@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.9.tgz#12f8b05d3c9ef0844df88f3833e29ea1e49ec5e0"
|
||||
integrity sha512-b9MG5MWne+IuL3uLm8jwPhlJzqYaGBGk/qibOqb17T24j1iyrlO7T5bZ8zO6pUy5iT/TahVfHPnPJC1qTK5OmA==
|
||||
|
||||
"@angular/platform-browser@9.1.9":
|
||||
version "9.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.1.9.tgz#c2fcc50aebfdc268521b407e32dc0d967cb40411"
|
||||
integrity sha512-V861X3MxJp1AlMTnkUPldpBLIJbApXF3ka0A5Dq2nVJCyOFeteGkaRWSBgqe2jxmq+LVpJbzcNvtDFXw6mQ0jA==
|
||||
|
||||
"@ng-bootstrap/ng-bootstrap@^6.1.0":
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-6.1.0.tgz#fce7550a095aeac42108f76ac1ebd63caf8304e9"
|
||||
integrity sha512-2GzkNJBKdeHkaUqaCAqSILPft0IzzHjMfAlAuGY6/ZLlVQ0glt5MTbIXtIhSbjR+OvlrljoXFLrvzs1LGdmE+A==
|
||||
|
||||
"@serialport/binding-abstract@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-abstract/-/binding-abstract-8.0.6.tgz#78e6d7995a95c46d480445303e6f32ca4d53edcd"
|
||||
integrity sha512-1swwUVoRyQ9ubxrkJ8JPppykohUpTAP4jkGr36e9NjbVocSPfqeX6tFZFwl/IdUlwJwxGdbKDqq7FvXniCQUMw==
|
||||
"@angular/localize@^9.0.0-rc.7":
|
||||
version "9.0.0-rc.7"
|
||||
resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-9.0.0-rc.7.tgz#8819a32309d44a631c102d3c8d064302cfc23f3c"
|
||||
integrity sha512-y03uNKoZSsedY5W2X7NUNcmxm6rsL6dMs2g1NRw0jOmveXjk8N0g7uUgcBQhXJ7LiHtaRcIK+bOq+2JvvTtZlQ==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
"@babel/core" "^7.5.5"
|
||||
glob "7.1.2"
|
||||
yargs "13.1.0"
|
||||
|
||||
"@serialport/binding-mock@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/binding-mock/-/binding-mock-8.0.6.tgz#41a8f827269c6a0e58546513a274e12023134155"
|
||||
integrity sha512-BIbY5/PsDDo0QWDNCCxDgpowAdks+aZR8BOsEtK2GoASTTcJCy1fBwPIfH870o7rnbH901wY3C+yuTfdOvSO9A==
|
||||
"@angular/platform-browser-dynamic@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.0-rc.5.tgz#6beb6e5f625df5939b757b80f7f39134e95769f0"
|
||||
integrity sha512-MCDIuwcFlXo4f/ro9NiYcV1t8SBdt22dXjQWWSij+ABlVqrW7Xwl8oNq0q2+HJQIlg+a37Y2svJouUN1kLvZ3A==
|
||||
|
||||
"@angular/platform-browser@9.0.0-rc.5":
|
||||
version "9.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.0.0-rc.5.tgz#b10dcd5df71c33e7bff48154ae3876de5236eb5e"
|
||||
integrity sha512-omnc9GnVU8THx2YSnJUzrR2Lk2alzao9AhR+I05GOlYgL3HsuttTtTBEzVfvecGLwSBKrdtbPUwWG4NTuuxGTA==
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
|
||||
integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
|
||||
dependencies:
|
||||
"@serialport/binding-abstract" "^8.0.6"
|
||||
debug "^4.1.1"
|
||||
"@babel/highlight" "^7.0.0"
|
||||
|
||||
"@serialport/bindings@^8.0.7":
|
||||
version "8.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/bindings/-/bindings-8.0.7.tgz#2a58f60f1e24ee4549be6f9e0e37b3359d038a1c"
|
||||
integrity sha512-IqudDL8ne2Y2S0W5fKA6wdgHCIA2e2OIaPVYhGy6duE6legNHFY+05CLicHAyAeTocXmHU7rVNxzVQrOG5tM4g==
|
||||
"@babel/core@^7.5.5":
|
||||
version "7.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e"
|
||||
integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw==
|
||||
dependencies:
|
||||
"@serialport/binding-abstract" "^8.0.6"
|
||||
"@serialport/parser-readline" "^8.0.6"
|
||||
bindings "^1.5.0"
|
||||
debug "^4.1.1"
|
||||
nan "^2.14.0"
|
||||
prebuild-install "^5.3.0"
|
||||
"@babel/code-frame" "^7.5.5"
|
||||
"@babel/generator" "^7.7.4"
|
||||
"@babel/helpers" "^7.7.4"
|
||||
"@babel/parser" "^7.7.5"
|
||||
"@babel/template" "^7.7.4"
|
||||
"@babel/traverse" "^7.7.4"
|
||||
"@babel/types" "^7.7.4"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
json5 "^2.1.0"
|
||||
lodash "^4.17.13"
|
||||
resolve "^1.3.2"
|
||||
semver "^5.4.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@serialport/parser-byte-length@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-8.0.6.tgz#efb6195692b1088e6c095fd43bae196fc30674d0"
|
||||
integrity sha512-92mrFxFEvq3gRvSM7ANK/jfbmHslz91a5oYJy/nbSn4H/MCRXjxR2YOkQgVXuN+zLt+iyDoW3pcOP4Sc1nWdqQ==
|
||||
|
||||
"@serialport/parser-cctalk@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-8.0.6.tgz#4134a3c479d465df3b152a21e16b8ecf1bc818c3"
|
||||
integrity sha512-pqtCYQPgxnxHygiXUPCfgX7sEx+fdR/ObjpscidynEULUq2fFrC5kBkrxRbTfHRtTaU2ii9DyjFq0JVRCbhI0Q==
|
||||
|
||||
"@serialport/parser-delimiter@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-8.0.6.tgz#0e467cb07a40bd3006835c48e488666bd7de22cc"
|
||||
integrity sha512-ogKOcPisPMlVtirkuDu3SFTF0+xT0ijxoH7XjpZiYL41EVi367MwuCnEmXG+dEKKnF0j9EPqOyD2LGSJxaFmhQ==
|
||||
|
||||
"@serialport/parser-readline@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-8.0.6.tgz#8a6a296a1bec08a4855bf7a62bc6335d52972e4a"
|
||||
integrity sha512-OYBT2mpczh9QUI3MTw8j0A0tIlPVjpVipvuVnjRkYwxrxPeq04RaLFhaDpuRzua5rTKMt89c1y3btYeoDXMjAA==
|
||||
"@babel/generator@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
|
||||
integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==
|
||||
dependencies:
|
||||
"@serialport/parser-delimiter" "^8.0.6"
|
||||
"@babel/types" "^7.7.4"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@serialport/parser-ready@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-8.0.6.tgz#d6e95e53ee70d298ae0b4147995007f4ba62651c"
|
||||
integrity sha512-xcEqv4rc119WR5JzAuu8UeJOlAwET2PTdNb6aIrrLlmTxhvuBbuRFcsnF3BpH9jUL30Kh7a6QiNXIwVG+WR/1Q==
|
||||
|
||||
"@serialport/parser-regex@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-8.0.6.tgz#70aa1abe31899d1b986f44cfb6777a76e26755bf"
|
||||
integrity sha512-J8KY75Azz5ZyExmyM5YfUxbXOWBkZCytKgCCmZ966ttwZS0bUZOuoCaZj2Zp4VILJAiLuxHoqc0foi67Fri5+g==
|
||||
|
||||
"@serialport/stream@^8.0.6":
|
||||
version "8.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-8.0.6.tgz#3395dbac788c00797c2435c61c2ecb4e99fbf41d"
|
||||
integrity sha512-ym1PwM0rwLrj90vRBB66I1hwMXbuMw9wGTxqns75U3N/tuNFOH85mxXaYVF2TpI66aM849NoI1jMm50fl9equg==
|
||||
"@babel/helper-function-name@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
|
||||
integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
"@babel/helper-get-function-arity" "^7.7.4"
|
||||
"@babel/template" "^7.7.4"
|
||||
"@babel/types" "^7.7.4"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
|
||||
integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.7.4"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
|
||||
integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==
|
||||
dependencies:
|
||||
"@babel/types" "^7.7.4"
|
||||
|
||||
"@babel/helpers@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302"
|
||||
integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==
|
||||
dependencies:
|
||||
"@babel/template" "^7.7.4"
|
||||
"@babel/traverse" "^7.7.4"
|
||||
"@babel/types" "^7.7.4"
|
||||
|
||||
"@babel/highlight@^7.0.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
|
||||
integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==
|
||||
dependencies:
|
||||
chalk "^2.0.0"
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.7.4", "@babel/parser@^7.7.5":
|
||||
version "7.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71"
|
||||
integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==
|
||||
|
||||
"@babel/template@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
|
||||
integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/parser" "^7.7.4"
|
||||
"@babel/types" "^7.7.4"
|
||||
|
||||
"@babel/traverse@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
|
||||
integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.5.5"
|
||||
"@babel/generator" "^7.7.4"
|
||||
"@babel/helper-function-name" "^7.7.4"
|
||||
"@babel/helper-split-export-declaration" "^7.7.4"
|
||||
"@babel/parser" "^7.7.4"
|
||||
"@babel/types" "^7.7.4"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/types@^7.7.4":
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
|
||||
integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@ng-bootstrap/ng-bootstrap@^5.1.4":
|
||||
version "5.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-5.1.4.tgz#1ace4d4a7b80017fb1c55547a5569993b4742b5d"
|
||||
integrity sha512-UtL9GBkAMy0O/0Rkc4DG1WoFDWhAnAdvsQuJ1IFLmlN2v6HAX+E84tgUK0n15WLBhYBXXuhRx0dIW2jafjg1xQ==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@types/color-name@^1.1.1":
|
||||
version "1.1.1"
|
||||
@@ -130,12 +191,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
|
||||
integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==
|
||||
|
||||
"@types/semver@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408"
|
||||
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/semver@^6.0.2":
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
|
||||
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
|
||||
|
||||
JSONStream@^1.3.4, JSONStream@^1.3.5:
|
||||
version "1.3.5"
|
||||
@@ -203,6 +262,11 @@ ansi-regex@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||
|
||||
ansi-regex@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
||||
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
||||
|
||||
ansi-regex@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
|
||||
@@ -290,11 +354,6 @@ asynckit@^0.4.0:
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
|
||||
at-least-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
||||
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||
@@ -328,13 +387,6 @@ bin-links@^1.1.2:
|
||||
graceful-fs "^4.1.11"
|
||||
write-file-atomic "^2.3.0"
|
||||
|
||||
bindings@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
|
||||
dependencies:
|
||||
file-uri-to-path "1.0.0"
|
||||
|
||||
bl@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
|
||||
@@ -380,10 +432,10 @@ buffer-from@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
|
||||
builder-util-runtime@8.7.0:
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.0.tgz#e48ad004835c8284662e8eaf47a53468c66e8e8d"
|
||||
integrity sha512-G1AqqVM2vYTrSFR982c1NNzwXKrGLQjVjaZaWQdn4O6Z3YKjdMDofw88aD9jpyK9ZXkrCxR0tI3Qe9wNbyTlXg==
|
||||
builder-util-runtime@8.4.0:
|
||||
version "8.4.0"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz#3163fffc078e6b8f3dd5b6eb12a8345573590682"
|
||||
integrity sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
sax "^1.2.4"
|
||||
@@ -448,7 +500,7 @@ caseless@~0.12.0:
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||
|
||||
chalk@^2.0.1:
|
||||
chalk@^2.0.0, chalk@^2.0.1:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
@@ -633,6 +685,13 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
|
||||
|
||||
convert-source-map@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.1"
|
||||
|
||||
copy-concurrently@^1.0.0:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
|
||||
@@ -666,6 +725,17 @@ cross-spawn@^5.0.1:
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^6.0.0:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
|
||||
dependencies:
|
||||
nice-try "^1.0.4"
|
||||
path-key "^2.0.1"
|
||||
semver "^5.5.0"
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
crypto-random-string@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
|
||||
@@ -704,7 +774,7 @@ debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.1.1:
|
||||
debug@^4.1.0, debug@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
@@ -862,18 +932,24 @@ electron-localshortcut@^3.1.0:
|
||||
keyboardevent-from-electron-accelerator "^1.1.0"
|
||||
keyboardevents-areequal "^0.2.1"
|
||||
|
||||
electron-updater@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.1.tgz#9d485b6262bc56fcf7ee62b1dc1b3b105a3e96a7"
|
||||
integrity sha512-UDC5AHCgeiHJYDYWZG/rsl1vdAFKqI/Lm7whN57LKAk8EfhTewhcEHzheRcncLgikMcQL8gFo1KeX51tf5a5Wg==
|
||||
electron-updater@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.0.tgz#f9ecfc657f65ead737d42b9efecf628d3756b550"
|
||||
integrity sha512-GuS3g7HDh17x/SaFjxjswlWUaKHczksYkV2Xc5CKj/bZH0YCvTSHtOmnBAdAmCk99u/71p3zP8f0jIqDfGcjww==
|
||||
dependencies:
|
||||
"@types/semver" "^7.1.0"
|
||||
builder-util-runtime "8.7.0"
|
||||
fs-extra "^9.0.0"
|
||||
"@types/semver" "^6.0.2"
|
||||
builder-util-runtime "8.4.0"
|
||||
fs-extra "^8.1.0"
|
||||
js-yaml "^3.13.1"
|
||||
lazy-val "^1.0.4"
|
||||
lodash.isequal "^4.5.0"
|
||||
semver "^7.1.3"
|
||||
pako "^1.0.10"
|
||||
semver "^6.3.0"
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
@@ -940,6 +1016,11 @@ esprima@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
|
||||
esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
execa@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
|
||||
@@ -953,6 +1034,19 @@ execa@^0.7.0:
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
|
||||
dependencies:
|
||||
cross-spawn "^6.0.0"
|
||||
get-stream "^4.0.0"
|
||||
is-stream "^1.1.0"
|
||||
npm-run-path "^2.0.0"
|
||||
p-finally "^1.0.0"
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
expand-template@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
@@ -988,11 +1082,6 @@ figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
|
||||
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||
|
||||
find-npm-prefix@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf"
|
||||
@@ -1068,15 +1157,14 @@ fs-constants@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||
|
||||
fs-extra@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
|
||||
integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==
|
||||
fs-extra@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
|
||||
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
|
||||
dependencies:
|
||||
at-least-node "^1.0.0"
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^1.0.0"
|
||||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-minipass@^1.2.5:
|
||||
version "1.2.6"
|
||||
@@ -1186,6 +1274,18 @@ github-from-package@0.0.0:
|
||||
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
|
||||
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
|
||||
|
||||
glob@7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.0.3, glob@^7.1.1, glob@^7.1.3:
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
|
||||
@@ -1205,6 +1305,11 @@ global-dirs@^0.1.0:
|
||||
dependencies:
|
||||
ini "^1.3.4"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
||||
|
||||
got@^6.7.1:
|
||||
version "6.7.1"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
|
||||
@@ -1383,6 +1488,11 @@ invert-kv@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
|
||||
integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
|
||||
|
||||
invert-kv@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
|
||||
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
|
||||
|
||||
ip-regex@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
|
||||
@@ -1489,10 +1599,15 @@ isstream@~0.1.2:
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
|
||||
js-yaml@3.14.0, js-yaml@^3.13.1:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
|
||||
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-yaml@3.13.1, js-yaml@^3.13.1:
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
||||
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
@@ -1502,6 +1617,11 @@ jsbn@~0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
|
||||
|
||||
jsesc@^2.5.1:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
||||
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
|
||||
|
||||
json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||
@@ -1522,12 +1642,17 @@ json-stringify-safe@~5.0.1:
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
|
||||
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==
|
||||
json5@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6"
|
||||
integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==
|
||||
dependencies:
|
||||
universalify "^1.0.0"
|
||||
minimist "^1.2.0"
|
||||
|
||||
jsonfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
|
||||
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
@@ -1556,12 +1681,12 @@ keyboardevents-areequal@^0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
|
||||
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
|
||||
|
||||
keytar@^5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.6.0.tgz#7b5d4bd043d17211163640be6c4a27a49b12bb39"
|
||||
integrity sha512-ueulhshHSGoryfRXaIvTj0BV1yB0KddBGhGoqCxSN9LR1Ks1GKuuCdVhF+2/YOs5fMl6MlTI9On1a4DHDXoTow==
|
||||
keytar@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/keytar/-/keytar-5.0.0.tgz#c89b6b7a4608fd7af633d9f8474b1a7eb97cbe6f"
|
||||
integrity sha512-a5UheK59YOlJf9i+2Osaj/kkH6mK0RCHVMtJ84u6ZfbfRIbOJ/H4b5VlOF/LgNHF6s78dRSBzZnvIuPiBKv6wg==
|
||||
dependencies:
|
||||
nan "2.14.1"
|
||||
nan "2.14.0"
|
||||
prebuild-install "5.3.3"
|
||||
|
||||
latest-version@^3.0.0:
|
||||
@@ -1588,6 +1713,13 @@ lcid@^1.0.0:
|
||||
dependencies:
|
||||
invert-kv "^1.0.0"
|
||||
|
||||
lcid@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
|
||||
integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
|
||||
dependencies:
|
||||
invert-kv "^2.0.0"
|
||||
|
||||
libcipm@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-3.0.3.tgz#2e764effe0b90d458790dab3165794c804075ed3"
|
||||
@@ -1803,6 +1935,11 @@ lodash.without@~4.4.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
|
||||
integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=
|
||||
|
||||
lodash@^4.17.13:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
lowercase-keys@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
@@ -1854,6 +1991,13 @@ make-fetch-happen@^4.0.1:
|
||||
socks-proxy-agent "^4.0.0"
|
||||
ssri "^6.0.0"
|
||||
|
||||
map-age-cleaner@^0.1.1:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
|
||||
integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
|
||||
dependencies:
|
||||
p-defer "^1.0.0"
|
||||
|
||||
meant@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d"
|
||||
@@ -1866,6 +2010,15 @@ mem@^1.1.0:
|
||||
dependencies:
|
||||
mimic-fn "^1.0.0"
|
||||
|
||||
mem@^4.0.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
|
||||
integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
|
||||
dependencies:
|
||||
map-age-cleaner "^0.1.1"
|
||||
mimic-fn "^2.0.0"
|
||||
p-is-promise "^2.0.0"
|
||||
|
||||
mime-db@1.40.0:
|
||||
version "1.40.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
|
||||
@@ -1883,6 +2036,11 @@ 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-fn@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-response@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46"
|
||||
@@ -1979,25 +2137,32 @@ mz@^2.7.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nan@2.14.1, nan@^2.13.2, nan@^2.14.0:
|
||||
version "2.14.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
||||
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
||||
nan@2.14.0, nan@^2.13.2, nan@^2.14.0:
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||
|
||||
napi-build-utils@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508"
|
||||
integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==
|
||||
|
||||
ngx-toastr@^12.0.1:
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-12.0.1.tgz#288c8ef505f1216aa4952cd2a8c6fa7c57a54ccc"
|
||||
integrity sha512-PABtbn2dyHweVSbo/py1W3veXzcmZO7uVItfTW9AykSSeAUju3gOCgauAw89km0aJ9EBcPOieaoI+9tAR7Pfug==
|
||||
ngx-toastr@^11.2.1:
|
||||
version "11.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-11.2.1.tgz#130dcb416499f4419b18c39ad9cfea2e7790c7c4"
|
||||
integrity sha512-qLZA+h1lIGLQ1HAJpx5JJ8i87PAZPAN6MnexmrWipSONqrK4fRh+nUKIxqmcckIiD16dgu2O5SNloSJymTKUAw==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
node-abi@^2.16.0, node-abi@^2.7.0:
|
||||
version "2.16.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.16.0.tgz#7df94e9c0a7a189f4197ab84bac8089ef5894992"
|
||||
integrity sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==
|
||||
nice-try@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-abi@^2.13.0, node-abi@^2.7.0:
|
||||
version "2.13.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.13.0.tgz#e2f2ec444d0aca3ea1b3874b6de41d1665828f63"
|
||||
integrity sha512-9HrZGFVTR5SOu3PZAnAY2hLO36aW1wmA+FDsVkr85BTST32TLCA1H/AEcatVRAsWLyXS3bqUDYCAjq5/QGuSTA==
|
||||
dependencies:
|
||||
semver "^5.4.1"
|
||||
|
||||
@@ -2045,10 +2210,10 @@ node-gyp@^4.0.0:
|
||||
tar "^4.4.8"
|
||||
which "1"
|
||||
|
||||
node-pty@^0.10.0-beta9:
|
||||
version "0.10.0-beta9"
|
||||
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta9.tgz#e5a795f9b53948346803cb71bac4ffc02e7909f0"
|
||||
integrity sha512-Qm6uSH30FUcAhJ9s76C+lgvTsOW2cHUbkIGjCdOVCL0c7S4DxsmKBRgjcr+guUK9d9KwfuZHeSjXYWjpJFPe4w==
|
||||
node-pty@^0.10.0-beta2:
|
||||
version "0.10.0-beta3"
|
||||
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta3.tgz#a33c9fc67c9e4d4f124111e1da2a72b0783008e7"
|
||||
integrity sha512-j7MoJ3K999jrT9gAVs7JvM/skAQXQITrZK/PhL9B4W4GAPkANKwdu9uEtNvYionQ9dV8gRGte7lg9D2cRDdAiA==
|
||||
dependencies:
|
||||
nan "^2.14.0"
|
||||
|
||||
@@ -2351,6 +2516,15 @@ os-locale@^2.0.0:
|
||||
lcid "^1.0.0"
|
||||
mem "^1.1.0"
|
||||
|
||||
os-locale@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
|
||||
integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
|
||||
dependencies:
|
||||
execa "^1.0.0"
|
||||
lcid "^2.0.0"
|
||||
mem "^4.0.0"
|
||||
|
||||
os-tmpdir@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
@@ -2364,11 +2538,21 @@ osenv@0, osenv@^0.1.4, osenv@^0.1.5:
|
||||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.0"
|
||||
|
||||
p-defer@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
|
||||
integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
|
||||
|
||||
p-finally@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
|
||||
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
|
||||
|
||||
p-is-promise@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
|
||||
integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
|
||||
|
||||
p-limit@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
|
||||
@@ -2464,6 +2648,11 @@ pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0:
|
||||
unique-filename "^1.1.1"
|
||||
which "^1.3.1"
|
||||
|
||||
pako@^1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
|
||||
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
|
||||
|
||||
parallel-transform@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
|
||||
@@ -2493,7 +2682,7 @@ path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
|
||||
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
|
||||
|
||||
path-key@^2.0.0:
|
||||
path-key@^2.0.0, path-key@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
|
||||
@@ -2528,7 +2717,7 @@ pkg-up@^2.0.0:
|
||||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
prebuild-install@5.3.3, prebuild-install@^5.3.0:
|
||||
prebuild-install@5.3.3:
|
||||
version "5.3.3"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e"
|
||||
integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==
|
||||
@@ -2841,6 +3030,13 @@ resolve@^1.10.0:
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
resolve@^1.3.2:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.0.tgz#6d14c6f9db9f8002071332b600039abf82053f64"
|
||||
integrity sha512-uviWSi5N67j3t3UKFxej1loCH0VZn5XuqdNxoLShPcYPw6cUZn74K1VRj+9myynRX03bxIBEkwlkob/ujLsJVw==
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
retry@^0.10.0:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
|
||||
@@ -2865,15 +3061,15 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
dependencies:
|
||||
aproba "^1.1.1"
|
||||
|
||||
rxjs-compat@^6.5.5:
|
||||
version "6.5.5"
|
||||
resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.5.tgz#073c40510f29c45a2a5fc02dde87f8c3ad75f2c2"
|
||||
integrity sha512-F42sssVbUyWH4vJswEo6m+Eh02xHv3q93n8S7nUJO58R7sbc3CvJIOts605zdaBhWa1xMB9aVSyqPqhQ5q3eXg==
|
||||
rxjs-compat@^6.5.3:
|
||||
version "6.5.3"
|
||||
resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.3.tgz#18440949b2678bf87a78a754009676b2c49183dc"
|
||||
integrity sha512-BIJX2yovz3TBpjJoAZyls2QYuU6ZiCaZ+U96SmxQpuSP/qDUfiXPKOVLbThBB2WZijNHkdTTJXKRwvv5Y48H7g==
|
||||
|
||||
rxjs@^6.5.5:
|
||||
version "6.5.5"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
|
||||
integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
|
||||
rxjs@^6.5.3:
|
||||
version "6.5.3"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
|
||||
integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
@@ -2904,32 +3100,16 @@ semver-diff@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
semver@^7.1.3:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6"
|
||||
integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==
|
||||
semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@~5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
||||
integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
|
||||
|
||||
serialport@^8.0.7:
|
||||
version "8.0.7"
|
||||
resolved "https://registry.yarnpkg.com/serialport/-/serialport-8.0.7.tgz#9f28b1b7c47333a0962f5505a1c3feb1d90f89a9"
|
||||
integrity sha512-R9bfNebs2dblYf5sD/Aaa7j8+siP4X7TGT02lqHM9DF5fyjlrPGXmsLw9+LKOz1AvjGjkxf2NzBVnDpqRX7clQ==
|
||||
dependencies:
|
||||
"@serialport/binding-mock" "^8.0.6"
|
||||
"@serialport/bindings" "^8.0.7"
|
||||
"@serialport/parser-byte-length" "^8.0.6"
|
||||
"@serialport/parser-cctalk" "^8.0.6"
|
||||
"@serialport/parser-delimiter" "^8.0.6"
|
||||
"@serialport/parser-readline" "^8.0.6"
|
||||
"@serialport/parser-ready" "^8.0.6"
|
||||
"@serialport/parser-regex" "^8.0.6"
|
||||
"@serialport/stream" "^8.0.6"
|
||||
debug "^4.1.1"
|
||||
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
@@ -3018,6 +3198,11 @@ sorted-union-stream@~2.1.3:
|
||||
from2 "^1.3.0"
|
||||
stream-iterate "^1.1.0"
|
||||
|
||||
source-map@^0.5.0:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||
|
||||
spdx-correct@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
|
||||
@@ -3119,6 +3304,15 @@ string-width@^1.0.1:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string-width@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
|
||||
dependencies:
|
||||
emoji-regex "^7.0.1"
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^5.1.0"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
|
||||
@@ -3166,6 +3360,13 @@ strip-ansi@^4.0.0:
|
||||
dependencies:
|
||||
ansi-regex "^3.0.0"
|
||||
|
||||
strip-ansi@^5.1.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
|
||||
dependencies:
|
||||
ansi-regex "^4.1.0"
|
||||
|
||||
strip-ansi@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
|
||||
@@ -3282,6 +3483,11 @@ tiny-relative-date@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07"
|
||||
integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
|
||||
|
||||
tough-cookie@~2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
@@ -3343,10 +3549,10 @@ unique-string@^1.0.0:
|
||||
dependencies:
|
||||
crypto-random-string "^1.0.0"
|
||||
|
||||
universalify@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
||||
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
||||
universalify@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -3477,10 +3683,10 @@ windows-blurbehind@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/windows-blurbehind/-/windows-blurbehind-1.0.1.tgz#ff098713873304e38330b2c54cc41bb369b587b9"
|
||||
integrity sha512-1HzHfCiM1ayrbACJu5qE9zELV24uX/tINT6kxaZwLY3rtQAoeav6x9z7LFHWoLaGDN/sYbnK+9Vk0cz7fsk5HQ==
|
||||
|
||||
windows-native-registry@^1.0.17:
|
||||
version "1.0.17"
|
||||
resolved "https://registry.yarnpkg.com/windows-native-registry/-/windows-native-registry-1.0.17.tgz#d8cce48b364703a55c226690431b325114405022"
|
||||
integrity sha512-u9Fp9TyDo5dvhlW6hYBOdHPETtAahXKxo3jeW5EXwNK7qa+nSNopQycN1drtBVWe3jpJXvyKpt9zrjiDd+u4JQ==
|
||||
windows-native-registry@^1.0.16:
|
||||
version "1.0.16"
|
||||
resolved "https://registry.yarnpkg.com/windows-native-registry/-/windows-native-registry-1.0.16.tgz#761f21b7dfa6cdb28479cf9bc66b705592e3ae6a"
|
||||
integrity sha512-RROB5VPEafEJLK93vdttfq4BGWaMWI/OHjAE2cqA31eMjmPShD2KaerlhEfUgqa5THsaAbYUK0LQKc4UQTjIMg==
|
||||
dependencies:
|
||||
nan "^2.14.0"
|
||||
|
||||
@@ -3566,10 +3772,18 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
|
||||
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
|
||||
|
||||
yargs-parser@^18.1.1:
|
||||
version "18.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.1.tgz#bf7407b915427fc760fcbbccc6c82b4f0ffcbd37"
|
||||
integrity sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA==
|
||||
yargs-parser@^13.0.0:
|
||||
version "13.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
|
||||
integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^16.1.0:
|
||||
version "16.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1"
|
||||
integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
@@ -3581,6 +3795,23 @@ yargs-parser@^9.0.2:
|
||||
dependencies:
|
||||
camelcase "^4.1.0"
|
||||
|
||||
yargs@13.1.0:
|
||||
version "13.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.1.0.tgz#b2729ce4bfc0c584939719514099d8a916ad2301"
|
||||
integrity sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==
|
||||
dependencies:
|
||||
cliui "^4.0.0"
|
||||
find-up "^3.0.0"
|
||||
get-caller-file "^2.0.1"
|
||||
os-locale "^3.1.0"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^3.0.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^13.0.0"
|
||||
|
||||
yargs@^11.0.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
|
||||
@@ -3599,10 +3830,10 @@ yargs@^11.0.0:
|
||||
y18n "^3.2.1"
|
||||
yargs-parser "^9.0.2"
|
||||
|
||||
yargs@^15.3.1:
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
|
||||
integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==
|
||||
yargs@^15.0.2:
|
||||
version "15.0.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.0.2.tgz#4248bf218ef050385c4f7e14ebdf425653d13bd3"
|
||||
integrity sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==
|
||||
dependencies:
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
@@ -3614,9 +3845,9 @@ yargs@^15.3.1:
|
||||
string-width "^4.2.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.1"
|
||||
yargs-parser "^16.1.0"
|
||||
|
||||
zone.js@^0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16"
|
||||
integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==
|
||||
zone.js@^0.10.2:
|
||||
version "0.10.2"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.2.tgz#67ca084b3116fc33fc40435e0d5ea40a207e392e"
|
||||
integrity sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg==
|
||||
|
@@ -1,7 +1,4 @@
|
||||
#!/bin/bash
|
||||
cat > '/usr/bin/${executable}' << END
|
||||
#!/bin/sh
|
||||
'/opt/${productFilename}/${executable}' --no-sandbox $@
|
||||
END
|
||||
|
||||
chmod +x '/usr/bin/${executable}'
|
||||
# Link to the binary
|
||||
ln -sf '/opt/${productFilename}/${executable}' '/usr/bin/${executable}'
|
||||
|
@@ -1,16 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const signHook = require('./afterSignHook')
|
||||
|
||||
module.exports = async function (params) {
|
||||
// notarize the app on Mac OS only.
|
||||
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
return
|
||||
}
|
||||
console.log('afterBuild hook triggered')
|
||||
|
||||
let pkgName = fs.readdirSync('dist').find(x => x.endsWith('.pkg'))
|
||||
signHook({
|
||||
appOutDir: 'dist',
|
||||
_pathOverride: pkgName,
|
||||
})
|
||||
}
|
@@ -6,14 +6,14 @@ const notarizer = require('electron-notarize')
|
||||
|
||||
module.exports = async function (params) {
|
||||
// notarize the app on Mac OS only.
|
||||
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
if (process.platform !== 'darwin' || process.env.GITHUB_REF !== 'refs/heads/master' || process.env.GITHUB_REF && !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
return
|
||||
}
|
||||
console.log('afterSign hook triggered', params)
|
||||
|
||||
let appId = 'org.terminus'
|
||||
|
||||
let appPath = path.join(params.appOutDir, params._pathOverride || `${params.packager.appInfo.productFilename}.app`)
|
||||
let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`)
|
||||
if (!fs.existsSync(appPath)) {
|
||||
throw new Error(`Cannot find application at: ${appPath}`)
|
||||
}
|
||||
|
@@ -1,62 +0,0 @@
|
||||
---
|
||||
appId: org.terminus
|
||||
productName: Terminus
|
||||
compression: normal
|
||||
afterSign: "./build/mac/afterSignHook.js"
|
||||
afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
|
||||
files:
|
||||
- "**/*"
|
||||
- dist
|
||||
extraResources:
|
||||
- builtin-plugins
|
||||
- extras
|
||||
publish:
|
||||
- provider: github
|
||||
|
||||
win:
|
||||
icon: "./build/windows/icon.ico"
|
||||
artifactName: terminus-${version}-portable.${ext}
|
||||
rfc3161TimeStampServer: http://sha256timestamp.ws.symantec.com/sha256/timestamp
|
||||
nsis:
|
||||
oneClick: false
|
||||
artifactName: terminus-${version}-setup.${ext}
|
||||
installerIcon: "./build/windows/icon.ico"
|
||||
|
||||
mac:
|
||||
category: public.app-category.video
|
||||
icon: "./build/mac/icon.icns"
|
||||
artifactName: terminus-${version}-macos.${ext}
|
||||
hardenedRuntime: true
|
||||
entitlements: "./build/mac/entitlements.plist"
|
||||
entitlementsInherit: "./build/mac/entitlements.plist"
|
||||
extendInfo:
|
||||
NSRequiresAquaSystemAppearance: false
|
||||
pkg:
|
||||
artifactName: terminus-${version}-macos.pkg
|
||||
|
||||
linux:
|
||||
category: Utilities
|
||||
icon: "./build/icons"
|
||||
artifactName: terminus-${version}-linux.${ext}
|
||||
executableArgs:
|
||||
- "--no-sandbox"
|
||||
snap:
|
||||
plugs:
|
||||
- default
|
||||
- system-files
|
||||
- system-observe
|
||||
deb:
|
||||
depends:
|
||||
- gconf2
|
||||
- gconf-service
|
||||
- gnome-keyring
|
||||
- libnotify4
|
||||
- libsecret-1-0
|
||||
- libappindicator1
|
||||
- libxtst6
|
||||
- libnss3
|
||||
afterInstall: build/linux/after-install.tpl
|
||||
rpm:
|
||||
depends:
|
||||
- screen
|
||||
- gnome-keyring
|
Binary file not shown.
Binary file not shown.
143
package.json
143
package.json
@@ -1,35 +1,39 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||
"@sentry/cli": "^1.52.3",
|
||||
"@sentry/electron": "^1.2.1",
|
||||
"@angular/compiler": "9.0.0-rc.5",
|
||||
"@angular/compiler-cli": "9.0.0-rc.5",
|
||||
"@angular/core": "9.0.0-rc.5",
|
||||
"@fortawesome/fontawesome-free": "^5.11.2",
|
||||
"@ngtools/webpack": "9.0.0-rc.5",
|
||||
"@sentry/cli": "^1.49.0",
|
||||
"@sentry/electron": "^1.0.0",
|
||||
"@types/electron-config": "^3.2.2",
|
||||
"@types/electron-debug": "^2.1.0",
|
||||
"@types/js-yaml": "^3.12.4",
|
||||
"@types/js-yaml": "^3.12.1",
|
||||
"@types/node": "12.7.12",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
||||
"@typescript-eslint/parser": "^2.34.0",
|
||||
"@types/webpack-env": "1.14.1",
|
||||
"@typescript-eslint/eslint-plugin": "^2.9.0",
|
||||
"@typescript-eslint/parser": "^2.10.0",
|
||||
"apply-loader": "2.0.0",
|
||||
"awesome-typescript-loader": "^5.0.0",
|
||||
"core-js": "^3.6.5",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.4.2",
|
||||
"electron": "^8.2.5",
|
||||
"electron-builder": "22.6.1",
|
||||
"core-js": "^3.4.2",
|
||||
"cross-env": "6.0.3",
|
||||
"css-loader": "3.4.0",
|
||||
"electron": "^7.1.3",
|
||||
"electron-builder": "22.1.0",
|
||||
"electron-download": "^4.1.1",
|
||||
"electron-installer-snap": "^5.0.0",
|
||||
"electron-installer-snap": "^4.1.0",
|
||||
"electron-notarize": "^0.1.1",
|
||||
"electron-rebuild": "^1.10.1",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"electron-rebuild": "^1.8.5",
|
||||
"eslint": "^6.7.1",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"file-loader": "^5.0.2",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"html-loader": "0.5.5",
|
||||
"json-loader": "0.5.7",
|
||||
"node-abi": "^2.16.0",
|
||||
"node-gyp": "^6.1.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"node-abi": "^2.12.0",
|
||||
"node-gyp": "^6.0.1",
|
||||
"node-sass": "^4.13.0",
|
||||
"npmlog": "4.1.2",
|
||||
"npx": "^10.2.0",
|
||||
"pug": "^2.0.4",
|
||||
@@ -37,37 +41,104 @@
|
||||
"pug-lint": "^2.6.0",
|
||||
"pug-loader": "^2.4.0",
|
||||
"pug-static-loader": "2.0.0",
|
||||
"raw-loader": "4.0.1",
|
||||
"raw-loader": "4.0.0",
|
||||
"sass-loader": "^8.0.0",
|
||||
"shelljs": "0.8.4",
|
||||
"shelljs": "0.8.3",
|
||||
"source-code-pro": "^2.30.2",
|
||||
"source-sans-pro": "3.6.0",
|
||||
"style-loader": "^1.1.4",
|
||||
"style-loader": "^1.0.1",
|
||||
"svg-inline-loader": "^0.8.0",
|
||||
"to-string-loader": "1.1.6",
|
||||
"tslib": "^2.0.0",
|
||||
"typedoc": "^0.17.6",
|
||||
"typescript": "^3.9.3",
|
||||
"tslib": "^1.10.0",
|
||||
"typedoc": "^0.15.3",
|
||||
"typescript": "^3.7.3",
|
||||
"url-loader": "^3.0.0",
|
||||
"val-loader": "2.1.1",
|
||||
"webpack": "^5.0.0-beta.16",
|
||||
"val-loader": "2.1.0",
|
||||
"webpack": "4",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"yaml-loader": "0.6.0"
|
||||
"yaml-loader": "0.5.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"*/node-abi": "^2.14.0"
|
||||
"*/node-abi": "^2.8.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "org.terminus",
|
||||
"productName": "Terminus",
|
||||
"compression": "normal",
|
||||
"afterSign": "./build/mac/afterSignHook.js",
|
||||
"files": [
|
||||
"**/*",
|
||||
"dist"
|
||||
],
|
||||
"extraResources": [
|
||||
"builtin-plugins",
|
||||
"extras"
|
||||
],
|
||||
"win": {
|
||||
"icon": "./build/windows/icon.ico",
|
||||
"artifactName": "terminus-${version}-setup.exe",
|
||||
"rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"artifactName": "terminus-${version}-setup.${ext}",
|
||||
"installerIcon": "./build/windows/icon.ico"
|
||||
},
|
||||
"publish": [
|
||||
{
|
||||
"provider": "github"
|
||||
}
|
||||
],
|
||||
"portable": {
|
||||
"artifactName": "terminus-${version}-portable.exe"
|
||||
},
|
||||
"mac": {
|
||||
"category": "public.app-category.video",
|
||||
"icon": "./build/mac/icon.icns",
|
||||
"artifactName": "terminus-${version}-macos.${ext}",
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "./build/mac/entitlements.plist",
|
||||
"entitlementsInherit": "./build/mac/entitlements.plist",
|
||||
"extendInfo": {
|
||||
"NSRequiresAquaSystemAppearance": false
|
||||
}
|
||||
},
|
||||
"pkg": {
|
||||
"artifactName": "terminus-${version}-macos.pkg"
|
||||
},
|
||||
"linux": {
|
||||
"category": "Utilities",
|
||||
"icon": "./build/icons",
|
||||
"artifactName": "terminus-${version}-linux.${ext}"
|
||||
},
|
||||
"deb": {
|
||||
"depends": [
|
||||
"gconf2",
|
||||
"gconf-service",
|
||||
"libnotify4",
|
||||
"libsecret-1-0",
|
||||
"libappindicator1",
|
||||
"libxtst6",
|
||||
"libnss3"
|
||||
],
|
||||
"afterInstall": "build/linux/after-install.tpl"
|
||||
},
|
||||
"rpm": {
|
||||
"depends": [
|
||||
"screen",
|
||||
"gnome-python2-gnomekeyring"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build:typings && webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js && webpack --color --config terminus-serial/webpack.config.js",
|
||||
"build:typings": "node scripts/build-typings.js",
|
||||
"build": "npm run build:typings && webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js",
|
||||
"build:typings": "tsc --project terminus-core/tsconfig.typings.json && tsc --project terminus-settings/tsconfig.typings.json && tsc --project terminus-terminal/tsconfig.typings.json && tsc --project terminus-plugin-manager/tsconfig.typings.json && tsc --project terminus-ssh/tsconfig.typings.json",
|
||||
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
|
||||
"start": "cross-env TERMINUS_DEV=1 electron app --debug",
|
||||
"prod": "cross-env TERMINUS_DEV=1 electron app",
|
||||
"docs": "typedoc --out docs/api terminus-core/src && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src",
|
||||
"lint": "eslint --ext ts */src */lib",
|
||||
"lint": "eslint --ext ts */src",
|
||||
"postinstall": "node ./scripts/install-deps.js"
|
||||
},
|
||||
"repository": "eugeny/terminus",
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT"
|
||||
"repository": "eugeny/terminus"
|
||||
}
|
||||
|
@@ -1,10 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
const builder = require('electron-builder').build
|
||||
const vars = require('./vars')
|
||||
const fs = require('fs')
|
||||
const signHook = require('../build/mac/afterSignHook')
|
||||
|
||||
const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/')
|
||||
const isCI = !!process.env.GITHUB_REF
|
||||
|
||||
builder({
|
||||
dir: true,
|
||||
@@ -15,7 +14,4 @@ builder({
|
||||
},
|
||||
},
|
||||
publish: isTag ? 'always' : 'onTag',
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
}).catch(() => process.exit(1))
|
||||
|
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
const sh = require('shelljs')
|
||||
const vars = require('./vars')
|
||||
const log = require('npmlog')
|
||||
|
||||
vars.builtinPlugins.forEach(plugin => {
|
||||
log.info('typings', plugin)
|
||||
sh.exec(`npx tsc --project ${plugin}/tsconfig.typings.json`)
|
||||
})
|
@@ -7,7 +7,7 @@ const isCI = !!process.env.GITHUB_REF
|
||||
|
||||
builder({
|
||||
dir: true,
|
||||
win: ['nsis', 'zip'],
|
||||
win: ['nsis', 'portable'],
|
||||
config: {
|
||||
extraMetadata: {
|
||||
version: vars.version,
|
||||
|
@@ -21,10 +21,5 @@ exports.builtinPlugins = [
|
||||
'terminus-community-color-schemes',
|
||||
'terminus-plugin-manager',
|
||||
'terminus-ssh',
|
||||
'terminus-serial',
|
||||
]
|
||||
exports.bundledModules = [
|
||||
'@angular',
|
||||
'@ng-bootstrap',
|
||||
]
|
||||
exports.electronVersion = electronInfo.version
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-community-color-schemes",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.98-nightly.0",
|
||||
"description": "Community color schemes for Terminus",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"exclude": ["node_modules", "dist", "typings"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "./typings",
|
||||
"paths": {
|
||||
"terminus-*": ["../../terminus-*"],
|
||||
"*": ["../../app/node_modules/*"]
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-core",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.98-nightly.0",
|
||||
"description": "Terminus core",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -30,7 +30,7 @@
|
||||
"ng2-dnd": "^5.0.2",
|
||||
"ngx-perfect-scrollbar": "^8.0.0",
|
||||
"shell-escape": "^0.2.0",
|
||||
"uuid": "^8.0.0",
|
||||
"uuid": "^3.3.2",
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@@ -1,13 +1,11 @@
|
||||
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
|
||||
export { TabHeaderComponent } from '../components/tabHeader.component'
|
||||
export { SplitTabComponent, SplitContainer } from '../components/splitTab.component'
|
||||
export { TabRecoveryProvider, RecoveredTab, RecoveryToken } from './tabRecovery'
|
||||
export { TabRecoveryProvider, RecoveredTab } from './tabRecovery'
|
||||
export { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider'
|
||||
export { ConfigProvider } from './configProvider'
|
||||
export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider'
|
||||
export { Theme } from './theme'
|
||||
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
|
||||
export { SelectorOption } from './selector'
|
||||
|
||||
export { AppService } from '../services/app.service'
|
||||
export { ConfigService } from '../services/config.service'
|
||||
@@ -20,4 +18,3 @@ export { HostAppService, Platform } from '../services/hostApp.service'
|
||||
export { ShellIntegrationService } from '../services/shellIntegration.service'
|
||||
export { ThemesService } from '../services/themes.service'
|
||||
export { TabsService } from '../services/tabs.service'
|
||||
export * from '../utils'
|
||||
|
@@ -1,8 +0,0 @@
|
||||
export interface SelectorOption<T> {
|
||||
name: string
|
||||
description?: string
|
||||
result?: T
|
||||
icon?: string
|
||||
freeInputPattern?: string
|
||||
callback?: (string?) => void
|
||||
}
|
@@ -12,12 +12,6 @@ export interface RecoveredTab {
|
||||
options?: any
|
||||
}
|
||||
|
||||
export interface RecoveryToken {
|
||||
[_: string]: any
|
||||
type: string
|
||||
tabColor?: string|null
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend to enable recovery for your custom tab.
|
||||
* This works in conjunction with [[getRecoveryToken()]]
|
||||
@@ -40,5 +34,5 @@ export abstract class TabRecoveryProvider {
|
||||
* @returns [[RecoveredTab]] descriptor containing tab type and component inputs
|
||||
* or `null` if this token is from a different tab type or is not supported
|
||||
*/
|
||||
abstract async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null>
|
||||
abstract async recover (recoveryToken: any): Promise<RecoveredTab|null>
|
||||
}
|
||||
|
@@ -10,8 +10,8 @@ title-bar(
|
||||
.inset.background(*ngIf='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"')
|
||||
.tabs(
|
||||
dnd-sortable-container,
|
||||
[sortableData]='app.tabs',
|
||||
)
|
||||
//- [sortableData]='app.tabs',
|
||||
tab-header(
|
||||
*ngFor='let tab of app.tabs; let idx = index',
|
||||
dnd-sortable,
|
||||
@@ -38,7 +38,7 @@ title-bar(
|
||||
button.btn.btn-secondary.btn-tab-bar(
|
||||
[title]='button.title',
|
||||
(click)='button.click && button.click()',
|
||||
[fastHtmlBind]='button.icon',
|
||||
[innerHTML]='sanitizeIcon(button.icon)',
|
||||
ngbDropdownToggle,
|
||||
)
|
||||
div(*ngIf='button.submenu', ngbDropdownMenu)
|
||||
@@ -49,7 +49,7 @@ title-bar(
|
||||
)
|
||||
.icon-wrapper(
|
||||
*ngIf='hasIcons(button.submenuItems)',
|
||||
[fastHtmlBind]='item.icon'
|
||||
[innerHTML]='sanitizeIcon(item.icon)'
|
||||
)
|
||||
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
|
||||
|
||||
@@ -64,7 +64,7 @@ title-bar(
|
||||
button.btn.btn-secondary.btn-tab-bar(
|
||||
[title]='button.title',
|
||||
(click)='button.click && button.click()',
|
||||
[fastHtmlBind]='button.icon',
|
||||
[innerHTML]='sanitizeIcon(button.icon)',
|
||||
ngbDropdownToggle,
|
||||
)
|
||||
div(*ngIf='button.submenu', ngbDropdownMenu)
|
||||
@@ -75,7 +75,7 @@ title-bar(
|
||||
)
|
||||
.icon-wrapper(
|
||||
*ngIf='hasIcons(button.submenuItems)',
|
||||
[fastHtmlBind]='item.icon'
|
||||
[innerHTML]='sanitizeIcon(item.icon)'
|
||||
)
|
||||
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
|
||||
|
||||
@@ -83,7 +83,7 @@ title-bar(
|
||||
*ngIf='updatesAvailable',
|
||||
title='Update available - Click to install',
|
||||
(click)='updateApp()',
|
||||
[fastHtmlBind]='updateIcon'
|
||||
[innerHTML]='sanitizeIcon(updateIcon)'
|
||||
)
|
||||
|
||||
window-controls.background(
|
||||
|
@@ -64,7 +64,6 @@ $tab-border-radius: 4px;
|
||||
&>.drag-space {
|
||||
min-width: 1px;
|
||||
flex: 1 0 1%;
|
||||
margin-top: 2px; // for window resizing
|
||||
-webkit-app-region: drag;
|
||||
|
||||
&.persistent {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component, Inject, Input, HostListener, HostBinding } from '@angular/core'
|
||||
import { trigger, style, animate, transition, state } from '@angular/animations'
|
||||
import { DomSanitizer } from '@angular/platform-browser'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
import { ElectronService } from '../services/electron.service'
|
||||
@@ -20,8 +20,8 @@ import { AppService, ToolbarButton, ToolbarButtonProvider } from '../api'
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: require('./appRoot.component.pug'),
|
||||
styles: [require('./appRoot.component.scss')],
|
||||
templateUrl: './appRoot.component.pug',
|
||||
styleUrls: ['./appRoot.component.scss'],
|
||||
animations: [
|
||||
trigger('animateTab', [
|
||||
state('in', style({
|
||||
@@ -75,6 +75,7 @@ export class AppRootComponent {
|
||||
public hostApp: HostAppService,
|
||||
public config: ConfigService,
|
||||
public app: AppService,
|
||||
private domSanitizer: DomSanitizer,
|
||||
@Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[],
|
||||
log: LogService,
|
||||
ngbModal: NgbModal,
|
||||
@@ -108,15 +109,6 @@ export class AppRootComponent {
|
||||
if (hotkey === 'previous-tab') {
|
||||
this.app.previousTab()
|
||||
}
|
||||
if (hotkey === 'move-tab-left') {
|
||||
this.app.moveSelectedTabLeft()
|
||||
}
|
||||
if (hotkey === 'move-tab-right') {
|
||||
this.app.moveSelectedTabRight()
|
||||
}
|
||||
if (hotkey === 'reopen-tab') {
|
||||
this.app.reopenLastTab()
|
||||
}
|
||||
}
|
||||
if (hotkey === 'toggle-fullscreen') {
|
||||
this.hostApp.toggleFullscreen()
|
||||
@@ -128,8 +120,17 @@ export class AppRootComponent {
|
||||
this.docking.dock()
|
||||
})
|
||||
|
||||
this.hostApp.secondInstance$.subscribe(() => {
|
||||
this.presentWindow()
|
||||
})
|
||||
this.hotkeys.globalHotkey.subscribe(() => {
|
||||
this.onGlobalHotkey()
|
||||
})
|
||||
|
||||
this.hostApp.windowCloseRequest$.subscribe(async () => {
|
||||
this.app.closeWindow()
|
||||
if (await this.app.closeAllTabs()) {
|
||||
this.hostApp.closeWindow()
|
||||
}
|
||||
})
|
||||
|
||||
if (window['safeModeReason']) {
|
||||
@@ -168,6 +169,40 @@ export class AppRootComponent {
|
||||
})
|
||||
}
|
||||
|
||||
onGlobalHotkey () {
|
||||
if (this.hostApp.getWindow().isFocused()) {
|
||||
this.hideWindow()
|
||||
} else {
|
||||
this.presentWindow()
|
||||
}
|
||||
}
|
||||
|
||||
presentWindow () {
|
||||
if (!this.hostApp.getWindow().isVisible()) {
|
||||
// unfocused, invisible
|
||||
this.hostApp.getWindow().show()
|
||||
this.hostApp.getWindow().focus()
|
||||
} else {
|
||||
if (this.config.store.appearance.dock === 'off') {
|
||||
// not docked, visible
|
||||
setTimeout(() => {
|
||||
this.hostApp.getWindow().focus()
|
||||
})
|
||||
} else {
|
||||
// docked, visible
|
||||
this.hostApp.getWindow().hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hideWindow () {
|
||||
this.electron.loseFocus()
|
||||
this.hostApp.getWindow().blur()
|
||||
if (this.hostApp.platform !== Platform.macOS) {
|
||||
this.hostApp.getWindow().hide()
|
||||
}
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
this.ready = true
|
||||
|
||||
@@ -219,6 +254,10 @@ export class AppRootComponent {
|
||||
return submenuItems.some(x => !!x.icon)
|
||||
}
|
||||
|
||||
sanitizeIcon (icon: string): any {
|
||||
return this.domSanitizer.bypassSecurityTrustHtml(icon || '')
|
||||
}
|
||||
|
||||
private getToolbarButtons (aboveZero: boolean): ToolbarButton[] {
|
||||
let buttons: ToolbarButton[] = []
|
||||
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { ViewRef } from '@angular/core'
|
||||
import { RecoveryToken } from '../api/tabRecovery'
|
||||
|
||||
/**
|
||||
* Represents an active "process" inside a tab,
|
||||
@@ -14,11 +13,6 @@ export interface BaseTabProcess {
|
||||
* Abstract base class for custom tab components
|
||||
*/
|
||||
export abstract class BaseTabComponent {
|
||||
/**
|
||||
* Parent tab (usually a SplitTabComponent)
|
||||
*/
|
||||
parent: BaseTabComponent|null = null
|
||||
|
||||
/**
|
||||
* Current tab title
|
||||
*/
|
||||
@@ -44,7 +38,7 @@ export abstract class BaseTabComponent {
|
||||
*/
|
||||
color: string|null = null
|
||||
|
||||
hasFocus = false
|
||||
protected hasFocus = false
|
||||
|
||||
/**
|
||||
* Ping this if your recovery state has been changed and you want
|
||||
@@ -68,7 +62,7 @@ export abstract class BaseTabComponent {
|
||||
get destroyed$ (): Observable<void> { return this.destroyed }
|
||||
get recoveryStateChangedHint$ (): Observable<void> { return this.recoveryStateChangedHint }
|
||||
|
||||
protected constructor () {
|
||||
constructor () {
|
||||
this.focused$.subscribe(() => {
|
||||
this.hasFocus = true
|
||||
})
|
||||
@@ -77,7 +71,7 @@ export abstract class BaseTabComponent {
|
||||
})
|
||||
}
|
||||
|
||||
setTitle (title: string): void {
|
||||
setTitle (title: string) {
|
||||
this.title = title
|
||||
if (!this.customTitle) {
|
||||
this.titleChange.next(title)
|
||||
@@ -89,7 +83,7 @@ export abstract class BaseTabComponent {
|
||||
*
|
||||
* @param {type} progress: value between 0 and 1, or `null` to remove
|
||||
*/
|
||||
setProgress (progress: number|null): void {
|
||||
setProgress (progress: number|null) {
|
||||
this.progress.next(progress)
|
||||
if (progress) {
|
||||
if (this.progressClearTimeout) {
|
||||
@@ -124,7 +118,7 @@ export abstract class BaseTabComponent {
|
||||
* @return JSON serializable tab state representation
|
||||
* for your [[TabRecoveryProvider]] to parse
|
||||
*/
|
||||
async getRecoveryToken (): Promise<RecoveryToken|null> {
|
||||
async getRecoveryToken (): Promise<any> {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -142,11 +136,11 @@ export abstract class BaseTabComponent {
|
||||
return true
|
||||
}
|
||||
|
||||
emitFocused (): void {
|
||||
emitFocused () {
|
||||
this.focused.next()
|
||||
}
|
||||
|
||||
emitBlurred (): void {
|
||||
emitBlurred () {
|
||||
this.blurred.next()
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { NgZone, Component, Input, HostBinding, HostListener } from '@angular/core'
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
|
||||
|
||||
|
@@ -1,11 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component, Input, ElementRef, ViewChild } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'rename-tab-modal',
|
||||
template: require('./renameTabModal.component.pug'),
|
||||
templateUrl: './renameTabModal.component.pug',
|
||||
})
|
||||
export class RenameTabModalComponent {
|
||||
@Input() value: string
|
||||
|
@@ -3,7 +3,7 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
template: require('./safeModeModal.component.pug'),
|
||||
templateUrl: './safeModeModal.component.pug',
|
||||
})
|
||||
export class SafeModeModalComponent {
|
||||
@Input() error: Error
|
||||
@@ -14,7 +14,7 @@ export class SafeModeModalComponent {
|
||||
this.error = window['safeModeReason']
|
||||
}
|
||||
|
||||
close (): void {
|
||||
close () {
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
.modal-body
|
||||
input.form-control(
|
||||
type='text',
|
||||
[(ngModel)]='filter',
|
||||
autofocus,
|
||||
[placeholder]='name',
|
||||
(ngModelChange)='onFilterChange()'
|
||||
)
|
||||
|
||||
.list-group.mt-3(*ngIf='filteredOptions.length')
|
||||
a.list-group-item.list-group-item-action.d-flex.align-items-center(
|
||||
#item,
|
||||
(click)='selectOption(option)',
|
||||
[class.active]='selectedIndex == i',
|
||||
*ngFor='let option of filteredOptions; let i = index'
|
||||
)
|
||||
i.icon(
|
||||
class='fa-fw fas fa-{{option.icon}}',
|
||||
*ngIf='!iconIsSVG(option.icon)'
|
||||
)
|
||||
.icon(
|
||||
[fastHtmlBind]='option.icon',
|
||||
*ngIf='iconIsSVG(option.icon)'
|
||||
)
|
||||
.mr-2.title {{getOptionText(option)}}
|
||||
.text-muted {{option.description}}
|
@@ -1,13 +0,0 @@
|
||||
.list-group {
|
||||
max-height: 70vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 1.25rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-left: 10px;
|
||||
}
|
@@ -1,78 +0,0 @@
|
||||
import { Component, Input, HostListener, ViewChildren, QueryList, ElementRef } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { SelectorOption } from '../api/selector'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
template: require('./selectorModal.component.pug'),
|
||||
styles: [require('./selectorModal.component.scss')],
|
||||
})
|
||||
export class SelectorModalComponent<T> {
|
||||
@Input() options: SelectorOption<T>[]
|
||||
@Input() filteredOptions: SelectorOption<T>[]
|
||||
@Input() filter = ''
|
||||
@Input() name: string
|
||||
@Input() selectedIndex = 0
|
||||
@ViewChildren('item') itemChildren: QueryList<ElementRef>
|
||||
|
||||
constructor (
|
||||
public modalInstance: NgbActiveModal,
|
||||
) { }
|
||||
|
||||
ngOnInit (): void {
|
||||
this.onFilterChange()
|
||||
}
|
||||
|
||||
@HostListener('keyup', ['$event']) onKeyUp (event: KeyboardEvent): void {
|
||||
if (event.key === 'ArrowUp') {
|
||||
this.selectedIndex--
|
||||
}
|
||||
if (event.key === 'ArrowDown') {
|
||||
this.selectedIndex++
|
||||
}
|
||||
if (event.key === 'Enter') {
|
||||
this.selectOption(this.filteredOptions[this.selectedIndex])
|
||||
}
|
||||
if (event.key === 'Escape') {
|
||||
this.close()
|
||||
}
|
||||
|
||||
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
|
||||
Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
})
|
||||
}
|
||||
|
||||
onFilterChange (): void {
|
||||
const f = this.filter.trim().toLowerCase()
|
||||
if (!f) {
|
||||
this.filteredOptions = this.options.filter(x => !x.freeInputPattern)
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||
this.filteredOptions = this.options.filter(x => x.freeInputPattern || (x.name + (x.description || '')).toLowerCase().includes(f))
|
||||
}
|
||||
this.selectedIndex = Math.max(0, this.selectedIndex)
|
||||
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
|
||||
}
|
||||
|
||||
getOptionText (option: SelectorOption<T>): string {
|
||||
if (option.freeInputPattern) {
|
||||
return option.freeInputPattern.replace('%s', this.filter)
|
||||
}
|
||||
return option.name
|
||||
}
|
||||
|
||||
selectOption (option: SelectorOption<T>): void {
|
||||
option.callback?.(this.filter)
|
||||
this.modalInstance.close(option.result)
|
||||
}
|
||||
|
||||
close (): void {
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
|
||||
iconIsSVG (icon: string): boolean {
|
||||
return icon?.startsWith('<')
|
||||
}
|
||||
}
|
@@ -3,24 +3,3 @@
|
||||
position: relative;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
::ng-deep split-tab > .child {
|
||||
position: absolute;
|
||||
transition: 0.125s all;
|
||||
opacity: .75;
|
||||
|
||||
&.focused {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.minimized {
|
||||
opacity: .1;
|
||||
}
|
||||
|
||||
&.maximized {
|
||||
z-index: 2;
|
||||
box-shadow: rgba(0, 0, 0, 0.25) 0px 0px 30px;
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Observable, Subject, Subscription } from 'rxjs'
|
||||
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core'
|
||||
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, OnInit, OnDestroy } from '@angular/core'
|
||||
import { BaseTabComponent, BaseTabProcess } from './baseTab.component'
|
||||
import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from '../api/tabRecovery'
|
||||
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery'
|
||||
import { TabsService } from '../services/tabs.service'
|
||||
import { HotkeysService } from '../services/hotkeys.service'
|
||||
import { TabRecoveryService } from '../services/tabRecovery.service'
|
||||
@@ -48,7 +48,7 @@ export class SplitContainer {
|
||||
/**
|
||||
* Remove unnecessarily nested child containers and renormalizes [[ratios]]
|
||||
*/
|
||||
normalize (): void {
|
||||
normalize () {
|
||||
for (let i = 0; i < this.children.length; i++) {
|
||||
const child = this.children[i]
|
||||
|
||||
@@ -93,7 +93,7 @@ export class SplitContainer {
|
||||
return s
|
||||
}
|
||||
|
||||
async serialize (): Promise<RecoveryToken> {
|
||||
async serialize () {
|
||||
const children: any[] = []
|
||||
for (const child of this.children) {
|
||||
if (child instanceof SplitContainer) {
|
||||
@@ -138,11 +138,9 @@ export interface SplitSpannerInfo {
|
||||
(change)='onSpannerAdjusted(spanner)'
|
||||
></split-tab-spanner>
|
||||
`,
|
||||
styles: [require('./splitTab.component.scss')],
|
||||
styleUrls: ['./splitTab.component.scss'],
|
||||
})
|
||||
export class SplitTabComponent extends BaseTabComponent implements AfterViewInit, OnDestroy {
|
||||
static DIRECTIONS: SplitDirection[] = ['t', 'r', 'b', 'l']
|
||||
|
||||
export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
|
||||
/** @hidden */
|
||||
@ViewChild('vc', { read: ViewContainerRef }) viewContainer: ViewContainerRef
|
||||
|
||||
@@ -158,7 +156,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
_spanners: SplitSpannerInfo[] = []
|
||||
|
||||
private focusedTab: BaseTabComponent
|
||||
private maximizedTab: BaseTabComponent|null = null
|
||||
private hotkeysSubscription: Subscription
|
||||
private viewRefs: Map<BaseTabComponent, EmbeddedViewRef<any>> = new Map()
|
||||
|
||||
@@ -166,7 +163,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
private tabRemoved = new Subject<BaseTabComponent>()
|
||||
private splitAdjusted = new Subject<SplitSpannerInfo>()
|
||||
private focusChanged = new Subject<BaseTabComponent>()
|
||||
private initialized = new Subject<void>()
|
||||
|
||||
get tabAdded$ (): Observable<BaseTabComponent> { return this.tabAdded }
|
||||
get tabRemoved$ (): Observable<BaseTabComponent> { return this.tabRemoved }
|
||||
@@ -181,11 +177,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
*/
|
||||
get focusChanged$ (): Observable<BaseTabComponent> { return this.focusChanged }
|
||||
|
||||
/**
|
||||
* Fired once tab layout is created and child tabs can be added
|
||||
*/
|
||||
get initialized$ (): Observable<void> { return this.initialized }
|
||||
|
||||
/** @hidden */
|
||||
constructor (
|
||||
private hotkeys: HotkeysService,
|
||||
@@ -235,13 +226,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
case 'pane-nav-down':
|
||||
this.navigate('b')
|
||||
break
|
||||
case 'pane-maximize':
|
||||
if (this.maximizedTab) {
|
||||
this.maximize(null)
|
||||
} else if (this.getAllTabs().length > 1) {
|
||||
this.maximize(this.focusedTab)
|
||||
}
|
||||
break
|
||||
case 'close-pane':
|
||||
this.removeTab(this.focusedTab)
|
||||
break
|
||||
@@ -250,7 +234,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
async ngAfterViewInit (): Promise<void> {
|
||||
async ngOnInit () {
|
||||
if (this._recoveredState) {
|
||||
await this.recoverContainer(this.root, this._recoveredState)
|
||||
this.layout()
|
||||
@@ -261,17 +245,15 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
})
|
||||
}
|
||||
this.initialized.next()
|
||||
this.initialized.complete()
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
ngOnDestroy (): void {
|
||||
ngOnDestroy () {
|
||||
this.hotkeysSubscription.unsubscribe()
|
||||
}
|
||||
|
||||
/** @returns Flat list of all sub-tabs */
|
||||
getAllTabs (): BaseTabComponent[] {
|
||||
getAllTabs () {
|
||||
return this.root.getAllTabs()
|
||||
}
|
||||
|
||||
@@ -279,11 +261,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
return this.focusedTab
|
||||
}
|
||||
|
||||
getMaximizedTab (): BaseTabComponent|null {
|
||||
return this.maximizedTab
|
||||
}
|
||||
|
||||
focus (tab: BaseTabComponent): void {
|
||||
focus (tab: BaseTabComponent) {
|
||||
this.focusedTab = tab
|
||||
for (const x of this.getAllTabs()) {
|
||||
if (x !== tab) {
|
||||
@@ -294,22 +272,13 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
tab.emitFocused()
|
||||
this.focusChanged.next(tab)
|
||||
}
|
||||
|
||||
if (this.maximizedTab !== tab) {
|
||||
this.maximizedTab = null
|
||||
}
|
||||
this.layout()
|
||||
}
|
||||
|
||||
maximize (tab: BaseTabComponent|null): void {
|
||||
this.maximizedTab = tab
|
||||
this.layout()
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the first available tab inside the given [[SplitContainer]]
|
||||
*/
|
||||
focusAnyIn (parent: BaseTabComponent | SplitContainer): void {
|
||||
focusAnyIn (parent: BaseTabComponent | SplitContainer) {
|
||||
if (!parent) {
|
||||
return
|
||||
}
|
||||
@@ -323,9 +292,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
/**
|
||||
* Inserts a new `tab` to the `side` of the `relative` tab
|
||||
*/
|
||||
async addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection): Promise<void> {
|
||||
tab.parent = this
|
||||
|
||||
addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection) {
|
||||
let target = (relative ? this.getParentOf(relative) : null) || this.root
|
||||
let insertIndex = relative ? target.children.indexOf(relative) : -1
|
||||
|
||||
@@ -355,9 +322,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
target.children.splice(insertIndex, 0, tab)
|
||||
|
||||
this.recoveryStateChangedHint.next()
|
||||
|
||||
await this.initialized$.toPromise()
|
||||
|
||||
this.attachTabView(tab)
|
||||
|
||||
setImmediate(() => {
|
||||
@@ -367,7 +331,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
})
|
||||
}
|
||||
|
||||
removeTab (tab: BaseTabComponent): void {
|
||||
removeTab (tab: BaseTabComponent) {
|
||||
const parent = this.getParentOf(tab)
|
||||
if (!parent) {
|
||||
return
|
||||
@@ -377,11 +341,11 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
parent.children.splice(index, 1)
|
||||
|
||||
this.detachTabView(tab)
|
||||
tab.parent = null
|
||||
|
||||
this.layout()
|
||||
|
||||
this.tabRemoved.next(tab)
|
||||
|
||||
if (this.root.children.length === 0) {
|
||||
this.destroy()
|
||||
} else {
|
||||
@@ -392,7 +356,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
/**
|
||||
* Moves focus in the given direction
|
||||
*/
|
||||
navigate (dir: SplitDirection): void {
|
||||
navigate (dir: SplitDirection) {
|
||||
let rel: BaseTabComponent | SplitContainer = this.focusedTab
|
||||
let parent = this.getParentOf(rel)
|
||||
if (!parent) {
|
||||
@@ -425,12 +389,11 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
}
|
||||
|
||||
async splitTab (tab: BaseTabComponent, dir: SplitDirection): Promise<BaseTabComponent|null> {
|
||||
async splitTab (tab: BaseTabComponent, dir: SplitDirection) {
|
||||
const newTab = await this.tabsService.duplicate(tab)
|
||||
if (newTab) {
|
||||
this.addTab(newTab, tab, dir)
|
||||
}
|
||||
return newTab
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -468,18 +431,11 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
onSpannerAdjusted (spanner: SplitSpannerInfo): void {
|
||||
onSpannerAdjusted (spanner: SplitSpannerInfo) {
|
||||
this.layout()
|
||||
this.splitAdjusted.next(spanner)
|
||||
}
|
||||
|
||||
destroy (): void {
|
||||
super.destroy()
|
||||
for (const x of this.getAllTabs()) {
|
||||
x.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
private attachTabView (tab: BaseTabComponent) {
|
||||
const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any> // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
this.viewRefs.set(tab, ref)
|
||||
@@ -529,25 +485,14 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
if (child instanceof SplitContainer) {
|
||||
this.layoutInternal(child, childX, childY, childW, childH)
|
||||
} else {
|
||||
const viewRef = this.viewRefs.get(child)
|
||||
if (viewRef) {
|
||||
const element = viewRef.rootNodes[0]
|
||||
element.classList.toggle('child', true)
|
||||
element.classList.toggle('maximized', child === this.maximizedTab)
|
||||
element.classList.toggle('minimized', this.maximizedTab && child !== this.maximizedTab)
|
||||
element.classList.toggle('focused', child === this.focusedTab)
|
||||
element.style.left = `${childX}%`
|
||||
element.style.top = `${childY}%`
|
||||
element.style.width = `${childW}%`
|
||||
element.style.height = `${childH}%`
|
||||
const element = this.viewRefs.get(child)!.rootNodes[0]
|
||||
element.style.position = 'absolute'
|
||||
element.style.left = `${childX}%`
|
||||
element.style.top = `${childY}%`
|
||||
element.style.width = `${childW}%`
|
||||
element.style.height = `${childH}%`
|
||||
|
||||
if (child === this.maximizedTab) {
|
||||
element.style.left = '5%'
|
||||
element.style.top = '5%'
|
||||
element.style.width = '90%'
|
||||
element.style.height = '90%'
|
||||
}
|
||||
}
|
||||
element.style.opacity = child === this.focusedTab ? 1 : 0.75
|
||||
}
|
||||
offset += sizes[i]
|
||||
|
||||
@@ -575,24 +520,19 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
if (recovered) {
|
||||
const tab = this.tabsService.create(recovered.type, recovered.options)
|
||||
children.push(tab)
|
||||
tab.parent = this
|
||||
this.attachTabView(tab)
|
||||
} else {
|
||||
state.ratios.splice(state.children.indexOf(childState), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
while (root.ratios.length < root.children.length) {
|
||||
root.ratios.push(1)
|
||||
}
|
||||
root.normalize()
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class SplitTabRecoveryProvider extends TabRecoveryProvider {
|
||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||
async recover (recoveryToken: any): Promise<RecoveredTab|null> {
|
||||
if (recoveryToken && recoveryToken.type === 'app:split-tab') {
|
||||
return {
|
||||
type: SplitTabComponent,
|
||||
|
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component, Input, HostBinding, ElementRef, Output, EventEmitter } from '@angular/core'
|
||||
import { SplitContainer } from './splitTab.component'
|
||||
|
||||
@@ -6,7 +5,7 @@ import { SplitContainer } from './splitTab.component'
|
||||
@Component({
|
||||
selector: 'split-tab-spanner',
|
||||
template: '',
|
||||
styles: [require('./splitTabSpanner.component.scss')],
|
||||
styleUrls: ['./splitTabSpanner.component.scss'],
|
||||
})
|
||||
export class SplitTabSpannerComponent {
|
||||
@Input() container: SplitContainer
|
||||
@@ -17,17 +16,13 @@ export class SplitTabSpannerComponent {
|
||||
@HostBinding('class.v') isVertical = true
|
||||
@HostBinding('style.left') cssLeft: string
|
||||
@HostBinding('style.top') cssTop: string
|
||||
@HostBinding('style.width') cssWidth: string | null
|
||||
@HostBinding('style.height') cssHeight: string | null
|
||||
@HostBinding('style.width') cssWidth: string
|
||||
@HostBinding('style.height') cssHeight: string
|
||||
private marginOffset = -5
|
||||
|
||||
constructor (private element: ElementRef) { }
|
||||
|
||||
ngAfterViewInit () {
|
||||
this.element.nativeElement.addEventListener('dblclick', () => {
|
||||
this.reset()
|
||||
})
|
||||
|
||||
this.element.nativeElement.addEventListener('mousedown', (e: MouseEvent) => {
|
||||
this.isActive = true
|
||||
const start = this.isVertical ? e.pageY : e.pageX
|
||||
@@ -54,16 +49,14 @@ export class SplitTabSpannerComponent {
|
||||
diff = Math.max(diff, -this.container.ratios[this.index - 1] + 0.1)
|
||||
diff = Math.min(diff, this.container.ratios[this.index] - 0.1)
|
||||
|
||||
if (diff) {
|
||||
this.container.ratios[this.index - 1] += diff
|
||||
this.container.ratios[this.index] -= diff
|
||||
this.change.emit()
|
||||
}
|
||||
this.container.ratios[this.index - 1] += diff
|
||||
this.container.ratios[this.index] -= diff
|
||||
this.change.emit()
|
||||
}
|
||||
|
||||
document.addEventListener('mouseup', offHandler, { passive: true })
|
||||
document.addEventListener('mouseup', offHandler)
|
||||
this.element.nativeElement.parentElement.addEventListener('mousemove', dragHandler)
|
||||
}, { passive: true })
|
||||
})
|
||||
}
|
||||
|
||||
ngOnChanges () {
|
||||
@@ -86,17 +79,10 @@ export class SplitTabSpannerComponent {
|
||||
}
|
||||
}
|
||||
|
||||
reset () {
|
||||
const ratio = (this.container.ratios[this.index - 1] + this.container.ratios[this.index]) / 2
|
||||
this.container.ratios[this.index - 1] = ratio
|
||||
this.container.ratios[this.index] = ratio
|
||||
this.change.emit()
|
||||
}
|
||||
|
||||
private setDimensions (x: number, y: number, w: number, h: number) {
|
||||
this.cssLeft = `${x}%`
|
||||
this.cssTop = `${y}%`
|
||||
this.cssWidth = w ? `${w}%` : null
|
||||
this.cssHeight = h ? `${h}%` : null
|
||||
this.cssWidth = w ? `${w}%` : 'initial'
|
||||
this.cssHeight = h ? `${h}%` : 'initial'
|
||||
}
|
||||
}
|
||||
|
@@ -7,13 +7,13 @@ import { ToolbarButton, ToolbarButtonProvider } from '../api'
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'start-page',
|
||||
template: require('./startPage.component.pug'),
|
||||
styles: [require('./startPage.component.scss')],
|
||||
templateUrl: './startPage.component.pug',
|
||||
styleUrls: ['./startPage.component.scss'],
|
||||
})
|
||||
export class StartPageComponent {
|
||||
version: string
|
||||
|
||||
private constructor (
|
||||
constructor (
|
||||
private config: ConfigService,
|
||||
private domSanitizer: DomSanitizer,
|
||||
public homeBase: HomeBaseService,
|
||||
|
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component, Input, ViewChild, HostBinding, ViewContainerRef, OnChanges } from '@angular/core'
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
|
||||
@@ -11,9 +10,9 @@ import { BaseTabComponent } from '../components/baseTab.component'
|
||||
</perfect-scrollbar-->
|
||||
<ng-template #placeholder></ng-template>
|
||||
`,
|
||||
styles: [
|
||||
require('./tabBody.component.scss'),
|
||||
require('./tabBody.deep.component.css'),
|
||||
styleUrls: [
|
||||
'./tabBody.component.scss',
|
||||
'./tabBody.deep.component.css',
|
||||
],
|
||||
})
|
||||
export class TabBodyComponent implements OnChanges {
|
||||
|
@@ -20,7 +20,7 @@ $tabs-height: 38px;
|
||||
cursor: -webkit-grab;
|
||||
|
||||
margin-left: 10px;
|
||||
width: 22px;
|
||||
width: 20px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
transition: 0.25s all;
|
||||
|
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core'
|
||||
import { SortableComponent } from 'ng2-dnd'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
@@ -18,8 +17,8 @@ export interface SortableComponentProxy {
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'tab-header',
|
||||
template: require('./tabHeader.component.pug'),
|
||||
styles: [require('./tabHeader.component.scss')],
|
||||
templateUrl: './tabHeader.component.pug',
|
||||
styleUrls: ['./tabHeader.component.scss'],
|
||||
})
|
||||
export class TabHeaderComponent {
|
||||
@Input() index: number
|
||||
@@ -49,15 +48,12 @@ export class TabHeaderComponent {
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
this.tab.progress$.subscribe(progress => {
|
||||
this.progress = progress
|
||||
})
|
||||
}
|
||||
|
||||
ngAfterViewInit () {
|
||||
if (this.hostApp.platform === Platform.macOS) {
|
||||
this.parentDraggable.setDragHandle(this.handle.nativeElement)
|
||||
}
|
||||
this.tab.progress$.subscribe(progress => {
|
||||
this.progress = progress
|
||||
})
|
||||
}
|
||||
|
||||
showRenameTabModal (): void {
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { HostAppService } from '../services/hostApp.service'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'title-bar',
|
||||
template: require('./titleBar.component.pug'),
|
||||
styles: [require('./titleBar.component.scss')],
|
||||
templateUrl: './titleBar.component.pug',
|
||||
styleUrls: ['./titleBar.component.scss'],
|
||||
})
|
||||
export class TitleBarComponent { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
export class TitleBarComponent {
|
||||
constructor (public hostApp: HostAppService) { }
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ import { CheckboxComponent } from './checkbox.component'
|
||||
<label class="custom-control-label"></label>
|
||||
</div>
|
||||
`,
|
||||
styles: [require('./toggle.component.scss')],
|
||||
styleUrls: ['./toggle.component.scss'],
|
||||
providers: [
|
||||
{ provide: NG_VALUE_ACCESSOR, useExisting: ToggleComponent, multi: true },
|
||||
],
|
||||
|
@@ -1,29 +1,19 @@
|
||||
.container.mt-5.mb-5
|
||||
.mb-4
|
||||
.terminus-logo
|
||||
h1.terminus-title Terminus
|
||||
sup α
|
||||
.mb-4
|
||||
.terminus-logo
|
||||
h1.terminus-title Terminus
|
||||
sup α
|
||||
|
||||
.container
|
||||
.text-center.mb-5 Thank you for downloading Terminus!
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Enable analytics
|
||||
.description Help us track the number of Terminus installs across the world!
|
||||
toggle([(ngModel)]='config.store.enableAnalytics')
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Enable SSH plugin
|
||||
.description Adds an SSH connection manager UI to Terminus
|
||||
toggle([(ngModel)]='enableSSH')
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Enable Serial plugin
|
||||
.description Allows attaching Terminus to serial ports
|
||||
toggle([(ngModel)]='enableSerial')
|
||||
|
||||
toggle(
|
||||
[(ngModel)]='config.store.enableAnalytics',
|
||||
(ngModelChange)='config.save(); config.requestRestart()',
|
||||
)
|
||||
|
||||
.text-center.mt-5
|
||||
button.btn.btn-primary((click)='closeAndDisable()') Close and never show again
|
||||
|
@@ -2,7 +2,5 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: auto;
|
||||
flex: auto;
|
||||
max-height: 100%;
|
||||
overflow-y: auto;
|
||||
flex: 0 1 500px;
|
||||
}
|
||||
|
@@ -1,39 +1,26 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component } from '@angular/core'
|
||||
import { BaseTabComponent } from './baseTab.component'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { HostAppService } from '../services/hostApp.service'
|
||||
import { AppService } from '../services/app.service'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'welcome-page',
|
||||
template: require('./welcomeTab.component.pug'),
|
||||
styles: [require('./welcomeTab.component.scss')],
|
||||
templateUrl: './welcomeTab.component.pug',
|
||||
styleUrls: ['./welcomeTab.component.scss'],
|
||||
})
|
||||
export class WelcomeTabComponent extends BaseTabComponent {
|
||||
enableSSH = false
|
||||
enableSerial = false
|
||||
|
||||
constructor (
|
||||
private hostApp: HostAppService,
|
||||
private app: AppService,
|
||||
public config: ConfigService,
|
||||
) {
|
||||
super()
|
||||
this.setTitle('Welcome')
|
||||
this.enableSSH = !config.store.pluginBlacklist.includes('ssh')
|
||||
this.enableSerial = !config.store.pluginBlacklist.includes('serial')
|
||||
}
|
||||
|
||||
closeAndDisable () {
|
||||
this.config.store.enableWelcomeTab = false
|
||||
this.config.store.pluginBlacklist = []
|
||||
if (!this.enableSSH) {
|
||||
this.config.store.pluginBlacklist.push('ssh')
|
||||
}
|
||||
if (!this.enableSerial) {
|
||||
this.config.store.pluginBlacklist.push('serial')
|
||||
}
|
||||
this.config.save()
|
||||
this.hostApp.getWindow().reload()
|
||||
this.app.closeTab(this)
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component } from '@angular/core'
|
||||
import { HostAppService } from '../services/hostApp.service'
|
||||
import { AppService } from '../services/app.service'
|
||||
@@ -6,13 +5,15 @@ import { AppService } from '../services/app.service'
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'window-controls',
|
||||
template: require('./windowControls.component.pug'),
|
||||
styles: [require('./windowControls.component.scss')],
|
||||
templateUrl: './windowControls.component.pug',
|
||||
styleUrls: ['./windowControls.component.scss'],
|
||||
})
|
||||
export class WindowControlsComponent {
|
||||
private constructor (public hostApp: HostAppService, public app: AppService) { }
|
||||
constructor (public hostApp: HostAppService, public app: AppService) { }
|
||||
|
||||
async closeWindow () {
|
||||
this.app.closeWindow()
|
||||
if (await this.app.closeAllTabs()) {
|
||||
this.hostApp.closeWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,8 +7,6 @@ hotkeys:
|
||||
- 'F11'
|
||||
close-tab:
|
||||
- 'Ctrl-Shift-W'
|
||||
reopen-tab:
|
||||
- 'Ctrl-Shift-T'
|
||||
toggle-last-tab: []
|
||||
rename-tab:
|
||||
- 'Ctrl-Shift-R'
|
||||
@@ -18,10 +16,6 @@ hotkeys:
|
||||
previous-tab:
|
||||
- 'Ctrl-Shift-Left'
|
||||
- 'Ctrl-Shift-Tab'
|
||||
move-tab-left:
|
||||
- 'Ctrl-Shift-PageUp'
|
||||
move-tab-right:
|
||||
- 'Ctrl-Shift-PageDown'
|
||||
tab-1:
|
||||
- 'Alt-1'
|
||||
tab-2:
|
||||
@@ -56,7 +50,5 @@ hotkeys:
|
||||
- 'Ctrl-Alt-Up'
|
||||
pane-nav-left:
|
||||
- 'Ctrl-Alt-Left'
|
||||
pane-maximize:
|
||||
- 'Ctrl-Alt-Enter'
|
||||
close-pane: []
|
||||
pluginBlacklist: ['ssh']
|
||||
|
@@ -7,8 +7,6 @@ hotkeys:
|
||||
- 'Ctrl+⌘+F'
|
||||
close-tab:
|
||||
- '⌘-W'
|
||||
reopen-tab:
|
||||
- '⌘-Shift-T'
|
||||
toggle-last-tab: []
|
||||
rename-tab:
|
||||
- '⌘-R'
|
||||
@@ -16,10 +14,6 @@ hotkeys:
|
||||
- 'Ctrl-Tab'
|
||||
previous-tab:
|
||||
- 'Ctrl-Shift-Tab'
|
||||
move-tab-left:
|
||||
- '⌘-Shift-Left'
|
||||
move-tab-right:
|
||||
- '⌘-Shift-Right'
|
||||
tab-1:
|
||||
- '⌘-1'
|
||||
tab-2:
|
||||
@@ -54,8 +48,6 @@ hotkeys:
|
||||
- '⌘-⌥-Up'
|
||||
pane-nav-left:
|
||||
- '⌘-⌥-Left'
|
||||
pane-maximize:
|
||||
- '⌘-⌥-Enter'
|
||||
close-pane:
|
||||
- '⌘-Shift-W'
|
||||
pluginBlacklist: ['ssh']
|
||||
|
@@ -5,11 +5,8 @@ hotkeys:
|
||||
- 'Ctrl+Space'
|
||||
toggle-fullscreen:
|
||||
- 'F11'
|
||||
- 'Alt-Enter'
|
||||
close-tab:
|
||||
- 'Ctrl-Shift-W'
|
||||
reopen-tab:
|
||||
- 'Ctrl-Shift-T'
|
||||
toggle-last-tab: []
|
||||
rename-tab:
|
||||
- 'Ctrl-Shift-R'
|
||||
@@ -19,10 +16,6 @@ hotkeys:
|
||||
previous-tab:
|
||||
- 'Ctrl-Shift-Left'
|
||||
- 'Ctrl-Shift-Tab'
|
||||
move-tab-left:
|
||||
- 'Ctrl-Shift-PageUp'
|
||||
move-tab-right:
|
||||
- 'Ctrl-Shift-PageDown'
|
||||
tab-1:
|
||||
- 'Alt-1'
|
||||
tab-2:
|
||||
@@ -57,7 +50,5 @@ hotkeys:
|
||||
- 'Ctrl-Alt-Up'
|
||||
pane-nav-left:
|
||||
- 'Ctrl-Alt-Left'
|
||||
pane-maximize:
|
||||
- 'Ctrl-Alt-Enter'
|
||||
close-pane: []
|
||||
pluginBlacklist: []
|
||||
|
@@ -2,15 +2,13 @@ appearance:
|
||||
dock: off
|
||||
dockScreen: current
|
||||
dockFill: 0.5
|
||||
dockHideOnBlur: false
|
||||
dockAlwaysOnTop: true
|
||||
tabsLocation: top
|
||||
cycleTabs: true
|
||||
theme: Standard
|
||||
frame: thin
|
||||
css: '/* * { color: blue !important; } */'
|
||||
opacity: 1.0
|
||||
vibrancy: true
|
||||
vibrancy: false
|
||||
vibrancyType: 'blur'
|
||||
enableAnalytics: true
|
||||
enableWelcomeTab: true
|
||||
|
@@ -7,7 +7,7 @@ import { Directive, AfterViewInit, ElementRef } from '@angular/core'
|
||||
export class AutofocusDirective implements AfterViewInit {
|
||||
constructor (private el: ElementRef) { }
|
||||
|
||||
ngAfterViewInit (): void {
|
||||
ngAfterViewInit () {
|
||||
this.el.nativeElement.blur()
|
||||
setTimeout(() => {
|
||||
this.el.nativeElement.focus()
|
||||
|
@@ -1,14 +0,0 @@
|
||||
import { Directive, Input, ElementRef, OnChanges } from '@angular/core'
|
||||
|
||||
/** @hidden */
|
||||
@Directive({
|
||||
selector: '[fastHtmlBind]',
|
||||
})
|
||||
export class FastHtmlBindDirective implements OnChanges {
|
||||
@Input() fastHtmlBind: string
|
||||
constructor (private el: ElementRef) { }
|
||||
|
||||
ngOnChanges (): void {
|
||||
this.el.nativeElement.innerHTML = this.fastHtmlBind || ''
|
||||
}
|
||||
}
|
@@ -25,10 +25,6 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
||||
id: 'close-tab',
|
||||
name: 'Close tab',
|
||||
},
|
||||
{
|
||||
id: 'reopen-tab',
|
||||
name: 'Reopen last tab',
|
||||
},
|
||||
{
|
||||
id: 'toggle-last-tab',
|
||||
name: 'Toggle last tab',
|
||||
@@ -41,14 +37,6 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
||||
id: 'previous-tab',
|
||||
name: 'Previous tab',
|
||||
},
|
||||
{
|
||||
id: 'move-tab-left',
|
||||
name: 'Move tab to the left',
|
||||
},
|
||||
{
|
||||
id: 'move-tab-right',
|
||||
name: 'Move tab to the right',
|
||||
},
|
||||
{
|
||||
id: 'tab-1',
|
||||
name: 'Tab 1',
|
||||
@@ -105,10 +93,6 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
||||
id: 'split-top',
|
||||
name: 'Split to the top',
|
||||
},
|
||||
{
|
||||
id: 'pane-maximize',
|
||||
name: 'Maximize the active pane',
|
||||
},
|
||||
{
|
||||
id: 'pane-nav-up',
|
||||
name: 'Focus the pane above',
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { PerfectScrollbarModule, PERFECT_SCROLLBAR_CONFIG } from 'ngx-perfect-scrollbar'
|
||||
import { DndModule } from 'ng2-dnd'
|
||||
// import { DndModule } from 'ng2-dnd'
|
||||
|
||||
import { AppRootComponent } from './components/appRoot.component'
|
||||
import { CheckboxComponent } from './components/checkbox.component'
|
||||
@@ -16,18 +17,16 @@ import { TitleBarComponent } from './components/titleBar.component'
|
||||
import { ToggleComponent } from './components/toggle.component'
|
||||
import { WindowControlsComponent } from './components/windowControls.component'
|
||||
import { RenameTabModalComponent } from './components/renameTabModal.component'
|
||||
import { SelectorModalComponent } from './components/selectorModal.component'
|
||||
import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component'
|
||||
import { SplitTabSpannerComponent } from './components/splitTabSpanner.component'
|
||||
import { WelcomeTabComponent } from './components/welcomeTab.component'
|
||||
|
||||
import { AutofocusDirective } from './directives/autofocus.directive'
|
||||
import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive'
|
||||
|
||||
import { HotkeyProvider } from './api/hotkeyProvider'
|
||||
import { ConfigProvider } from './api/configProvider'
|
||||
import { Theme } from './api/theme'
|
||||
import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
|
||||
// import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
|
||||
import { TabRecoveryProvider } from './api/tabRecovery'
|
||||
|
||||
import { AppService } from './services/app.service'
|
||||
@@ -36,7 +35,7 @@ import { ConfigService } from './services/config.service'
|
||||
import { StandardTheme, StandardCompactTheme, PaperTheme } from './theme'
|
||||
import { CoreConfigProvider } from './config'
|
||||
import { AppHotkeyProvider } from './hotkeys'
|
||||
import { TaskCompletionContextMenu, CommonOptionsContextMenu, TabManagementContextMenu } from './tabContextMenu'
|
||||
// import { TaskCompletionContextMenu, CommonOptionsContextMenu, CloseContextMenu } from './tabContextMenu'
|
||||
|
||||
import 'perfect-scrollbar/css/perfect-scrollbar.css'
|
||||
import 'ng2-dnd/bundles/style.css'
|
||||
@@ -53,9 +52,9 @@ const PROVIDERS = [
|
||||
{ provide: Theme, useClass: StandardCompactTheme, multi: true },
|
||||
{ provide: Theme, useClass: PaperTheme, multi: true },
|
||||
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: CommonOptionsContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: TabManagementContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: TaskCompletionContextMenu, multi: true },
|
||||
// { provide: TabContextMenuItemProvider, useClass: CommonOptionsContextMenu, multi: true },
|
||||
// { provide: TabContextMenuItemProvider, useClass: CloseContextMenu, multi: true },
|
||||
// { provide: TabContextMenuItemProvider, useClass: TaskCompletionContextMenu, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: SplitTabRecoveryProvider, multi: true },
|
||||
{ provide: PERFECT_SCROLLBAR_CONFIG, useValue: { suppressScrollX: true } },
|
||||
]
|
||||
@@ -68,8 +67,9 @@ const PROVIDERS = [
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
PerfectScrollbarModule,
|
||||
DndModule.forRoot(),
|
||||
// DndModule,
|
||||
],
|
||||
providers: PROVIDERS,
|
||||
declarations: [
|
||||
AppRootComponent as any,
|
||||
CheckboxComponent,
|
||||
@@ -82,8 +82,6 @@ const PROVIDERS = [
|
||||
RenameTabModalComponent,
|
||||
SafeModeModalComponent,
|
||||
AutofocusDirective,
|
||||
FastHtmlBindDirective,
|
||||
SelectorModalComponent,
|
||||
SplitTabComponent,
|
||||
SplitTabSpannerComponent,
|
||||
WelcomeTabComponent,
|
||||
@@ -91,7 +89,6 @@ const PROVIDERS = [
|
||||
entryComponents: [
|
||||
RenameTabModalComponent,
|
||||
SafeModeModalComponent,
|
||||
SelectorModalComponent,
|
||||
SplitTabComponent,
|
||||
WelcomeTabComponent,
|
||||
],
|
||||
@@ -101,7 +98,7 @@ const PROVIDERS = [
|
||||
AutofocusDirective,
|
||||
],
|
||||
})
|
||||
export default class AppModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
export class AppModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
constructor (app: AppService, config: ConfigService) {
|
||||
app.ready$.subscribe(() => {
|
||||
if (config.store.enableWelcomeTab) {
|
||||
@@ -109,18 +106,17 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static forRoot (): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: AppModule,
|
||||
providers: PROVIDERS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AppModule
|
||||
|
||||
export { AppRootComponent as bootstrap }
|
||||
export * from './api'
|
||||
|
||||
// Deprecations
|
||||
export { ToolbarButton as IToolbarButton } from './api'
|
||||
export { HotkeyDescription as IHotkeyDescription } from './api'
|
||||
|
||||
export function fakeBootstrap () {
|
||||
return platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
}
|
||||
|
@@ -2,13 +2,9 @@
|
||||
import { Observable, Subject, AsyncSubject } from 'rxjs'
|
||||
import { takeUntil } from 'rxjs/operators'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { SplitTabComponent } from '../components/splitTab.component'
|
||||
import { SelectorModalComponent } from '../components/selectorModal.component'
|
||||
import { SelectorOption } from '../api/selector'
|
||||
import { RecoveryToken } from '../api/tabRecovery'
|
||||
|
||||
import { ConfigService } from './config.service'
|
||||
import { HostAppService } from './hostApp.service'
|
||||
@@ -50,7 +46,6 @@ export class AppService {
|
||||
|
||||
private lastTabIndex = 0
|
||||
private _activeTab: BaseTabComponent
|
||||
private closedTabsStack: RecoveryToken[] = []
|
||||
|
||||
private activeTabChange = new Subject<BaseTabComponent>()
|
||||
private tabsChanged = new Subject<void>()
|
||||
@@ -69,53 +64,38 @@ export class AppService {
|
||||
get ready$ (): Observable<void> { return this.ready }
|
||||
|
||||
/** @hidden */
|
||||
private constructor (
|
||||
constructor (
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
private tabRecovery: TabRecoveryService,
|
||||
private tabsService: TabsService,
|
||||
private ngbModal: NgbModal,
|
||||
) {
|
||||
this.tabsChanged$.subscribe(() => {
|
||||
this.tabRecovery.saveTabs(this.tabs)
|
||||
})
|
||||
setInterval(() => {
|
||||
this.tabRecovery.saveTabs(this.tabs)
|
||||
}, 30000)
|
||||
|
||||
if (hostApp.getWindow().id === 1) {
|
||||
if (config.store.terminal.recoverTabs) {
|
||||
this.tabRecovery.recoverTabs().then(tabs => {
|
||||
for (const tab of tabs) {
|
||||
this.openNewTabRaw(tab.type, tab.options)
|
||||
}
|
||||
this.tabRecovery.enabled = true
|
||||
this.startTabStorage()
|
||||
})
|
||||
} else {
|
||||
/** Continue to store the tabs even if the setting is currently off */
|
||||
this.tabRecovery.enabled = true
|
||||
this.startTabStorage()
|
||||
}
|
||||
}
|
||||
|
||||
hostApp.windowFocused$.subscribe(() => {
|
||||
this._activeTab?.emitFocused()
|
||||
})
|
||||
|
||||
this.tabClosed$.subscribe(async tab => {
|
||||
const token = await tab.getRecoveryToken()
|
||||
if (token) {
|
||||
this.closedTabsStack.push(token)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
addTabRaw (tab: BaseTabComponent, index: number|null = null): void {
|
||||
if (index !== null) {
|
||||
this.tabs.splice(index, 0, tab)
|
||||
} else {
|
||||
this.tabs.push(tab)
|
||||
}
|
||||
startTabStorage () {
|
||||
this.tabsChanged$.subscribe(() => {
|
||||
this.tabRecovery.saveTabs(this.tabs)
|
||||
})
|
||||
setInterval(() => {
|
||||
this.tabRecovery.saveTabs(this.tabs)
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
addTabRaw (tab: BaseTabComponent) {
|
||||
this.tabs.push(tab)
|
||||
this.selectTab(tab)
|
||||
this.tabsChanged.next()
|
||||
this.tabOpened.next(tab)
|
||||
@@ -141,18 +121,13 @@ export class AppService {
|
||||
this.tabsChanged.next()
|
||||
this.tabClosed.next(tab)
|
||||
})
|
||||
|
||||
if (tab instanceof SplitTabComponent) {
|
||||
tab.tabAdded$.subscribe(() => this.emitTabsChanged())
|
||||
tab.tabRemoved$.subscribe(() => this.emitTabsChanged())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new tab **without** wrapping it in a SplitTabComponent
|
||||
* @param inputs Properties to be assigned on the new tab component instance
|
||||
*/
|
||||
openNewTabRaw (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
|
||||
openNewTabRaw (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||
const tab = this.tabsService.create(type, inputs)
|
||||
this.addTabRaw(tab)
|
||||
return tab
|
||||
@@ -162,7 +137,7 @@ export class AppService {
|
||||
* Adds a new tab while wrapping it in a SplitTabComponent
|
||||
* @param inputs Properties to be assigned on the new tab component instance
|
||||
*/
|
||||
openNewTab (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
|
||||
openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||
const splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent
|
||||
const tab = this.tabsService.create(type, inputs)
|
||||
splitTab.addTab(tab, null, 'r')
|
||||
@@ -170,24 +145,7 @@ export class AppService {
|
||||
return tab
|
||||
}
|
||||
|
||||
async reopenLastTab (): Promise<BaseTabComponent|null> {
|
||||
const token = this.closedTabsStack.pop()
|
||||
if (token) {
|
||||
const recoveredTab = await this.tabRecovery.recoverTab(token)
|
||||
if (recoveredTab) {
|
||||
const tab = this.tabsService.create(recoveredTab.type, recoveredTab.options)
|
||||
if (this.activeTab) {
|
||||
this.addTabRaw(tab, this.tabs.indexOf(this.activeTab) + 1)
|
||||
} else {
|
||||
this.addTabRaw(tab)
|
||||
}
|
||||
return tab
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
selectTab (tab: BaseTabComponent): void {
|
||||
selectTab (tab: BaseTabComponent) {
|
||||
if (this._activeTab === tab) {
|
||||
this._activeTab.emitFocused()
|
||||
return
|
||||
@@ -211,26 +169,15 @@ export class AppService {
|
||||
}
|
||||
}
|
||||
|
||||
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
||||
for (const topLevelTab of this.tabs) {
|
||||
if (topLevelTab instanceof SplitTabComponent) {
|
||||
if (topLevelTab.getAllTabs().includes(tab)) {
|
||||
return topLevelTab
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/** Switches between the current tab and the previously active one */
|
||||
toggleLastTab (): void {
|
||||
toggleLastTab () {
|
||||
if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) {
|
||||
this.lastTabIndex = 0
|
||||
}
|
||||
this.selectTab(this.tabs[this.lastTabIndex])
|
||||
}
|
||||
|
||||
nextTab (): void {
|
||||
nextTab () {
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex < this.tabs.length - 1) {
|
||||
@@ -241,7 +188,7 @@ export class AppService {
|
||||
}
|
||||
}
|
||||
|
||||
previousTab (): void {
|
||||
previousTab () {
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex > 0) {
|
||||
@@ -252,37 +199,8 @@ export class AppService {
|
||||
}
|
||||
}
|
||||
|
||||
moveSelectedTabLeft (): void {
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex > 0) {
|
||||
this.swapTabs(this._activeTab, this.tabs[tabIndex - 1])
|
||||
} else if (this.config.store.appearance.cycleTabs) {
|
||||
this.swapTabs(this._activeTab, this.tabs[this.tabs.length - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moveSelectedTabRight (): void {
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex < this.tabs.length - 1) {
|
||||
this.swapTabs(this._activeTab, this.tabs[tabIndex + 1])
|
||||
} else if (this.config.store.appearance.cycleTabs) {
|
||||
this.swapTabs(this._activeTab, this.tabs[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
swapTabs (a: BaseTabComponent, b: BaseTabComponent): void {
|
||||
const i1 = this.tabs.indexOf(a)
|
||||
const i2 = this.tabs.indexOf(b)
|
||||
this.tabs[i1] = b
|
||||
this.tabs[i2] = a
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
emitTabsChanged (): void {
|
||||
emitTabsChanged () {
|
||||
this.tabsChanged.next()
|
||||
}
|
||||
|
||||
@@ -296,12 +214,11 @@ export class AppService {
|
||||
tab.destroy()
|
||||
}
|
||||
|
||||
async duplicateTab (tab: BaseTabComponent): Promise<BaseTabComponent|null> {
|
||||
async duplicateTab (tab: BaseTabComponent) {
|
||||
const dup = await this.tabsService.duplicate(tab)
|
||||
if (dup) {
|
||||
this.addTabRaw(dup, this.tabs.indexOf(tab) + 1)
|
||||
this.addTabRaw(dup)
|
||||
}
|
||||
return dup
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,18 +236,8 @@ export class AppService {
|
||||
return true
|
||||
}
|
||||
|
||||
async closeWindow (): Promise<void> {
|
||||
this.tabRecovery.enabled = false
|
||||
await this.tabRecovery.saveTabs(this.tabs)
|
||||
if (await this.closeAllTabs()) {
|
||||
this.hostApp.closeWindow()
|
||||
} else {
|
||||
this.tabRecovery.enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
emitReady (): void {
|
||||
emitReady () {
|
||||
this.ready.next()
|
||||
this.ready.complete()
|
||||
this.hostApp.emitReady()
|
||||
@@ -351,15 +258,7 @@ export class AppService {
|
||||
return this.completionObservers.get(tab)!.done$
|
||||
}
|
||||
|
||||
stopObservingTabCompletion (tab: BaseTabComponent): void {
|
||||
stopObservingTabCompletion (tab: BaseTabComponent) {
|
||||
this.completionObservers.delete(tab)
|
||||
}
|
||||
|
||||
showSelector <T> (name: string, options: SelectorOption<T>[]): Promise<T> {
|
||||
const modal = this.ngbModal.open(SelectorModalComponent)
|
||||
const instance: SelectorModalComponent<T> = modal.componentInstance
|
||||
instance.name = name
|
||||
instance.options = options
|
||||
return modal.result as Promise<T>
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ function isNonStructuralObjectMember (v): boolean {
|
||||
|
||||
/** @hidden */
|
||||
export class ConfigProxy {
|
||||
constructor (real: Record<string, any>, defaults: Record<string, any>) {
|
||||
constructor (real: any, defaults: any) {
|
||||
for (const key in defaults) {
|
||||
if (isStructuralMember(defaults[key])) {
|
||||
if (!real[key]) {
|
||||
@@ -71,10 +71,8 @@ export class ConfigProxy {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
|
||||
getValue (_key: string): any { }
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
|
||||
setValue (_key: string, _value: any) { }
|
||||
getValue (_key: string): any { } // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
setValue (_key: string, _value: any) { } // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@@ -102,7 +100,7 @@ export class ConfigService {
|
||||
get changed$ (): Observable<void> { return this.changed }
|
||||
|
||||
/** @hidden */
|
||||
private constructor (
|
||||
constructor (
|
||||
electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
@Inject(ConfigProvider) configProviders: ConfigProvider[],
|
||||
@@ -126,23 +124,8 @@ export class ConfigService {
|
||||
})
|
||||
}
|
||||
|
||||
getDefaults (): Record<string, any> {
|
||||
const cleanup = o => {
|
||||
if (o instanceof Array) {
|
||||
return o.map(cleanup)
|
||||
} else if (o instanceof Object) {
|
||||
const r = {}
|
||||
for (const k of Object.keys(o)) {
|
||||
if (k !== '__nonStructural') {
|
||||
r[k] = cleanup(o[k])
|
||||
}
|
||||
}
|
||||
return r
|
||||
} else {
|
||||
return o
|
||||
}
|
||||
}
|
||||
return cleanup(this.defaults)
|
||||
getDefaults () {
|
||||
return this.defaults
|
||||
}
|
||||
|
||||
load (): void {
|
||||
@@ -155,11 +138,9 @@ export class ConfigService {
|
||||
}
|
||||
|
||||
save (): void {
|
||||
// Scrub undefined values
|
||||
this._store = JSON.parse(JSON.stringify(this._store))
|
||||
fs.writeFileSync(this.path, yaml.safeDump(this._store), 'utf8')
|
||||
this.emitChange()
|
||||
this.hostApp.broadcastConfigChange(this.store)
|
||||
this.hostApp.broadcastConfigChange()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,11 +173,11 @@ export class ConfigService {
|
||||
enabledServices<T extends object> (services: T[]): T[] {
|
||||
if (!this.servicesCache) {
|
||||
this.servicesCache = {}
|
||||
const ngModule = window['rootModule'].ɵinj
|
||||
const ngModule = window['rootModule'].ngInjectorDef
|
||||
for (const imp of ngModule.imports) {
|
||||
const module = imp['ngModule'] || imp
|
||||
if (module.ɵinj?.providers) {
|
||||
this.servicesCache[module['pluginName']] = module.ɵinj.providers.map(provider => {
|
||||
if (module.ngInjectorDef && module.ngInjectorDef.providers) {
|
||||
this.servicesCache[module['pluginName']] = module.ngInjectorDef.providers.map(provider => {
|
||||
return provider['useClass'] || provider
|
||||
})
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import { HostAppService, Bounds } from '../services/hostApp.service'
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DockingService {
|
||||
/** @hidden */
|
||||
private constructor (
|
||||
constructor (
|
||||
private electron: ElectronService,
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
@@ -15,7 +15,7 @@ export class DockingService {
|
||||
electron.screen.on('display-metrics-changed', () => this.repositionWindow())
|
||||
}
|
||||
|
||||
dock (): void {
|
||||
dock () {
|
||||
const dockSide = this.config.store.appearance.dock
|
||||
|
||||
if (dockSide === 'off') {
|
||||
@@ -53,25 +53,22 @@ export class DockingService {
|
||||
newBounds.y = display.bounds.y
|
||||
}
|
||||
|
||||
const alwaysOnTop = this.config.store.appearance.dockAlwaysOnTop
|
||||
|
||||
this.hostApp.setAlwaysOnTop(alwaysOnTop)
|
||||
this.hostApp.setAlwaysOnTop(true)
|
||||
setImmediate(() => {
|
||||
this.hostApp.setBounds(newBounds)
|
||||
})
|
||||
}
|
||||
|
||||
getCurrentScreen (): Electron.Display {
|
||||
getCurrentScreen () {
|
||||
return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint())
|
||||
}
|
||||
|
||||
getScreens (): Electron.Display[] {
|
||||
getScreens () {
|
||||
const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id
|
||||
return this.electron.screen.getAllDisplays().sort((a, b) =>
|
||||
a.bounds.x === b.bounds.x ? a.bounds.y - b.bounds.y : a.bounds.x - b.bounds.x
|
||||
).map((display, index) => {
|
||||
).map((display,index) => {
|
||||
return {
|
||||
...display,
|
||||
id: display.id,
|
||||
name: display.id === primaryDisplayID ? 'Primary Display' : `Display ${index +1}`,
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ export class ElectronService {
|
||||
private electron: any
|
||||
|
||||
/** @hidden */
|
||||
private constructor () {
|
||||
constructor () {
|
||||
this.electron = require('electron')
|
||||
this.remote = this.electron.remote
|
||||
this.app = this.remote.app
|
||||
@@ -43,6 +43,15 @@ export class ElectronService {
|
||||
this.MenuItem = this.remote.MenuItem
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes OS focus from Terminus' window
|
||||
*/
|
||||
loseFocus () {
|
||||
if (process.platform === 'darwin') {
|
||||
this.remote.Menu.sendActionToFirstResponder('hide:')
|
||||
}
|
||||
}
|
||||
|
||||
async showMessageBox (
|
||||
browserWindow: Electron.BrowserWindow,
|
||||
options: Electron.MessageBoxOptions
|
||||
|
@@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'
|
||||
import { ElectronService } from './electron.service'
|
||||
import { ConfigService } from './config.service'
|
||||
import * as mixpanel from 'mixpanel'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import * as uuidv4 from 'uuid/v4'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class HomeBaseService {
|
||||
@@ -11,7 +11,7 @@ export class HomeBaseService {
|
||||
mixpanel: any
|
||||
|
||||
/** @hidden */
|
||||
private constructor (
|
||||
constructor (
|
||||
private electron: ElectronService,
|
||||
private config: ConfigService,
|
||||
) {
|
||||
@@ -22,29 +22,24 @@ export class HomeBaseService {
|
||||
}
|
||||
}
|
||||
|
||||
openGitHub (): void {
|
||||
openGitHub () {
|
||||
this.electron.shell.openExternal('https://github.com/eugeny/terminus')
|
||||
}
|
||||
|
||||
reportBug (): void {
|
||||
reportBug () {
|
||||
let body = `Version: ${this.appVersion}\n`
|
||||
body += `Platform: ${os.platform()} ${os.release()}\n`
|
||||
const label = {
|
||||
aix: 'OS: IBM AIX',
|
||||
android: 'OS: Android',
|
||||
darwin: 'OS: macOS',
|
||||
freebsd: 'OS: FreeBSD',
|
||||
windows: 'OS: Windows',
|
||||
linux: 'OS: Linux',
|
||||
openbsd: 'OS: OpenBSD',
|
||||
sunos: 'OS: Solaris',
|
||||
win32: 'OS: Windows',
|
||||
}[os.platform()]
|
||||
const plugins = (window as any).installedPlugins.filter(x => !x.isBuiltin).map(x => x.name)
|
||||
body += `Plugins: ${plugins.join(', ') || 'none'}\n\n`
|
||||
this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`)
|
||||
}
|
||||
|
||||
enableAnalytics (): void {
|
||||
enableAnalytics () {
|
||||
if (!window.localStorage.analyticsUserID) {
|
||||
window.localStorage.analyticsUserID = uuidv4()
|
||||
}
|
||||
@@ -56,7 +51,7 @@ export class HomeBaseService {
|
||||
this.mixpanel.track('launch', this.getAnalyticsProperties())
|
||||
}
|
||||
|
||||
getAnalyticsProperties (): Record<string, string> {
|
||||
getAnalyticsProperties () {
|
||||
return {
|
||||
distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase
|
||||
platform: process.platform,
|
||||
|
@@ -4,7 +4,6 @@ import { Observable, Subject } from 'rxjs'
|
||||
import { Injectable, NgZone, EventEmitter } from '@angular/core'
|
||||
import { ElectronService } from './electron.service'
|
||||
import { Logger, LogService } from './log.service'
|
||||
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
|
||||
|
||||
export enum Platform {
|
||||
Linux, macOS, Windows,
|
||||
@@ -40,7 +39,6 @@ export class HostAppService {
|
||||
private configChangeBroadcast = new Subject<void>()
|
||||
private windowCloseRequest = new Subject<void>()
|
||||
private windowMoved = new Subject<void>()
|
||||
private windowFocused = new Subject<void>()
|
||||
private displayMetricsChanged = new Subject<void>()
|
||||
private logger: Logger
|
||||
private windowId: number
|
||||
@@ -87,8 +85,6 @@ export class HostAppService {
|
||||
|
||||
get windowMoved$ (): Observable<void> { return this.windowMoved }
|
||||
|
||||
get windowFocused$ (): Observable<void> { return this.windowFocused }
|
||||
|
||||
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
|
||||
|
||||
private constructor (
|
||||
@@ -132,10 +128,6 @@ export class HostAppService {
|
||||
this.zone.run(() => this.windowMoved.next())
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:window-focused', () => {
|
||||
this.zone.run(() => this.windowFocused.next())
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:display-metrics-changed', () => {
|
||||
this.zone.run(() => this.displayMetricsChanged.next())
|
||||
})
|
||||
@@ -165,60 +157,53 @@ export class HostAppService {
|
||||
electron.ipcRenderer.on('host:config-change', () => this.zone.run(() => {
|
||||
this.configChangeBroadcast.next()
|
||||
}))
|
||||
|
||||
if (
|
||||
isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED) &&
|
||||
!isWindowsBuild(WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED)
|
||||
) {
|
||||
electron.ipcRenderer.send('window-set-disable-vibrancy-while-dragging', true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current remote [[BrowserWindow]]
|
||||
*/
|
||||
getWindow (): Electron.BrowserWindow {
|
||||
getWindow () {
|
||||
return this.electron.BrowserWindow.fromId(this.windowId)
|
||||
}
|
||||
|
||||
newWindow (): void {
|
||||
newWindow () {
|
||||
this.electron.ipcRenderer.send('app:new-window')
|
||||
}
|
||||
|
||||
toggleFullscreen (): void {
|
||||
toggleFullscreen () {
|
||||
const window = this.getWindow()
|
||||
window.setFullScreen(!this.isFullScreen)
|
||||
}
|
||||
|
||||
openDevTools (): void {
|
||||
openDevTools () {
|
||||
this.getWindow().webContents.openDevTools({ mode: 'undocked' })
|
||||
}
|
||||
|
||||
focusWindow (): void {
|
||||
focusWindow () {
|
||||
this.electron.ipcRenderer.send('window-focus')
|
||||
}
|
||||
|
||||
minimize (): void {
|
||||
minimize () {
|
||||
this.electron.ipcRenderer.send('window-minimize')
|
||||
}
|
||||
|
||||
maximize (): void {
|
||||
maximize () {
|
||||
this.electron.ipcRenderer.send('window-maximize')
|
||||
}
|
||||
|
||||
unmaximize (): void {
|
||||
unmaximize () {
|
||||
this.electron.ipcRenderer.send('window-unmaximize')
|
||||
}
|
||||
|
||||
toggleMaximize (): void {
|
||||
toggleMaximize () {
|
||||
this.electron.ipcRenderer.send('window-toggle-maximize')
|
||||
}
|
||||
|
||||
setBounds (bounds: Bounds): void {
|
||||
setBounds (bounds: Bounds) {
|
||||
this.electron.ipcRenderer.send('window-set-bounds', bounds)
|
||||
}
|
||||
|
||||
setAlwaysOnTop (flag: boolean): void {
|
||||
setAlwaysOnTop (flag: boolean) {
|
||||
this.electron.ipcRenderer.send('window-set-always-on-top', flag)
|
||||
}
|
||||
|
||||
@@ -227,50 +212,48 @@ export class HostAppService {
|
||||
*
|
||||
* @param type `null`, or `fluent` when supported (Windowd only)
|
||||
*/
|
||||
setVibrancy (enable: boolean, type: string|null): void {
|
||||
if (!isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
|
||||
type = null
|
||||
}
|
||||
setVibrancy (enable: boolean, type: string) {
|
||||
document.body.classList.toggle('vibrant', enable)
|
||||
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
|
||||
if (this.platform === Platform.macOS) {
|
||||
this.getWindow().setVibrancy(enable ? 'dark' : null as any) // electron issue 20269
|
||||
}
|
||||
if (this.platform === Platform.Windows) {
|
||||
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
|
||||
}
|
||||
}
|
||||
|
||||
setTitle (title: string): void {
|
||||
setTitle (title: string) {
|
||||
this.electron.ipcRenderer.send('window-set-title', title)
|
||||
}
|
||||
|
||||
setTouchBar (touchBar: Electron.TouchBar): void {
|
||||
setTouchBar (touchBar: Electron.TouchBar) {
|
||||
this.getWindow().setTouchBar(touchBar)
|
||||
}
|
||||
|
||||
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]): void {
|
||||
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]) {
|
||||
this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies other windows of config file changes
|
||||
*/
|
||||
broadcastConfigChange (configStore: {[k: string]: any}): void {
|
||||
this.electron.ipcRenderer.send('app:config-change', configStore)
|
||||
broadcastConfigChange () {
|
||||
this.electron.ipcRenderer.send('app:config-change')
|
||||
}
|
||||
|
||||
emitReady (): void {
|
||||
emitReady () {
|
||||
this.electron.ipcRenderer.send('app:ready')
|
||||
}
|
||||
|
||||
bringToFront (): void {
|
||||
bringToFront () {
|
||||
this.electron.ipcRenderer.send('window-bring-to-front')
|
||||
}
|
||||
|
||||
closeWindow (): void {
|
||||
closeWindow () {
|
||||
this.electron.ipcRenderer.send('window-close')
|
||||
}
|
||||
|
||||
registerGlobalHotkey (specs: string[]): void {
|
||||
this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
|
||||
}
|
||||
|
||||
relaunch (): void {
|
||||
relaunch () {
|
||||
if (this.isPortable) {
|
||||
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
|
||||
} else {
|
||||
@@ -279,7 +262,7 @@ export class HostAppService {
|
||||
this.electron.app.exit()
|
||||
}
|
||||
|
||||
quit (): void {
|
||||
quit () {
|
||||
this.logger.info('Quitting')
|
||||
this.electron.app.quit()
|
||||
}
|
||||
|
@@ -1,10 +1,8 @@
|
||||
import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { HotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
|
||||
import { stringifyKeySequence } from './hotkeys.util'
|
||||
import { ConfigService } from './config.service'
|
||||
import { ElectronService } from './electron.service'
|
||||
import { HostAppService } from './hostApp.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { ElectronService } from '../services/electron.service'
|
||||
|
||||
export interface PartialHotkeyMatch {
|
||||
id: string
|
||||
@@ -22,23 +20,14 @@ interface EventBufferEntry {
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class HotkeysService {
|
||||
key = new EventEmitter<KeyboardEvent>()
|
||||
|
||||
/** @hidden */
|
||||
matchedHotkey = new EventEmitter<string>()
|
||||
|
||||
/**
|
||||
* Fired for each recognized hotkey
|
||||
*/
|
||||
get hotkey$ (): Observable<string> { return this._hotkey }
|
||||
|
||||
private _hotkey = new Subject<string>()
|
||||
globalHotkey = new EventEmitter<void>()
|
||||
private currentKeystrokes: EventBufferEntry[] = []
|
||||
private disabledLevel = 0
|
||||
private hotkeyDescriptions: HotkeyDescription[] = []
|
||||
|
||||
private constructor (
|
||||
private zone: NgZone,
|
||||
private hostApp: HostAppService,
|
||||
private electron: ElectronService,
|
||||
private config: ConfigService,
|
||||
@Inject(HotkeyProvider) private hotkeyProviders: HotkeyProvider[],
|
||||
@@ -60,9 +49,6 @@ export class HotkeysService {
|
||||
this.getHotkeyDescriptions().then(hotkeys => {
|
||||
this.hotkeyDescriptions = hotkeys
|
||||
})
|
||||
|
||||
// deprecated
|
||||
this.hotkey$.subscribe(h => this.matchedHotkey.emit(h))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +57,7 @@ export class HotkeysService {
|
||||
* @param name DOM event name
|
||||
* @param nativeEvent event object
|
||||
*/
|
||||
pushKeystroke (name: string, nativeEvent: KeyboardEvent): void {
|
||||
pushKeystroke (name: string, nativeEvent: KeyboardEvent) {
|
||||
(nativeEvent as any).event = name
|
||||
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
|
||||
}
|
||||
@@ -79,26 +65,26 @@ export class HotkeysService {
|
||||
/**
|
||||
* Check the buffer for new complete keystrokes
|
||||
*/
|
||||
processKeystrokes (): void {
|
||||
processKeystrokes () {
|
||||
if (this.isEnabled()) {
|
||||
this.zone.run(() => {
|
||||
const matched = this.getCurrentFullyMatchedHotkey()
|
||||
if (matched) {
|
||||
console.log('Matched hotkey', matched)
|
||||
this._hotkey.next(matched)
|
||||
this.matchedHotkey.emit(matched)
|
||||
this.clearCurrentKeystrokes()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
emitKeyEvent (nativeEvent: KeyboardEvent): void {
|
||||
emitKeyEvent (nativeEvent: KeyboardEvent) {
|
||||
this.zone.run(() => {
|
||||
this.key.emit(nativeEvent)
|
||||
})
|
||||
}
|
||||
|
||||
clearCurrentKeystrokes (): void {
|
||||
clearCurrentKeystrokes () {
|
||||
this.currentKeystrokes = []
|
||||
}
|
||||
|
||||
@@ -156,15 +142,15 @@ export class HotkeysService {
|
||||
return this.hotkeyDescriptions.filter((x) => x.id === id)[0]
|
||||
}
|
||||
|
||||
enable (): void {
|
||||
enable () {
|
||||
this.disabledLevel--
|
||||
}
|
||||
|
||||
disable (): void {
|
||||
disable () {
|
||||
this.disabledLevel++
|
||||
}
|
||||
|
||||
isEnabled (): boolean {
|
||||
isEnabled () {
|
||||
return this.disabledLevel === 0
|
||||
}
|
||||
|
||||
@@ -183,7 +169,6 @@ export class HotkeysService {
|
||||
if (typeof value === 'string') {
|
||||
value = [value]
|
||||
}
|
||||
const specs: string[] = []
|
||||
value.forEach((item: string | string[]) => {
|
||||
item = typeof item === 'string' ? [item] : item
|
||||
|
||||
@@ -192,13 +177,13 @@ export class HotkeysService {
|
||||
electronKeySpec = electronKeySpec.replace('⌘', 'Command')
|
||||
electronKeySpec = electronKeySpec.replace('⌥', 'Alt')
|
||||
electronKeySpec = electronKeySpec.replace(/-/g, '+')
|
||||
specs.push(electronKeySpec)
|
||||
this.electron.globalShortcut.register(electronKeySpec, () => {
|
||||
this.globalHotkey.emit()
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('Could not register the global hotkey:', err)
|
||||
}
|
||||
})
|
||||
|
||||
this.hostApp.registerGlobalHotkey(specs)
|
||||
}
|
||||
|
||||
private getHotkeysConfig () {
|
||||
@@ -218,9 +203,6 @@ export class HotkeysService {
|
||||
if (typeof value === 'string') {
|
||||
value = [value]
|
||||
}
|
||||
if (!(value instanceof Array)) {
|
||||
continue
|
||||
}
|
||||
if (value) {
|
||||
value = value.map((item: string | string[]) => typeof item === 'string' ? [item] : item)
|
||||
keys[key] = value
|
||||
|
@@ -32,27 +32,27 @@ export class Logger {
|
||||
private name: string,
|
||||
) {}
|
||||
|
||||
debug (...args: any[]): void {
|
||||
debug (...args: any[]) {
|
||||
this.doLog('debug', ...args)
|
||||
}
|
||||
|
||||
info (...args: any[]): void {
|
||||
info (...args: any[]) {
|
||||
this.doLog('info', ...args)
|
||||
}
|
||||
|
||||
warn (...args: any[]): void {
|
||||
warn (...args: any[]) {
|
||||
this.doLog('warn', ...args)
|
||||
}
|
||||
|
||||
error (...args: any[]): void {
|
||||
error (...args: any[]) {
|
||||
this.doLog('error', ...args)
|
||||
}
|
||||
|
||||
log (...args: any[]): void {
|
||||
log (...args: any[]) {
|
||||
this.doLog('log', ...args)
|
||||
}
|
||||
|
||||
private doLog (level: string, ...args: any[]): void {
|
||||
private doLog (level: string, ...args: any[]) {
|
||||
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||
if (this.winstonLogger) {
|
||||
this.winstonLogger[level](...args)
|
||||
@@ -65,7 +65,7 @@ export class LogService {
|
||||
private log: any
|
||||
|
||||
/** @hidden */
|
||||
private constructor (electron: ElectronService) {
|
||||
constructor (electron: ElectronService) {
|
||||
this.log = initializeWinston(electron)
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import { HostAppService, Platform } from './hostApp.service'
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
||||
try {
|
||||
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
|
||||
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires
|
||||
} catch (_) { }
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@@ -18,22 +18,15 @@ export class ShellIntegrationService {
|
||||
private automatorWorkflowsDestination: string
|
||||
private registryKeys = [
|
||||
{
|
||||
path: 'Software\\Classes\\Directory\\Background\\shell\\Terminus',
|
||||
value: 'Open Terminus here',
|
||||
path: 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
|
||||
command: 'open "%V"',
|
||||
},
|
||||
{
|
||||
path: 'SOFTWARE\\Classes\\Directory\\shell\\Terminus',
|
||||
value: 'Open Terminus here',
|
||||
command: 'open "%V"',
|
||||
},
|
||||
{
|
||||
path: 'Software\\Classes\\*\\shell\\Terminus',
|
||||
value: 'Paste path into Terminus',
|
||||
path: 'Software\\Classes\\*\\shell\\Paste path into Terminus',
|
||||
command: 'paste "%V"',
|
||||
},
|
||||
]
|
||||
private constructor (
|
||||
constructor (
|
||||
private electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
) {
|
||||
@@ -58,7 +51,7 @@ export class ShellIntegrationService {
|
||||
return true
|
||||
}
|
||||
|
||||
async install (): Promise<void> {
|
||||
async install () {
|
||||
const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
|
||||
if (this.hostApp.platform === Platform.macOS) {
|
||||
for (const wf of this.automatorWorkflows) {
|
||||
@@ -68,21 +61,13 @@ export class ShellIntegrationService {
|
||||
for (const registryKey of this.registryKeys) {
|
||||
wnr.createRegistryKey(wnr.HK.CU, registryKey.path)
|
||||
wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command')
|
||||
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, '', wnr.REG.SZ, registryKey.value)
|
||||
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, exe)
|
||||
wnr.setRegistryValue(wnr.HK.CU, registryKey.path + '\\command', '', wnr.REG.SZ, exe + ' ' + registryKey.command)
|
||||
}
|
||||
|
||||
if(wnr.getRegistryKey(wnr.HK.CU, 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here')) {
|
||||
wnr.deleteRegistryKey(wnr.HK.CU, 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here')
|
||||
}
|
||||
if(wnr.getRegistryKey(wnr.HK.CU, 'Software\\Classes\\*\\shell\\Paste path into Terminus')) {
|
||||
wnr.deleteRegistryKey(wnr.HK.CU, 'Software\\Classes\\*\\shell\\Paste path into Terminus')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async remove (): Promise<void> {
|
||||
async remove () {
|
||||
if (this.hostApp.platform === Platform.macOS) {
|
||||
for (const wf of this.automatorWorkflows) {
|
||||
await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Injectable, Inject } from '@angular/core'
|
||||
import { TabRecoveryProvider, RecoveredTab, RecoveryToken } from '../api/tabRecovery'
|
||||
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery'
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { Logger, LogService } from '../services/log.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
@@ -8,9 +8,8 @@ import { ConfigService } from '../services/config.service'
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TabRecoveryService {
|
||||
logger: Logger
|
||||
enabled = false
|
||||
|
||||
private constructor (
|
||||
constructor (
|
||||
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
|
||||
private config: ConfigService,
|
||||
log: LogService
|
||||
@@ -18,41 +17,21 @@ export class TabRecoveryService {
|
||||
this.logger = log.create('tabRecovery')
|
||||
}
|
||||
|
||||
async saveTabs (tabs: BaseTabComponent[]): Promise<void> {
|
||||
if (!this.enabled) {
|
||||
return
|
||||
}
|
||||
async saveTabs (tabs: BaseTabComponent[]) {
|
||||
window.localStorage.tabsRecovery = JSON.stringify(
|
||||
await Promise.all(
|
||||
tabs
|
||||
.map(tab => {
|
||||
let token = tab.getRecoveryToken()
|
||||
if (token) {
|
||||
token = token.then(r => {
|
||||
if (r) {
|
||||
r.tabTitle = tab.title
|
||||
if (tab.color) {
|
||||
r.tabColor = tab.color
|
||||
}
|
||||
}
|
||||
return r
|
||||
})
|
||||
}
|
||||
return token
|
||||
})
|
||||
.map(tab => tab.getRecoveryToken())
|
||||
.filter(token => !!token)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
async recoverTab (token: RecoveryToken): Promise<RecoveredTab|null> {
|
||||
async recoverTab (token: any): Promise<RecoveredTab|null> {
|
||||
for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
||||
try {
|
||||
const tab = await provider.recover(token)
|
||||
if (tab !== null) {
|
||||
tab.options = tab.options || {}
|
||||
tab.options.color = token.tabColor || null
|
||||
tab.options.title = token.tabTitle || ''
|
||||
if (tab) {
|
||||
return tab
|
||||
}
|
||||
} catch (error) {
|
||||
|
@@ -8,7 +8,7 @@ export type TabComponentType = new (...args: any[]) => BaseTabComponent
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TabsService {
|
||||
/** @hidden */
|
||||
private constructor (
|
||||
constructor (
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private injector: Injector,
|
||||
private tabRecovery: TabRecoveryService,
|
||||
@@ -17,7 +17,7 @@ export class TabsService {
|
||||
/**
|
||||
* Instantiates a tab component and assigns given inputs
|
||||
*/
|
||||
create (type: TabComponentType, inputs?: Record<string, any>): BaseTabComponent {
|
||||
create (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
|
||||
const componentRef = componentFactory.create(this.injector)
|
||||
const tab = componentRef.instance
|
||||
|
@@ -7,7 +7,7 @@ export class ThemesService {
|
||||
private styleElement: HTMLElement|null = null
|
||||
|
||||
/** @hidden */
|
||||
private constructor (
|
||||
constructor (
|
||||
private config: ConfigService,
|
||||
@Inject(Theme) private themes: Theme[],
|
||||
) {
|
||||
|
@@ -14,7 +14,7 @@ export class TouchbarService {
|
||||
private tabSegments: SegmentedControlSegment[] = []
|
||||
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
|
||||
|
||||
private constructor (
|
||||
constructor (
|
||||
private app: AppService,
|
||||
private hostApp: HostAppService,
|
||||
@Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[],
|
||||
@@ -48,7 +48,7 @@ export class TouchbarService {
|
||||
})
|
||||
}
|
||||
|
||||
updateTabs (): void {
|
||||
updateTabs () {
|
||||
this.tabSegments = this.app.tabs.map(tab => ({
|
||||
label: this.shortenTitle(tab.title),
|
||||
}))
|
||||
@@ -56,7 +56,7 @@ export class TouchbarService {
|
||||
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
|
||||
}
|
||||
|
||||
update (): void {
|
||||
update () {
|
||||
if (this.hostApp.platform !== Platform.macOS) {
|
||||
return
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@ import { Injectable } from '@angular/core'
|
||||
import { Logger, LogService } from './log.service'
|
||||
import { ElectronService } from './electron.service'
|
||||
import { ConfigService } from './config.service'
|
||||
import { AppUpdater } from 'electron-updater'
|
||||
|
||||
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
|
||||
|
||||
@@ -19,27 +18,21 @@ export class UpdaterService {
|
||||
private downloaded: Promise<boolean>
|
||||
private electronUpdaterAvailable = true
|
||||
private updateURL: string
|
||||
private autoUpdater: AppUpdater
|
||||
private autoUpdater
|
||||
|
||||
private constructor (
|
||||
constructor (
|
||||
log: LogService,
|
||||
private electron: ElectronService,
|
||||
private config: ConfigService,
|
||||
config: ConfigService,
|
||||
) {
|
||||
this.logger = log.create('updater')
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
this.electronUpdaterAvailable = false
|
||||
return
|
||||
}
|
||||
|
||||
this.autoUpdater = electron.remote.require('electron-updater').autoUpdater
|
||||
|
||||
this.autoUpdater.autoInstallOnAppQuit = !!config.store.enableAutomaticUpdates
|
||||
|
||||
this.autoUpdater.on('update-available', () => {
|
||||
this.logger.info('Update available')
|
||||
this.autoUpdater.downloadUpdate()
|
||||
})
|
||||
this.autoUpdater.once('update-not-available', () => {
|
||||
this.logger.info('No updates')
|
||||
@@ -49,8 +42,9 @@ export class UpdaterService {
|
||||
this.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||
})
|
||||
|
||||
if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
|
||||
this.logger.debug('Checking for updates')
|
||||
this.logger.debug('Checking for updates')
|
||||
|
||||
if (this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
|
||||
try {
|
||||
this.autoUpdater.checkForUpdates()
|
||||
} catch (e) {
|
||||
@@ -61,9 +55,6 @@ export class UpdaterService {
|
||||
}
|
||||
|
||||
async check (): Promise<boolean> {
|
||||
if (!this.config.store.enableAutomaticUpdates) {
|
||||
return false
|
||||
}
|
||||
if (!this.electronUpdaterAvailable) {
|
||||
this.logger.debug('Checking for updates through fallback method.')
|
||||
const response = await axios.get(UPDATES_URL)
|
||||
@@ -80,7 +71,7 @@ export class UpdaterService {
|
||||
return this.downloaded
|
||||
}
|
||||
|
||||
async update (): Promise<void> {
|
||||
async update () {
|
||||
if (!this.electronUpdaterAvailable) {
|
||||
this.electron.shell.openExternal(this.updateURL)
|
||||
} else {
|
||||
|
@@ -1,16 +1,13 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Injectable, NgZone } from '@angular/core'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { AppService } from './services/app.service'
|
||||
import { BaseTabComponent } from './components/baseTab.component'
|
||||
import { TabHeaderComponent } from './components/tabHeader.component'
|
||||
import { SplitTabComponent, SplitDirection } from './components/splitTab.component'
|
||||
import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
||||
weight = 99
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CloseContextMenu extends TabContextMenuItemProvider {
|
||||
weight = -5
|
||||
|
||||
constructor (
|
||||
private app: AppService,
|
||||
@@ -19,67 +16,39 @@ export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
let items: Electron.MenuItemConstructorOptions[] = [
|
||||
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
return [
|
||||
{
|
||||
label: 'Close',
|
||||
click: () => this.zone.run(() => {
|
||||
if (this.app.tabs.includes(tab)) {
|
||||
this.app.closeTab(tab, true)
|
||||
} else {
|
||||
tab.destroy()
|
||||
this.app.closeTab(tab, true)
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'Close other tabs',
|
||||
click: () => this.zone.run(() => {
|
||||
for (const t of this.app.tabs.filter(x => x !== tab)) {
|
||||
this.app.closeTab(t, true)
|
||||
}
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'Close tabs to the right',
|
||||
click: () => this.zone.run(() => {
|
||||
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
|
||||
this.app.closeTab(t, true)
|
||||
}
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'Close tabs to the left',
|
||||
click: () => this.zone.run(() => {
|
||||
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
|
||||
this.app.closeTab(t, true)
|
||||
}
|
||||
}),
|
||||
},
|
||||
]
|
||||
if (tabHeader) {
|
||||
items = [
|
||||
...items,
|
||||
{
|
||||
label: 'Close other tabs',
|
||||
click: () => this.zone.run(() => {
|
||||
for (const t of this.app.tabs.filter(x => x !== tab)) {
|
||||
this.app.closeTab(t, true)
|
||||
}
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'Close tabs to the right',
|
||||
click: () => this.zone.run(() => {
|
||||
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
|
||||
this.app.closeTab(t, true)
|
||||
}
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'Close tabs to the left',
|
||||
click: () => this.zone.run(() => {
|
||||
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
|
||||
this.app.closeTab(t, true)
|
||||
}
|
||||
}),
|
||||
},
|
||||
]
|
||||
} else {
|
||||
if (tab.parent instanceof SplitTabComponent) {
|
||||
const directions: SplitDirection[] = ['r', 'b', 'l', 't']
|
||||
items.push({
|
||||
label: 'Split',
|
||||
submenu: directions.map(dir => ({
|
||||
label: {
|
||||
r: 'Right',
|
||||
b: 'Down',
|
||||
l: 'Left',
|
||||
t: 'Up',
|
||||
}[dir],
|
||||
click: () => this.zone.run(() => {
|
||||
(tab.parent as SplitTabComponent).splitTab(tab, dir)
|
||||
}),
|
||||
})) as Electron.MenuItemConstructorOptions[],
|
||||
})
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +63,7 @@ const COLORS = [
|
||||
]
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
weight = -1
|
||||
|
||||
@@ -106,38 +75,33 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
let items: Electron.MenuItemConstructorOptions[] = []
|
||||
if (tabHeader) {
|
||||
items = [
|
||||
...items,
|
||||
{
|
||||
label: 'Rename',
|
||||
click: () => this.zone.run(() => tabHeader?.showRenameTabModal()),
|
||||
},
|
||||
{
|
||||
label: 'Duplicate',
|
||||
click: () => this.zone.run(() => this.app.duplicateTab(tab)),
|
||||
},
|
||||
{
|
||||
label: 'Color',
|
||||
sublabel: COLORS.find(x => x.value === tab.color)!.name,
|
||||
submenu: COLORS.map(color => ({
|
||||
label: color.name,
|
||||
type: 'radio',
|
||||
checked: tab.color === color.value,
|
||||
click: () => this.zone.run(() => {
|
||||
tab.color = color.value
|
||||
}),
|
||||
})) as Electron.MenuItemConstructorOptions[],
|
||||
},
|
||||
]
|
||||
}
|
||||
return items
|
||||
return [
|
||||
{
|
||||
label: 'Rename',
|
||||
click: () => this.zone.run(() => tabHeader?.showRenameTabModal()),
|
||||
},
|
||||
{
|
||||
label: 'Duplicate',
|
||||
click: () => this.zone.run(() => this.app.duplicateTab(tab)),
|
||||
},
|
||||
{
|
||||
label: 'Color',
|
||||
sublabel: COLORS.find(x => x.value === tab.color)!.name,
|
||||
submenu: COLORS.map(color => ({
|
||||
label: color.name,
|
||||
type: 'radio',
|
||||
checked: tab.color === color.value,
|
||||
click: () => this.zone.run(() => {
|
||||
tab.color = color.value
|
||||
}),
|
||||
})) as Electron.MenuItemConstructorOptions[],
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
||||
constructor (
|
||||
private app: AppService,
|
||||
@@ -148,61 +112,36 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
||||
|
||||
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
const process = await tab.getCurrentProcess()
|
||||
let items: Electron.MenuItemConstructorOptions[] = []
|
||||
|
||||
const extTab: (BaseTabComponent & { __completionNotificationEnabled?: boolean, __outputNotificationSubscription?: Subscription|null }) = tab
|
||||
|
||||
if (process) {
|
||||
items.push({
|
||||
id: 'process-name',
|
||||
enabled: false,
|
||||
label: 'Current process: ' + process.name,
|
||||
})
|
||||
items.push({
|
||||
label: 'Notify when done',
|
||||
type: 'checkbox',
|
||||
checked: extTab.__completionNotificationEnabled,
|
||||
click: () => this.zone.run(() => {
|
||||
extTab.__completionNotificationEnabled = !extTab.__completionNotificationEnabled
|
||||
return [
|
||||
{
|
||||
id: 'process-name',
|
||||
enabled: false,
|
||||
label: 'Current process: ' + process.name,
|
||||
},
|
||||
{
|
||||
label: 'Notify when done',
|
||||
type: 'checkbox',
|
||||
checked: (tab as any).__completionNotificationEnabled,
|
||||
click: () => this.zone.run(() => {
|
||||
(tab as any).__completionNotificationEnabled = !(tab as any).__completionNotificationEnabled
|
||||
|
||||
if (extTab.__completionNotificationEnabled) {
|
||||
this.app.observeTabCompletion(tab).subscribe(() => {
|
||||
new Notification('Process completed', {
|
||||
body: process.name,
|
||||
}).addEventListener('click', () => {
|
||||
this.app.selectTab(tab)
|
||||
})
|
||||
extTab.__completionNotificationEnabled = false
|
||||
})
|
||||
} else {
|
||||
this.app.stopObservingTabCompletion(tab)
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
items.push({
|
||||
label: 'Notify on activity',
|
||||
type: 'checkbox',
|
||||
checked: !!extTab.__outputNotificationSubscription,
|
||||
click: () => this.zone.run(() => {
|
||||
if (extTab.__outputNotificationSubscription) {
|
||||
extTab.__outputNotificationSubscription.unsubscribe()
|
||||
extTab.__outputNotificationSubscription = null
|
||||
} else {
|
||||
extTab.__outputNotificationSubscription = tab.activity$.subscribe(active => {
|
||||
if (extTab.__outputNotificationSubscription && active) {
|
||||
extTab.__outputNotificationSubscription.unsubscribe()
|
||||
extTab.__outputNotificationSubscription = null
|
||||
new Notification('Tab activity', {
|
||||
body: tab.title,
|
||||
}).addEventListener('click', () => {
|
||||
this.app.selectTab(tab)
|
||||
if ((tab as any).__completionNotificationEnabled) {
|
||||
this.app.observeTabCompletion(tab).subscribe(() => {
|
||||
new Notification('Process completed', {
|
||||
body: process.name,
|
||||
}).addEventListener('click', () => {
|
||||
this.app.selectTab(tab)
|
||||
})
|
||||
;(tab as any).__completionNotificationEnabled = false
|
||||
})
|
||||
} else {
|
||||
this.app.stopObservingTabCompletion(tab)
|
||||
}
|
||||
})
|
||||
}
|
||||
}),
|
||||
})
|
||||
return items
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
@@ -16,12 +16,4 @@ app-root {
|
||||
terminaltab .content {
|
||||
margin: 5px !important;
|
||||
}
|
||||
|
||||
ssh-tab .content {
|
||||
margin: 5px !important;
|
||||
}
|
||||
|
||||
serial-tab .content {
|
||||
margin: 5px !important;
|
||||
}
|
||||
}
|
||||
|
@@ -246,7 +246,7 @@ ngb-tabset .tab-content {
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
transition: 0.0625s background;
|
||||
transition: 0.25s background;
|
||||
|
||||
i + * {
|
||||
margin-left: 10px;
|
||||
@@ -262,29 +262,6 @@ ngb-tabset .tab-content {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.list-group-light {
|
||||
.list-group-item {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-top: 1px solid rgba(255, 255, 255, .1);
|
||||
|
||||
&:not(.combi) {
|
||||
padding: $list-group-item-padding-y $list-group-item-padding-x;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
&.list-group-item-action {
|
||||
&:hover, &.active {
|
||||
background: $list-group-hover-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkbox i.on {
|
||||
color: $blue;
|
||||
}
|
||||
@@ -415,7 +392,3 @@ search-panel {
|
||||
border-color: $nav-tabs-link-active-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: $list-group-border-color;
|
||||
}
|
||||
|
@@ -142,7 +142,7 @@ $nav-tabs-link-active-border-color: #eee;
|
||||
$navbar-padding-y: 0;
|
||||
$navbar-padding-x: 0;
|
||||
|
||||
$dropdown-bg: $content-bg-solid;
|
||||
$dropdown-bg: $table-bg;
|
||||
$dropdown-color: $body-color;
|
||||
$dropdown-border-width: 1px;
|
||||
$dropdown-box-shadow: 0 .5rem 1rem rgba($black,.175);
|
||||
|
@@ -2,6 +2,9 @@
|
||||
"extends": "../tsconfig.json",
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src"
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"*": ["../../app/node_modules/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,11 @@
|
||||
const path = require('path')
|
||||
const { AngularCompilerPlugin } = require('@ngtools/webpack')
|
||||
|
||||
module.exports = {
|
||||
target: 'node',
|
||||
entry: 'src/index.ts',
|
||||
context: __dirname,
|
||||
devtool: 'eval-cheap-module-source-map',
|
||||
devtool: 'cheap-module-source-map',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'index.js',
|
||||
@@ -23,22 +24,26 @@ module.exports = {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: {
|
||||
loader: 'awesome-typescript-loader',
|
||||
options: {
|
||||
configFileName: path.resolve(__dirname, 'tsconfig.json'),
|
||||
typeRoots: [
|
||||
path.resolve(__dirname, 'node_modules/@types'),
|
||||
path.resolve(__dirname, '../node_modules/@types'),
|
||||
],
|
||||
paths: {
|
||||
"terminus-*": [path.resolve(__dirname, '../terminus-*')],
|
||||
"*": [path.resolve(__dirname, '../app/node_modules/*')],
|
||||
},
|
||||
},
|
||||
},
|
||||
test: /(?:\.ngfactory\.js|\.ngfactory|\.ngstyle\.js|\.ts)$/,
|
||||
loader: '@ngtools/webpack',
|
||||
},
|
||||
// {
|
||||
// test: /\.ts$/,
|
||||
// use: {
|
||||
// loader: 'awesome-typescript-loader',
|
||||
// options: {
|
||||
// configFileName: path.resolve(__dirname, 'tsconfig.json'),
|
||||
// typeRoots: [
|
||||
// path.resolve(__dirname, 'node_modules/@types'),
|
||||
// path.resolve(__dirname, '../node_modules/@types'),
|
||||
// ],
|
||||
// paths: {
|
||||
// "terminus-*": [path.resolve(__dirname, '../terminus-*')],
|
||||
// "*": [path.resolve(__dirname, '../app/node_modules/*')],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
||||
{ test: /\.css$/, use: ['to-string-loader', 'css-loader'], include: /component\.css/ },
|
||||
@@ -57,4 +62,12 @@ module.exports = {
|
||||
/^@angular/,
|
||||
/^@ng-bootstrap/,
|
||||
],
|
||||
plugins: [
|
||||
new AngularCompilerPlugin({
|
||||
tsConfigPath: path.resolve(__dirname, 'tsconfig.json'),
|
||||
entryModule: './terminus-core/src/index#AppModule',
|
||||
sourceMap: true,
|
||||
directTemplateLoading: true,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
@@ -3,21 +3,14 @@
|
||||
|
||||
|
||||
"@types/js-yaml@^3.9.0":
|
||||
version "3.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.4.tgz#7d3b534ec35a0585128e2d332db1403ebe057e25"
|
||||
integrity sha512-fYMgzN+9e28R81weVN49inn/u798ruU91En1ZnGvSZzCRc5jXx9B2EDhlRaWmcO1RIxFHL8AajRXzxDuJu93+A==
|
||||
version "3.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656"
|
||||
integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==
|
||||
|
||||
"@types/node@*":
|
||||
version "13.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.1.tgz#238eb34a66431b71d2aaddeaa7db166f25971a0d"
|
||||
integrity sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA==
|
||||
|
||||
"@types/semver@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408"
|
||||
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/semver@^6.0.2":
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
|
||||
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
|
||||
|
||||
"@types/shell-escape@^0.2.0":
|
||||
version "0.2.0"
|
||||
@@ -52,27 +45,23 @@ async@^2.6.1:
|
||||
dependencies:
|
||||
lodash "^4.17.11"
|
||||
|
||||
at-least-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
||||
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
||||
|
||||
axios@^0.19.0:
|
||||
version "0.19.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
|
||||
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
|
||||
integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
|
||||
dependencies:
|
||||
follow-redirects "1.5.10"
|
||||
is-buffer "^2.0.2"
|
||||
|
||||
bootstrap@^4.1.3:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
|
||||
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac"
|
||||
integrity sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==
|
||||
|
||||
builder-util-runtime@8.7.0:
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.0.tgz#e48ad004835c8284662e8eaf47a53468c66e8e8d"
|
||||
integrity sha512-G1AqqVM2vYTrSFR982c1NNzwXKrGLQjVjaZaWQdn4O6Z3YKjdMDofw88aD9jpyK9ZXkrCxR0tI3Qe9wNbyTlXg==
|
||||
builder-util-runtime@8.4.0:
|
||||
version "8.4.0"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz#3163fffc078e6b8f3dd5b6eb12a8345573590682"
|
||||
integrity sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
sax "^1.2.4"
|
||||
@@ -129,9 +118,9 @@ colorspace@1.1.x:
|
||||
text-hex "1.0.x"
|
||||
|
||||
core-js@^3.1.2:
|
||||
version "3.6.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
|
||||
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.2.tgz#ee2b1a60b50388d8ddcda8cdb44a92c7a9ea76df"
|
||||
integrity sha512-bUTfqFWtNKWp73oNIfRkqwYZJeNT3lstzZcAkhhiuvDraRSgOH1/+F9ZklbpR4zpdKuo4cpXN8tKP7s61yjX+g==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
@@ -174,17 +163,18 @@ diagnostics@^1.1.1:
|
||||
kuler "1.0.x"
|
||||
|
||||
electron-updater@^4.0.6:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.1.tgz#9d485b6262bc56fcf7ee62b1dc1b3b105a3e96a7"
|
||||
integrity sha512-UDC5AHCgeiHJYDYWZG/rsl1vdAFKqI/Lm7whN57LKAk8EfhTewhcEHzheRcncLgikMcQL8gFo1KeX51tf5a5Wg==
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.2.0.tgz#f9ecfc657f65ead737d42b9efecf628d3756b550"
|
||||
integrity sha512-GuS3g7HDh17x/SaFjxjswlWUaKHczksYkV2Xc5CKj/bZH0YCvTSHtOmnBAdAmCk99u/71p3zP8f0jIqDfGcjww==
|
||||
dependencies:
|
||||
"@types/semver" "^7.1.0"
|
||||
builder-util-runtime "8.7.0"
|
||||
fs-extra "^9.0.0"
|
||||
"@types/semver" "^6.0.2"
|
||||
builder-util-runtime "8.4.0"
|
||||
fs-extra "^8.1.0"
|
||||
js-yaml "^3.13.1"
|
||||
lazy-val "^1.0.4"
|
||||
lodash.isequal "^4.5.0"
|
||||
semver "^7.1.3"
|
||||
pako "^1.0.10"
|
||||
semver "^6.3.0"
|
||||
|
||||
enabled@1.0.x:
|
||||
version "1.0.2"
|
||||
@@ -232,15 +222,14 @@ follow-redirects@1.5.10:
|
||||
dependencies:
|
||||
debug "=3.1.0"
|
||||
|
||||
fs-extra@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
|
||||
integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==
|
||||
fs-extra@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
|
||||
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
|
||||
dependencies:
|
||||
at-least-node "^1.0.0"
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^1.0.0"
|
||||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.2"
|
||||
@@ -265,6 +254,11 @@ is-arrayish@^0.3.1:
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
||||
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
|
||||
|
||||
is-buffer@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
|
||||
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
|
||||
|
||||
is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
@@ -276,19 +270,17 @@ isarray@~1.0.0:
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
js-yaml@^3.13.1, js-yaml@^3.9.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
|
||||
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
||||
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
|
||||
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==
|
||||
dependencies:
|
||||
universalify "^1.0.0"
|
||||
jsonfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
|
||||
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
@@ -360,6 +352,11 @@ one-time@0.0.4:
|
||||
resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e"
|
||||
integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=
|
||||
|
||||
pako@^1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
|
||||
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
|
||||
|
||||
perfect-scrollbar@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.4.0.tgz#5d014ef9775e1f43058a1dbae9ed1daf0e7091f1"
|
||||
@@ -407,10 +404,10 @@ sax@^1.2.4:
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
semver@^7.1.3:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6"
|
||||
integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==
|
||||
semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
shell-escape@^0.2.0:
|
||||
version "0.2.0"
|
||||
@@ -458,20 +455,20 @@ triple-beam@^1.2.0, triple-beam@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
|
||||
|
||||
universalify@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
||||
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
||||
universalify@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
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=
|
||||
|
||||
uuid@^8.0.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
|
||||
integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
|
||||
uuid@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
||||
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
|
||||
|
||||
winston-transport@^4.3.0:
|
||||
version "4.3.0"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-plugin-manager",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.98-nightly.0",
|
||||
"description": "Terminus' plugin manager",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -17,10 +17,10 @@
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/semver": "^6.0.0",
|
||||
"axios": "^0.19.0",
|
||||
"mz": "^2.6.0",
|
||||
"semver": "^7.1.1"
|
||||
"semver": "^6.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^7",
|
||||
|
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { BehaviorSubject, Observable } from 'rxjs'
|
||||
import { debounceTime, distinctUntilChanged, first, tap, flatMap, map } from 'rxjs/operators'
|
||||
import semverGt from 'semver/functions/gt'
|
||||
import * as semver from 'semver'
|
||||
|
||||
import { Component, Input } from '@angular/core'
|
||||
import { ConfigService, ElectronService } from 'terminus-core'
|
||||
@@ -49,7 +48,7 @@ export class PluginsSettingsTabComponent {
|
||||
return plugins
|
||||
})).subscribe(available => {
|
||||
for (const plugin of this.pluginManager.installedPlugins) {
|
||||
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semverGt(x.version, plugin.version)) || null
|
||||
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version)) || null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -8,10 +8,6 @@ const NAME_PREFIX = 'terminus-'
|
||||
const KEYWORD = 'terminus-plugin'
|
||||
const OFFICIAL_NPM_ACCOUNT = 'eugenepankov'
|
||||
|
||||
const BLACKLIST = [
|
||||
'terminus-shell-selector', // superseded by profiles
|
||||
]
|
||||
|
||||
export interface PluginInfo {
|
||||
name: string
|
||||
description: string
|
||||
@@ -34,13 +30,13 @@ export class PluginManagerService {
|
||||
private npmReady: Promise<void>
|
||||
private npm: any
|
||||
|
||||
private constructor (
|
||||
constructor (
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('pluginManager')
|
||||
}
|
||||
|
||||
async getNPM (): Promise<any> {
|
||||
async getNPM () {
|
||||
if (!this.npm) {
|
||||
if (!this.npmReady) {
|
||||
this.npmReady = new Promise(resolve => {
|
||||
@@ -79,11 +75,10 @@ export class PluginManagerService {
|
||||
isOfficial: item.package.publisher.username === OFFICIAL_NPM_ACCOUNT,
|
||||
}))),
|
||||
map(plugins => plugins.filter(x => x.packageName.startsWith(NAME_PREFIX))),
|
||||
map(plugins => plugins.filter(x => !BLACKLIST.includes(x.packageName))),
|
||||
)
|
||||
}
|
||||
|
||||
async installPlugin (plugin: PluginInfo): Promise<void> {
|
||||
async installPlugin (plugin: PluginInfo) {
|
||||
(await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => {
|
||||
if (err) {
|
||||
this.logger.error(err)
|
||||
@@ -93,7 +88,7 @@ export class PluginManagerService {
|
||||
})
|
||||
}
|
||||
|
||||
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
||||
async uninstallPlugin (plugin: PluginInfo) {
|
||||
(await this.getNPM()).commands.remove([plugin.packageName], err => {
|
||||
if (err) {
|
||||
this.logger.error(err)
|
||||
|
@@ -2,17 +2,10 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/node@*":
|
||||
version "13.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.6.tgz#cb734a7c191472ae6a2b3a502b4dfffcea974113"
|
||||
integrity sha512-eyK7MWD0R1HqVTp+PtwRgFeIsemzuj4gBFSQxfPHY5iMjS7474e5wq+VFgTcdpyHeNxyKSaetYAjdMLJlKoWqA==
|
||||
|
||||
"@types/semver@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408"
|
||||
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/semver@^6.0.0":
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
|
||||
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
|
||||
|
||||
any-promise@^1.0.0:
|
||||
version "1.3.0"
|
||||
@@ -20,11 +13,12 @@ any-promise@^1.0.0:
|
||||
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
|
||||
|
||||
axios@^0.19.0:
|
||||
version "0.19.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
|
||||
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
|
||||
integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
|
||||
dependencies:
|
||||
follow-redirects "1.5.10"
|
||||
is-buffer "^2.0.2"
|
||||
|
||||
debug@=3.1.0:
|
||||
version "3.1.0"
|
||||
@@ -40,6 +34,11 @@ follow-redirects@1.5.10:
|
||||
dependencies:
|
||||
debug "=3.1.0"
|
||||
|
||||
is-buffer@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
|
||||
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
@@ -59,10 +58,10 @@ object-assign@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
semver@^7.1.1:
|
||||
version "7.2.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.2.2.tgz#d01432d74ed3010a20ffaf909d63a691520521cd"
|
||||
integrity sha512-Zo84u6o2PebMSK3zjJ6Zp5wi8VnQZnEaCP13Ul/lt1ANsLACxnJxq4EEm1PY94/por1Hm9+7xpIswdS5AkieMA==
|
||||
semver@^6.1.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
thenify-all@^1.0.0:
|
||||
version "1.6.0"
|
||||
|
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"name": "terminus-serial",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"description": "Serial connection manager for Terminus",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"typings": "typings/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --color",
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "12.7.3",
|
||||
"@types/ssh2": "^0.5.35",
|
||||
"ansi-colors": "^4.1.1",
|
||||
"cli-spinner": "^0.2.10",
|
||||
"electron-rebuild": "^1.10.0",
|
||||
"terminus-terminal": "^1.0.98-nightly.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^7",
|
||||
"@angular/core": "^7",
|
||||
"@angular/forms": "^7",
|
||||
"@ng-bootstrap/ng-bootstrap": "^1",
|
||||
"rxjs": "^5",
|
||||
"terminus-core": "*",
|
||||
"terminus-settings": "*",
|
||||
"terminus-terminal": "*"
|
||||
}
|
||||
}
|
@@ -1,156 +0,0 @@
|
||||
import { BaseSession } from 'terminus-terminal'
|
||||
import { SerialPort } from 'serialport'
|
||||
import { Logger } from 'terminus-core'
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
|
||||
export interface LoginScript {
|
||||
expect: string
|
||||
send: string
|
||||
isRegex?: boolean
|
||||
optional?: boolean
|
||||
}
|
||||
|
||||
export interface SerialConnection {
|
||||
name: string
|
||||
port: string
|
||||
baudrate: number
|
||||
databits: number
|
||||
stopbits: number
|
||||
parity: string
|
||||
rtscts: boolean
|
||||
xon: boolean
|
||||
xoff: boolean
|
||||
xany: boolean
|
||||
scripts?: LoginScript[]
|
||||
color?: string
|
||||
}
|
||||
|
||||
export const BAUD_RATES = [
|
||||
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600,
|
||||
]
|
||||
|
||||
export interface SerialPortInfo {
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export class SerialSession extends BaseSession {
|
||||
scripts?: LoginScript[]
|
||||
serial: SerialPort
|
||||
logger: Logger
|
||||
|
||||
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
||||
private serviceMessage = new Subject<string>()
|
||||
|
||||
constructor (public connection: SerialConnection) {
|
||||
super()
|
||||
this.scripts = connection.scripts || []
|
||||
}
|
||||
|
||||
async start (): Promise<void> {
|
||||
this.open = true
|
||||
|
||||
this.serial.on('data', data => {
|
||||
const dataString = data.toString()
|
||||
this.emitOutput(data)
|
||||
|
||||
if (this.scripts) {
|
||||
let found = false
|
||||
for (const script of this.scripts) {
|
||||
let match = false
|
||||
let cmd = ''
|
||||
if (script.isRegex) {
|
||||
const re = new RegExp(script.expect, 'g')
|
||||
if (dataString.match(re)) {
|
||||
cmd = dataString.replace(re, script.send)
|
||||
match = true
|
||||
found = true
|
||||
}
|
||||
} else {
|
||||
if (dataString.includes(script.expect)) {
|
||||
cmd = script.send
|
||||
match = true
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
this.logger.info('Executing script: "' + cmd + '"')
|
||||
this.serial.write(cmd + '\n')
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
if (script.optional) {
|
||||
this.logger.debug('Skip optional script: ' + script.expect)
|
||||
found = true
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
this.executeUnconditionalScripts()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.serial.on('end', () => {
|
||||
this.logger.info('Shell session ended')
|
||||
if (this.open) {
|
||||
this.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
this.executeUnconditionalScripts()
|
||||
}
|
||||
|
||||
write (data: Buffer): void {
|
||||
if (this.serial) {
|
||||
this.serial.write(data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
async destroy (): Promise<void> {
|
||||
this.serviceMessage.complete()
|
||||
await super.destroy()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
|
||||
resize (_, __) { }
|
||||
|
||||
kill (_?: string): void {
|
||||
this.serial.close()
|
||||
}
|
||||
|
||||
async getChildProcesses (): Promise<any[]> {
|
||||
return []
|
||||
}
|
||||
|
||||
async gracefullyKillProcess (): Promise<void> {
|
||||
this.kill('TERM')
|
||||
}
|
||||
|
||||
async getWorkingDirectory (): Promise<string|null> {
|
||||
return null
|
||||
}
|
||||
|
||||
private executeUnconditionalScripts () {
|
||||
if (this.scripts) {
|
||||
for (const script of this.scripts) {
|
||||
if (!script.expect) {
|
||||
console.log('Executing script:', script.send)
|
||||
this.serial.write(script.send + '\n')
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface SerialConnectionGroup {
|
||||
name: string
|
||||
connections: SerialConnection[]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user