mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-24 20:38:01 +00:00
Compare commits
398 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
aaab475e5f | ||
![]() |
e6bf76c616 | ||
![]() |
e36bad2553 | ||
![]() |
154cc29333 | ||
![]() |
1b0402c2cf | ||
![]() |
15073cbc81 | ||
![]() |
3365b143d8 | ||
![]() |
4d9cc91e91 | ||
![]() |
946f4292ef | ||
![]() |
eb12b1ae60 | ||
![]() |
4765c97d31 | ||
![]() |
3fb32e1a97 | ||
![]() |
9ec1a0d253 | ||
![]() |
fef19615bb | ||
![]() |
4d237baf33 | ||
![]() |
03e654b5a0 | ||
![]() |
ef815eaa40 | ||
![]() |
4771a38747 | ||
![]() |
ce016793d4 | ||
![]() |
3a854f04e1 | ||
![]() |
b5658d61d9 | ||
![]() |
02750d8581 | ||
![]() |
077a3e6bba | ||
![]() |
5454be032a | ||
![]() |
8a0b4f82db | ||
![]() |
74fd1aeea5 | ||
![]() |
aac230e362 | ||
![]() |
ae82ed4a47 | ||
![]() |
9d1b0e9861 | ||
![]() |
8cb4e9f27d | ||
![]() |
c8c00a2c9b | ||
![]() |
bacb475896 | ||
![]() |
c8faa67083 | ||
![]() |
b6c0e3cdfb | ||
![]() |
323581d513 | ||
![]() |
bc7a537c4c | ||
![]() |
10ae6ffd99 | ||
![]() |
847628fbff | ||
![]() |
b502c3e84d | ||
![]() |
85e99ff0a8 | ||
![]() |
21b81f476c | ||
![]() |
02de15a6d2 | ||
![]() |
38a6e7fe67 | ||
![]() |
2283a5dad9 | ||
![]() |
e98c12d409 | ||
![]() |
aacc603309 | ||
![]() |
2ef3a81dd8 | ||
![]() |
22ef1bbb87 | ||
![]() |
7ff9f268c9 | ||
![]() |
7866bcd9a4 | ||
![]() |
5a20ac19d9 | ||
![]() |
915f6acf22 | ||
![]() |
59b73fcdc1 | ||
![]() |
8699634492 | ||
![]() |
d625e90464 | ||
![]() |
bc31c775e9 | ||
![]() |
49424e8da5 | ||
![]() |
2526c4e458 | ||
![]() |
24de3ba77c | ||
![]() |
157ed82000 | ||
![]() |
8275a9449a | ||
![]() |
6ed6b90840 | ||
![]() |
d7565e497d | ||
![]() |
de827ef61a | ||
![]() |
7b4e99fc5f | ||
![]() |
035a6f8da8 | ||
![]() |
bcdbab43de | ||
![]() |
a24f52c58a | ||
![]() |
0e745ea607 | ||
![]() |
8fe9232d9b | ||
![]() |
e6004fa980 | ||
![]() |
987b89b914 | ||
![]() |
9fddfa6fc2 | ||
![]() |
6d765bb1b8 | ||
![]() |
0ca971a289 | ||
![]() |
e87f6e7af0 | ||
![]() |
56be0a1085 | ||
![]() |
41f464d21d | ||
![]() |
c8dde73158 | ||
![]() |
0971a85db4 | ||
![]() |
51d54a8477 | ||
![]() |
b75775283f | ||
![]() |
66558290a0 | ||
![]() |
a1980afd9d | ||
![]() |
2b28802ce7 | ||
![]() |
0514a7c229 | ||
![]() |
326901b7e8 | ||
![]() |
bbe6b61d63 | ||
![]() |
204c1057db | ||
![]() |
dff6a2470c | ||
![]() |
cbebc09504 | ||
![]() |
f56dd71f43 | ||
![]() |
17f52a257e | ||
![]() |
8d09ddb686 | ||
![]() |
e6fd31e0b0 | ||
![]() |
c6188a49f5 | ||
![]() |
9a60b4d102 | ||
![]() |
7977c1d644 | ||
![]() |
ac85a1d7d3 | ||
![]() |
86b503093c | ||
![]() |
dd3e7a0f89 | ||
![]() |
8905106b48 | ||
![]() |
225760a9a5 | ||
![]() |
4aa79a76ea | ||
![]() |
1e2d6c7e75 | ||
![]() |
f1e79e9ada | ||
![]() |
37cc37650e | ||
![]() |
d607b7423a | ||
![]() |
a2e843ec84 | ||
![]() |
17cafbfa52 | ||
![]() |
91333abc4f | ||
![]() |
05b2b11af5 | ||
![]() |
3931e8088e | ||
![]() |
299ede2eb1 | ||
![]() |
4fed323a2a | ||
![]() |
b4bf8ec250 | ||
![]() |
780657ce1d | ||
![]() |
2d558563e4 | ||
![]() |
bc5e6e9535 | ||
![]() |
0c15fc2657 | ||
![]() |
5e115c63f1 | ||
![]() |
2bcf23cff1 | ||
![]() |
2c59022b78 | ||
![]() |
358d9f30d2 | ||
![]() |
afd6ce4346 | ||
![]() |
5c7256ffe5 | ||
![]() |
a15e79ad5a | ||
![]() |
f1ecbd1a93 | ||
![]() |
7da941d038 | ||
![]() |
3efc142630 | ||
![]() |
d592469237 | ||
![]() |
b3e63620b3 | ||
![]() |
22b79510ea | ||
![]() |
70cf63f8fa | ||
![]() |
c9067cf8b8 | ||
![]() |
4ccc406768 | ||
![]() |
1c25747de0 | ||
![]() |
8e4c36ec24 | ||
![]() |
444d92d393 | ||
![]() |
2597702676 | ||
![]() |
c9d75d81e4 | ||
![]() |
98eb68c845 | ||
![]() |
5185e1fe1d | ||
![]() |
5bde116a4e | ||
![]() |
179acc1382 | ||
![]() |
c6d918e401 | ||
![]() |
62b53575ac | ||
![]() |
32b29a91e9 | ||
![]() |
4346030459 | ||
![]() |
9e8c0ccb14 | ||
![]() |
6c8d00eb16 | ||
![]() |
b3fcfd0c8b | ||
![]() |
4eefab5655 | ||
![]() |
2745896ec3 | ||
![]() |
cdfaaabb70 | ||
![]() |
60ab6ece62 | ||
![]() |
436318b534 | ||
![]() |
248f431437 | ||
![]() |
7794280115 | ||
![]() |
c2cc4c977f | ||
![]() |
f9b7f97863 | ||
![]() |
59ce7eeee6 | ||
![]() |
0e012a90ea | ||
![]() |
6773d260cf | ||
![]() |
7379f6cd59 | ||
![]() |
3aee24bdbd | ||
![]() |
84dbfa5d6c | ||
![]() |
43958d88b8 | ||
![]() |
f4b0e4cb52 | ||
![]() |
d91c898f6d | ||
![]() |
f16989a45d | ||
![]() |
1ef524e832 | ||
![]() |
65fcdd2745 | ||
![]() |
7030f562e8 | ||
![]() |
047b31dd67 | ||
![]() |
ae0d33f026 | ||
![]() |
039a0b7eb5 | ||
![]() |
3d3fcc41b8 | ||
![]() |
3e3e8f3132 | ||
![]() |
da21895e40 | ||
![]() |
34752ed69e | ||
![]() |
008eb98f50 | ||
![]() |
e521cd4648 | ||
![]() |
cb97a784da | ||
![]() |
96d9d81be2 | ||
![]() |
71797eb93f | ||
![]() |
ae3870e297 | ||
![]() |
055de5013c | ||
![]() |
ad1ea01976 | ||
![]() |
064fbfac67 | ||
![]() |
a31c83476d | ||
![]() |
bc9f4c267e | ||
![]() |
3e92ae278e | ||
![]() |
6adc3543a8 | ||
![]() |
af5293948c | ||
![]() |
34620db925 | ||
![]() |
4a5a96ea16 | ||
![]() |
fcc9d7cf7d | ||
![]() |
9cae50bfc5 | ||
![]() |
3cff5909bd | ||
![]() |
0130cd9d54 | ||
![]() |
926d4f51b3 | ||
![]() |
efe390f68d | ||
![]() |
6d0b2608a2 | ||
![]() |
ddd306dbf6 | ||
![]() |
30c632a5cc | ||
![]() |
65b3254b77 | ||
![]() |
f776a30c9f | ||
![]() |
c02525440c | ||
![]() |
dbda8dad34 | ||
![]() |
bc44f55989 | ||
![]() |
a3c998adab | ||
![]() |
b62b59f9b8 | ||
![]() |
bb1557b0a4 | ||
![]() |
d0fe64355b | ||
![]() |
7b4e6e8f3a | ||
![]() |
bd11c90846 | ||
![]() |
21f33618d4 | ||
![]() |
11c8ca6582 | ||
![]() |
6e9ac1b59a | ||
![]() |
91591a81ff | ||
![]() |
1ce0ff2e00 | ||
![]() |
92cef766f6 | ||
![]() |
d1d55d39b1 | ||
![]() |
4ad55bff6e | ||
![]() |
f73c41a709 | ||
![]() |
3ca55d972a | ||
![]() |
2b25c25337 | ||
![]() |
3621877f32 | ||
![]() |
cf2a8ddc96 | ||
![]() |
d461515881 | ||
![]() |
5828571a95 | ||
![]() |
3aba7c9b93 | ||
![]() |
d371bf2f41 | ||
![]() |
51934dccbd | ||
![]() |
b6caf47ce6 | ||
![]() |
e8362268bb | ||
![]() |
88c57a6794 | ||
![]() |
69a0b46a20 | ||
![]() |
a5a662c05d | ||
![]() |
4ab0b51d87 | ||
![]() |
c3285b24d9 | ||
![]() |
313345da3d | ||
![]() |
7173be8c22 | ||
![]() |
b97ef8c643 | ||
![]() |
d221f8e561 | ||
![]() |
95ed0a58b9 | ||
![]() |
77d4176b55 | ||
![]() |
48013e2102 | ||
![]() |
31dcb2b514 | ||
![]() |
43a9a7cb19 | ||
![]() |
88cecba2b6 | ||
![]() |
91e1870f91 | ||
![]() |
705050a96a | ||
![]() |
8d2550fb99 | ||
![]() |
c4a89d4ee3 | ||
![]() |
6140cdfabc | ||
![]() |
5786d61620 | ||
![]() |
32f6e16275 | ||
![]() |
668986fc08 | ||
![]() |
9190893ccf | ||
![]() |
546837ab55 | ||
![]() |
3825feae08 | ||
![]() |
fdeabae061 | ||
![]() |
8b307be92d | ||
![]() |
45516c4013 | ||
![]() |
5d8f7a4e34 | ||
![]() |
792c9279e2 | ||
![]() |
8825a8163e | ||
![]() |
7e42328c6f | ||
![]() |
2dd99d43ed | ||
![]() |
991b4fc965 | ||
![]() |
e9d7af5320 | ||
![]() |
bff23fe825 | ||
![]() |
79bd94ee6f | ||
![]() |
fdd833ef7c | ||
![]() |
c386504296 | ||
![]() |
9cc8649422 | ||
![]() |
625a9179c5 | ||
![]() |
66ed73f7c9 | ||
![]() |
95bd48d6c6 | ||
![]() |
328490a85e | ||
![]() |
d08413aeab | ||
![]() |
922f1fbade | ||
![]() |
cb96c8d470 | ||
![]() |
f3ebc43667 | ||
![]() |
e7696dcdf3 | ||
![]() |
4abf7d7738 | ||
![]() |
be206161d6 | ||
![]() |
dcd17f886e | ||
![]() |
2c94dea941 | ||
![]() |
7a2291f7db | ||
![]() |
af0d9142ed | ||
![]() |
6ba7d5b78f | ||
![]() |
bbf035d5fd | ||
![]() |
84bc4369cb | ||
![]() |
e01f77998c | ||
![]() |
08acd4df46 | ||
![]() |
2c9d968aa8 | ||
![]() |
19a3996861 | ||
![]() |
6d187e8117 | ||
![]() |
a7687a6fc2 | ||
![]() |
7cbec63039 | ||
![]() |
91320f1cd7 | ||
![]() |
5518ce5e0c | ||
![]() |
d59c52d7a5 | ||
![]() |
dd3a4cb289 | ||
![]() |
fc6ded4b1a | ||
![]() |
d4f61b3846 | ||
![]() |
ffad7b6ba7 | ||
![]() |
499f541328 | ||
![]() |
7c893a3c4b | ||
![]() |
1f5c55826b | ||
![]() |
197824004e | ||
![]() |
ee1d465bf6 | ||
![]() |
12bb070def | ||
![]() |
13ab29bcab | ||
![]() |
8cf0445b6d | ||
![]() |
90cc06c3fd | ||
![]() |
7d7b2cbcfd | ||
![]() |
3a76e0bb2e | ||
![]() |
9e2d070ed4 | ||
![]() |
f796718cae | ||
![]() |
a4c2ccdb93 | ||
![]() |
ccbaf1c2c2 | ||
![]() |
7ccd97eb49 | ||
![]() |
6b320e9cf3 | ||
![]() |
a6a5f2b132 | ||
![]() |
6fd7e97ef2 | ||
![]() |
fc821b5abd | ||
![]() |
f69a9b38fe | ||
![]() |
710b9d79ab | ||
![]() |
fddae662c8 | ||
![]() |
c3b3a3cea6 | ||
![]() |
2201cfe142 | ||
![]() |
a9ae3b2475 | ||
![]() |
3238706b25 | ||
![]() |
a5aec13b7f | ||
![]() |
454887ad21 | ||
![]() |
0ad585d647 | ||
![]() |
5aa3b889f5 | ||
![]() |
d371857fa8 | ||
![]() |
e116a42f8b | ||
![]() |
76acbc6c9f | ||
![]() |
572a6e24c4 | ||
![]() |
b3731a21ba | ||
![]() |
f58ba65d97 | ||
![]() |
45a99bb0cb | ||
![]() |
ab70be983a | ||
![]() |
cad1f96df7 | ||
![]() |
71866521f4 | ||
![]() |
56206d4fb8 | ||
![]() |
347681d199 | ||
![]() |
e6abdcf3e9 | ||
![]() |
dbae3b66cd | ||
![]() |
40ec457d20 | ||
![]() |
063caf3bcd | ||
![]() |
9325fd0977 | ||
![]() |
6231583590 | ||
![]() |
fce3a2c822 | ||
![]() |
73f45c9a24 | ||
![]() |
ca65f23c70 | ||
![]() |
f525398827 | ||
![]() |
cf2baa74a8 | ||
![]() |
fbd896d593 | ||
![]() |
f747107042 | ||
![]() |
760ad140cd | ||
![]() |
a0df434ed2 | ||
![]() |
0bcd5cfd8f | ||
![]() |
e0b71783c0 | ||
![]() |
45b76b2d3e | ||
![]() |
8228c99350 | ||
![]() |
c4dbd8180d | ||
![]() |
d3b1545a1e | ||
![]() |
57d7936239 | ||
![]() |
9e5315043d | ||
![]() |
89ba81f2e1 | ||
![]() |
1ee734cd18 | ||
![]() |
0bcfb6babf | ||
![]() |
fddd9e9db2 | ||
![]() |
2433fd1442 | ||
![]() |
437d832ac1 | ||
![]() |
c90aef1dfa | ||
![]() |
2d25f15041 | ||
![]() |
993d5bfd25 | ||
![]() |
4d8681b5ee | ||
![]() |
1384e26dd8 | ||
![]() |
809bf3360d | ||
![]() |
444875b82a | ||
![]() |
c261b64c8e | ||
![]() |
ab1b8a4500 | ||
![]() |
e65d5ba93b | ||
![]() |
6f8ba6b44b | ||
![]() |
aede1c47a2 | ||
![]() |
7b9ff043ad | ||
![]() |
d759104c76 | ||
![]() |
676bbba7a4 | ||
![]() |
b8d9f6442a |
@@ -262,6 +262,78 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Goobles",
|
||||
"name": "Gobius Dolhain",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/8776771?v=4",
|
||||
"profile": "https://github.com/Goobles",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "3l0w",
|
||||
"name": "Gwilherm Folliot",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/37798980?v=4",
|
||||
"profile": "https://github.com/3l0w",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dimitory",
|
||||
"name": "Dmitry Pronin",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/475955?v=4",
|
||||
"profile": "https://github.com/Dimitory",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "JonathanBeverley",
|
||||
"name": "Jonathan Beverley",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/20328966?v=4",
|
||||
"profile": "https://github.com/JonathanBeverley",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zend",
|
||||
"name": "Zenghai Liang",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/25160?v=4",
|
||||
"profile": "https://github.com/zend",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "matishadow",
|
||||
"name": "Mateusz Tracz",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/9083085?v=4",
|
||||
"profile": "https://about.me/matishadow",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pinpins",
|
||||
"name": "pinpin",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/36234677?v=4",
|
||||
"profile": "https://zergpool.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "TakuroOnoda",
|
||||
"name": "Takuro Onoda",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/1407926?v=4",
|
||||
"profile": "https://github.com/TakuroOnoda",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
@@ -29,7 +29,6 @@ rules:
|
||||
'@typescript-eslint/no-magic-numbers': off
|
||||
'@typescript-eslint/member-delimiter-style': off
|
||||
'@typescript-eslint/promise-function-async': off
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': off
|
||||
'@typescript-eslint/require-array-sort-compare': off
|
||||
'@typescript-eslint/no-floating-promises': off
|
||||
'@typescript-eslint/prefer-readonly': off
|
||||
@@ -37,6 +36,7 @@ rules:
|
||||
'@typescript-eslint/strict-boolean-expressions': off
|
||||
'@typescript-eslint/no-misused-promises': off
|
||||
'@typescript-eslint/typedef': off
|
||||
'@typescript-eslint/consistent-type-imports': off
|
||||
'@typescript-eslint/no-use-before-define':
|
||||
- error
|
||||
- classes: false
|
||||
@@ -53,7 +53,8 @@ rules:
|
||||
computed-property-spacing:
|
||||
- error
|
||||
- never
|
||||
comma-dangle:
|
||||
comma-dangle: off
|
||||
'@typescript-eslint/comma-dangle':
|
||||
- error
|
||||
- always-multiline
|
||||
curly: error
|
||||
@@ -93,14 +94,22 @@ rules:
|
||||
- error
|
||||
- single
|
||||
- allowTemplateLiterals: true
|
||||
'@typescript-eslint/no-confusing-void-expression': off
|
||||
'@typescript-eslint/no-non-null-assertion': off
|
||||
'@typescript-eslint/no-unnecessary-condition': off
|
||||
'@typescript-eslint/no-untyped-public-signature': off # bugs out on constructors
|
||||
'@typescript-eslint/no-unnecessary-condition':
|
||||
- error
|
||||
- allowConstantLoopConditions: true
|
||||
'@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
|
||||
'@typescript-eslint/no-unsafe-assignment': off
|
||||
'@typescript-eslint/naming-convention': off
|
||||
'@typescript-eslint/lines-between-class-members':
|
||||
- error
|
||||
- exceptAfterSingleLine: true
|
||||
'@typescript-eslint/dot-notation': off
|
||||
'@typescript-eslint/no-implicit-any-catch': off
|
||||
'@typescript-eslint/member-ordering': off
|
||||
'@typescript-eslint/no-var-requires': off
|
||||
|
5
.github/workflows/lint.yml
vendored
5
.github/workflows/lint.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 15
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
@@ -22,5 +22,8 @@ jobs:
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
|
||||
- name: Build typings
|
||||
run: yarn run build:typings
|
||||
|
||||
- name: Lint
|
||||
run: yarn run lint
|
||||
|
3
.github/workflows/linux.yml
vendored
3
.github/workflows/linux.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 15
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
@@ -36,6 +36,7 @@ jobs:
|
||||
env:
|
||||
DEBUG: electron-builder,electron-builder:*
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
USE_HARD_LINKS: false
|
||||
|
||||
- name: Package artifacts
|
||||
run: |
|
||||
|
30
.github/workflows/macos.yml
vendored
30
.github/workflows/macos.yml
vendored
@@ -2,7 +2,12 @@ name: macOS Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macOS-latest
|
||||
runs-on: macos-11.0
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
- arch: arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -11,11 +16,11 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 15
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo npm i -g yarn@1.19.1
|
||||
sudo npm i -g yarn@1.22.1
|
||||
cd app
|
||||
yarn
|
||||
cd ..
|
||||
@@ -24,27 +29,38 @@ jobs:
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
env:
|
||||
ARCH: ${{matrix.arch}}
|
||||
|
||||
- name: Webpack
|
||||
run: yarn run build
|
||||
|
||||
- name: Prepackage plugins
|
||||
run: scripts/prepackage-plugins.js
|
||||
env:
|
||||
ARCH: ${{matrix.arch}}
|
||||
|
||||
- run: sed -i '' 's/updateInfo = await/\/\/updateInfo = await/g' node_modules/app-builder-lib/out/targets/ArchiveTarget.js
|
||||
|
||||
- name: Build and sign packages
|
||||
run: scripts/build-macos.js
|
||||
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
|
||||
env:
|
||||
#DEBUG: electron-builder,electron-builder:*
|
||||
ARCH: ${{matrix.arch}}
|
||||
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 }}
|
||||
USE_HARD_LINKS: false
|
||||
# DEBUG: electron-builder,electron-builder:*
|
||||
|
||||
- name: Build packages without signing
|
||||
run: scripts/build-macos.js
|
||||
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
||||
env:
|
||||
DEBUG: electron-builder,electron-builder:*
|
||||
ARCH: ${{matrix.arch}}
|
||||
# DEBUG: electron-builder,electron-builder:*
|
||||
|
||||
- name: Package artifacts
|
||||
run: |
|
||||
@@ -56,11 +72,11 @@ jobs:
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload PKG
|
||||
with:
|
||||
name: macOS .pkg
|
||||
name: macOS .pkg (${{matrix.arch}})
|
||||
path: artifact-pkg
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload ZIP
|
||||
with:
|
||||
name: macOS .zip
|
||||
name: macOS .zip (${{matrix.arch}})
|
||||
path: artifact-zip
|
||||
|
2
.github/workflows/windows.yml
vendored
2
.github/workflows/windows.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
node-version: 14
|
||||
|
||||
- name: Build
|
||||
shell: powershell
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -13,6 +13,9 @@ dist
|
||||
*.xcuserstate
|
||||
*.wixpdb
|
||||
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
|
||||
coverage
|
||||
.nyc_output
|
||||
npm-debug.log
|
||||
@@ -28,3 +31,5 @@ docs/api
|
||||
.electron-symbols
|
||||
sentry.properties
|
||||
sentry-symbols.js
|
||||
|
||||
terminus-ssh/util/pagent.exe
|
||||
|
@@ -1,5 +1,5 @@
|
||||
language: node_js
|
||||
node_js: 11
|
||||
node_js: 15
|
||||
|
||||
stages:
|
||||
- Build
|
||||
|
18
README.md
18
README.md
@@ -1,12 +1,12 @@
|
||||

|
||||
****
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/terminus.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
|
||||
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/****terminus****.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=DOWNLOAD&logo=github&style=for-the-badge"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts"><img src="https://img.shields.io/badge/download-nightly%20build-magenta.svg?logo=appveyor&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=blue&logo=gitter&style=for-the-badge"></a>
|
||||
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=RELEASE&logo=github&style=for-the-badge"></a> <a href="https://nightly.link/Eugeny/terminus/workflows/windows/master"><img src="https://shields.io/badge/-Nightly-blue?logo=windows&style=for-the-badge"/></a> <a href="https://nightly.link/Eugeny/terminus/workflows/macos/master"><img src="https://shields.io/badge/-Nightly-black?logo=apple&style=for-the-badge"/></a> <a href="https://nightly.link/Eugeny/terminus/workflows/linux/master"><img src="https://shields.io/badge/-Nightly-orange?logo=linux&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=magenta&logo=gitter&style=for-the-badge"></a>
|
||||
</p>
|
||||
|
||||
----
|
||||
@@ -109,6 +109,18 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<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/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { app, ipcMain, Menu, Tray, shell, globalShortcut } from 'electron'
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import * as electron from 'electron'
|
||||
import { app, ipcMain, Menu, Tray, shell, screen, globalShortcut, MenuItemConstructorOptions } from 'electron'
|
||||
import * as promiseIpc from 'electron-promise-ipc'
|
||||
import { loadConfig } from './config'
|
||||
import { Window, WindowOptions } from './window'
|
||||
import { pluginManager } from './pluginManager'
|
||||
|
||||
export class Application {
|
||||
private tray: Tray
|
||||
private tray?: Tray
|
||||
private windows: Window[] = []
|
||||
|
||||
constructor () {
|
||||
@@ -15,13 +15,21 @@ export class Application {
|
||||
|
||||
ipcMain.on('app:register-global-hotkey', (_event, specs) => {
|
||||
globalShortcut.unregisterAll()
|
||||
for (let spec of specs) {
|
||||
for (const spec of specs) {
|
||||
globalShortcut.register(spec, () => {
|
||||
this.onGlobalHotkey()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
;(promiseIpc as any).on('plugin-manager:install', (path, name, version) => {
|
||||
return pluginManager.install(path, name, version)
|
||||
})
|
||||
|
||||
;(promiseIpc as any).on('plugin-manager:uninstall', (path, name) => {
|
||||
return pluginManager.uninstall(path, name)
|
||||
})
|
||||
|
||||
const configData = loadConfig()
|
||||
if (process.platform === 'linux') {
|
||||
app.commandLine.appendSwitch('no-sandbox')
|
||||
@@ -41,11 +49,13 @@ export class Application {
|
||||
}
|
||||
|
||||
init (): void {
|
||||
electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
|
||||
screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
|
||||
screen.on('display-added', () => this.broadcast('host:displays-changed'))
|
||||
screen.on('display-removed', () => this.broadcast('host:displays-changed'))
|
||||
}
|
||||
|
||||
async newWindow (options?: WindowOptions): Promise<Window> {
|
||||
let window = new Window(options)
|
||||
const window = new Window(options)
|
||||
this.windows.push(window)
|
||||
window.visible$.subscribe(visible => {
|
||||
if (visible) {
|
||||
@@ -66,29 +76,29 @@ export class Application {
|
||||
|
||||
onGlobalHotkey (): void {
|
||||
if (this.windows.some(x => x.isFocused())) {
|
||||
for (let window of this.windows) {
|
||||
for (const window of this.windows) {
|
||||
window.hide()
|
||||
}
|
||||
} else {
|
||||
for (let window of this.windows) {
|
||||
for (const window of this.windows) {
|
||||
window.present()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
presentAllWindows (): void {
|
||||
for (let window of this.windows) {
|
||||
for (const window of this.windows) {
|
||||
window.present()
|
||||
}
|
||||
}
|
||||
|
||||
broadcast (event: string, ...args): void {
|
||||
broadcast (event: string, ...args: any[]): void {
|
||||
for (const window of this.windows) {
|
||||
window.send(event, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
async send (event: string, ...args): Promise<void> {
|
||||
async send (event: string, ...args: any[]): Promise<void> {
|
||||
if (!this.hasWindows()) {
|
||||
await this.newWindow()
|
||||
}
|
||||
@@ -121,10 +131,8 @@ export class Application {
|
||||
}
|
||||
|
||||
disableTray (): void {
|
||||
if (this.tray) {
|
||||
this.tray.destroy()
|
||||
this.tray = null
|
||||
}
|
||||
this.tray?.destroy()
|
||||
this.tray = null
|
||||
}
|
||||
|
||||
hasWindows (): boolean {
|
||||
@@ -132,13 +140,18 @@ export class Application {
|
||||
}
|
||||
|
||||
focus (): void {
|
||||
for (let window of this.windows) {
|
||||
for (const window of this.windows) {
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
|
||||
handleSecondInstance (argv: string[], cwd: string): void {
|
||||
this.presentAllWindows()
|
||||
this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd)
|
||||
}
|
||||
|
||||
private setupMenu () {
|
||||
let template: Electron.MenuItemConstructorOptions[] = [
|
||||
const template: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Application',
|
||||
submenu: [
|
||||
|
@@ -5,7 +5,7 @@ export function parseArgs (argv: string[], cwd: string): any {
|
||||
argv = argv.slice(1)
|
||||
}
|
||||
|
||||
return require('yargs')
|
||||
return require('yargs/yargs')(argv.slice(1))
|
||||
.usage('terminus [command] [arguments]')
|
||||
.command('open [directory]', 'open a shell in a directory', {
|
||||
directory: { type: 'string', 'default': cwd },
|
||||
@@ -41,5 +41,5 @@ export function parseArgs (argv: string[], cwd: string): any {
|
||||
type: 'boolean',
|
||||
})
|
||||
.help('help')
|
||||
.parse(argv.slice(1))
|
||||
.parse()
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import * as yaml from 'js-yaml'
|
||||
import { app } from 'electron'
|
||||
|
||||
export function loadConfig (): any {
|
||||
let configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||
const configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||
if (fs.existsSync(configPath)) {
|
||||
return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
|
||||
} else {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import './portable'
|
||||
import 'source-map-support/register'
|
||||
import './sentry'
|
||||
import './lru'
|
||||
import { app, ipcMain, Menu } from 'electron'
|
||||
@@ -34,8 +35,7 @@ process.on('uncaughtException' as any, err => {
|
||||
})
|
||||
|
||||
app.on('second-instance', (_event, argv, cwd) => {
|
||||
application.presentAllWindows()
|
||||
application.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
||||
application.handleSecondInstance(argv, cwd)
|
||||
})
|
||||
|
||||
const argv = parseArgs(process.argv, process.cwd())
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as createLRU from 'lru-cache'
|
||||
import * as LRU from 'lru-cache'
|
||||
import * as fs from 'fs'
|
||||
const lru = createLRU({ max: 256, maxAge: 250 })
|
||||
const lru = new LRU({ max: 256, maxAge: 250 })
|
||||
const origLstat = fs.realpathSync.bind(fs)
|
||||
|
||||
// NB: The biggest offender of thrashing realpathSync is the node module system
|
||||
|
40
app/lib/pluginManager.ts
Normal file
40
app/lib/pluginManager.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { promisify } from 'util'
|
||||
|
||||
|
||||
export class PluginManager {
|
||||
npm: any
|
||||
npmReady?: Promise<void>
|
||||
|
||||
async ensureLoaded (): Promise<void> {
|
||||
if (!this.npmReady) {
|
||||
this.npmReady = new Promise(resolve => {
|
||||
const npm = require('npm')
|
||||
npm.load(err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
npm.config.set('global', false)
|
||||
this.npm = npm
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
return this.npmReady
|
||||
}
|
||||
|
||||
async install (path: string, name: string, version: string): Promise<void> {
|
||||
await this.ensureLoaded()
|
||||
this.npm.prefix = path
|
||||
return promisify(this.npm.commands.install)([`${name}@${version}`])
|
||||
}
|
||||
|
||||
async uninstall (path: string, name: string): Promise<void> {
|
||||
await this.ensureLoaded()
|
||||
this.npm.prefix = path
|
||||
return promisify(this.npm.commands.remove)([name])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const pluginManager = new PluginManager()
|
@@ -8,17 +8,15 @@ try {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const { init } = process.type === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer')
|
||||
const { init } = String(process.type) === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer')
|
||||
import * as isDev from 'electron-is-dev'
|
||||
|
||||
|
||||
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
|
||||
let release
|
||||
let release = null
|
||||
try {
|
||||
release = require('electron').app.getVersion()
|
||||
} catch {
|
||||
|
@@ -1,18 +1,22 @@
|
||||
import * as glasstron from 'glasstron'
|
||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
||||
glasstron.init()
|
||||
}
|
||||
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
import { debounceTime } from 'rxjs/operators'
|
||||
import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen } from 'electron'
|
||||
import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen, BrowserWindowConstructorOptions } from 'electron'
|
||||
import ElectronConfig = require('electron-config')
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
import macOSRelease from 'macos-release'
|
||||
import * as compareVersions from 'compare-versions'
|
||||
|
||||
import { parseArgs } from './cli'
|
||||
import { loadConfig } from './config'
|
||||
|
||||
let SetWindowCompositionAttribute: any
|
||||
let AccentState: any
|
||||
let DwmEnableBlurBehindWindow: any
|
||||
let DwmEnableBlurBehindWindow: any = null
|
||||
if (process.platform === 'win32') {
|
||||
SetWindowCompositionAttribute = require('windows-swca').SetWindowCompositionAttribute
|
||||
AccentState = require('windows-swca').ACCENT_STATE
|
||||
DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow
|
||||
}
|
||||
|
||||
@@ -20,13 +24,20 @@ export interface WindowOptions {
|
||||
hidden?: boolean
|
||||
}
|
||||
|
||||
abstract class GlasstronWindow extends BrowserWindow {
|
||||
blurType: string
|
||||
abstract setBlur (_: boolean)
|
||||
}
|
||||
|
||||
const macOSVibrancyType = compareVersions.compare(macOSRelease().version, '10.14', '>=') ? 'fullscreen-ui' : 'dark'
|
||||
|
||||
export class Window {
|
||||
ready: Promise<void>
|
||||
private visible = new Subject<boolean>()
|
||||
private closed = new Subject<void>()
|
||||
private window: BrowserWindow
|
||||
private window?: GlasstronWindow
|
||||
private windowConfig: ElectronConfig
|
||||
private windowBounds: Rectangle
|
||||
private windowBounds?: Rectangle
|
||||
private closing = false
|
||||
private lastVibrancy: {enabled: boolean, type?: string} | null = null
|
||||
private disableVibrancyWhileDragging = false
|
||||
@@ -38,13 +49,13 @@ export class Window {
|
||||
constructor (options?: WindowOptions) {
|
||||
this.configStore = loadConfig()
|
||||
|
||||
options = options || {}
|
||||
options = options ?? {}
|
||||
|
||||
this.windowConfig = new ElectronConfig({ name: 'window' })
|
||||
this.windowBounds = this.windowConfig.get('windowBoundaries')
|
||||
|
||||
let maximized = this.windowConfig.get('maximized')
|
||||
let bwOptions: Electron.BrowserWindowConstructorOptions = {
|
||||
const maximized = this.windowConfig.get('maximized')
|
||||
const bwOptions: BrowserWindowConstructorOptions = {
|
||||
width: 800,
|
||||
height: 600,
|
||||
title: 'Terminus',
|
||||
@@ -54,6 +65,7 @@ export class Window {
|
||||
nodeIntegration: true,
|
||||
preload: path.join(__dirname, 'sentry.js'),
|
||||
backgroundThrottling: false,
|
||||
enableRemoteModule: true,
|
||||
},
|
||||
frame: false,
|
||||
show: false,
|
||||
@@ -81,14 +93,15 @@ export class Window {
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
bwOptions.backgroundColor = '#131d27'
|
||||
if (process.platform === 'darwin') {
|
||||
this.window = new BrowserWindow(bwOptions) as GlasstronWindow
|
||||
} else {
|
||||
this.window = new glasstron.BrowserWindow(bwOptions)
|
||||
}
|
||||
|
||||
this.window = new BrowserWindow(bwOptions)
|
||||
this.window.once('ready-to-show', () => {
|
||||
if (process.platform === 'darwin') {
|
||||
this.window.setVibrancy('window')
|
||||
this.window.setVibrancy(macOSVibrancyType)
|
||||
} else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) {
|
||||
this.setVibrancy(true)
|
||||
}
|
||||
@@ -100,6 +113,13 @@ export class Window {
|
||||
this.window.show()
|
||||
}
|
||||
this.window.focus()
|
||||
this.window.moveTop()
|
||||
}
|
||||
})
|
||||
|
||||
this.window.on('blur', () => {
|
||||
if (this.configStore.appearance?.dockHideOnBlur) {
|
||||
this.hide()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -122,36 +142,35 @@ export class Window {
|
||||
})
|
||||
}
|
||||
|
||||
setVibrancy (enabled: boolean, type?: string): void {
|
||||
this.lastVibrancy = { enabled, type }
|
||||
setVibrancy (enabled: boolean, type?: string, userRequested?: boolean): void {
|
||||
if (userRequested ?? true) {
|
||||
this.lastVibrancy = { enabled, type }
|
||||
}
|
||||
if (process.platform === 'win32') {
|
||||
if (parseFloat(os.release()) >= 10) {
|
||||
let attribValue = AccentState.ACCENT_DISABLED
|
||||
if (enabled) {
|
||||
if (type === 'fluent') {
|
||||
attribValue = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND
|
||||
} else {
|
||||
attribValue = AccentState.ACCENT_ENABLE_BLURBEHIND
|
||||
}
|
||||
}
|
||||
SetWindowCompositionAttribute(this.window.getNativeWindowHandle(), attribValue, 0x00000000)
|
||||
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
|
||||
this.window.setBlur(enabled)
|
||||
} else {
|
||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||
}
|
||||
} else if (process.platform === 'linux') {
|
||||
this.window.setBackgroundColor(enabled ? '#00000000' : '#131d27')
|
||||
this.window.setBlur(enabled)
|
||||
} else {
|
||||
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
|
||||
this.window.setVibrancy(enabled ? macOSVibrancyType : null)
|
||||
}
|
||||
}
|
||||
|
||||
show (): void {
|
||||
this.window.show()
|
||||
this.window.moveTop()
|
||||
}
|
||||
|
||||
focus (): void {
|
||||
this.window.focus()
|
||||
}
|
||||
|
||||
send (event: string, ...args): void {
|
||||
send (event: string, ...args: any[]): void {
|
||||
if (!this.window) {
|
||||
return
|
||||
}
|
||||
@@ -193,12 +212,21 @@ export class Window {
|
||||
this.window.focus()
|
||||
})
|
||||
} else {
|
||||
// docked, visible
|
||||
this.window.hide()
|
||||
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 {
|
||||
this.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
||||
}
|
||||
|
||||
private setupWindowManagement () {
|
||||
this.window.on('show', () => {
|
||||
this.visible.next(true)
|
||||
@@ -209,7 +237,7 @@ export class Window {
|
||||
this.visible.next(false)
|
||||
})
|
||||
|
||||
let moveSubscription = new Observable<void>(observer => {
|
||||
const moveSubscription = new Observable<void>(observer => {
|
||||
this.window.on('move', () => observer.next())
|
||||
}).pipe(debounceTime(250)).subscribe(() => {
|
||||
this.send('host:window-moved')
|
||||
@@ -344,24 +372,21 @@ export class Window {
|
||||
this.disableVibrancyWhileDragging = value
|
||||
})
|
||||
|
||||
this.window.on('will-move', () => {
|
||||
let moveEndedTimeout: number|null = null
|
||||
const onBoundsChange = () => {
|
||||
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.setVibrancy(false, undefined, false)
|
||||
if (moveEndedTimeout) {
|
||||
clearTimeout(moveEndedTimeout)
|
||||
}
|
||||
this.window.on('move', onMove)
|
||||
})
|
||||
moveEndedTimeout = setTimeout(() => {
|
||||
this.setVibrancy(this.lastVibrancy.enabled, this.lastVibrancy.type)
|
||||
}, 50)
|
||||
}
|
||||
this.window.on('move', onBoundsChange)
|
||||
this.window.on('resize', onBoundsChange)
|
||||
}
|
||||
|
||||
private destroy () {
|
||||
|
@@ -13,43 +13,51 @@
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "9.1.0",
|
||||
"@angular/common": "9.1.2",
|
||||
"@angular/compiler": "9.1.2",
|
||||
"@angular/core": "9.1.2",
|
||||
"@angular/forms": "9.1.1",
|
||||
"@angular/platform-browser": "9.1.1",
|
||||
"@angular/platform-browser-dynamic": "9.1.2",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.0.2",
|
||||
"devtron": "1.4.0",
|
||||
"@angular/animations": "^9.1.9",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/compiler": "^9.1.9",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.9",
|
||||
"@angular/platform-browser-dynamic": "^9.1.9",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||
"@terminus-term/node-pty": "0.10.0-beta11",
|
||||
"electron-config": "2.0.0",
|
||||
"electron-debug": "^3.0.1",
|
||||
"electron-is-dev": "1.1.0",
|
||||
"electron-updater": "^4.3.0",
|
||||
"fontmanager-redux": "0.4.0",
|
||||
"js-yaml": "3.13.1",
|
||||
"keytar": "^5.5.0",
|
||||
"electron-promise-ipc": "^2.2.4",
|
||||
"fontmanager-redux": "1.0.0",
|
||||
"glasstron": "0.0.5",
|
||||
"js-yaml": "3.14.0",
|
||||
"keytar": "^7.2.0",
|
||||
"mz": "^2.7.0",
|
||||
"ngx-toastr": "^12.0.1",
|
||||
"node-pty": "^0.10.0-beta8",
|
||||
"npm": "6.9.0",
|
||||
"npm": "6",
|
||||
"path": "0.12.7",
|
||||
"rxjs": "^6.5.5",
|
||||
"rxjs-compat": "^6.5.5",
|
||||
"yargs": "^15.3.1",
|
||||
"zone.js": "^0.10.3"
|
||||
"yargs": "^15.4.1",
|
||||
"zone.js": "^0.11.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"macos-native-processlist": "^1.0.2",
|
||||
"serialport": "^8.0.7",
|
||||
"macos-native-processlist": "^2.0.0",
|
||||
"serialport": "^9.0.4",
|
||||
"windows-blurbehind": "^1.0.1",
|
||||
"windows-native-registry": "^1.0.17",
|
||||
"windows-process-tree": "^0.2.4",
|
||||
"windows-swca": "^2.0.2"
|
||||
"windows-native-registry": "^3.0.0",
|
||||
"windows-process-tree": "^0.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mz": "0.0.32",
|
||||
"@types/node": "12.7.12",
|
||||
"node-abi": "^2.15.0"
|
||||
"@types/node": "14.14.14",
|
||||
"node-abi": "2.19.3",
|
||||
"source-map-support": "^0.5.19"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"terminus-community-color-schemes": "*",
|
||||
"terminus-core": "*",
|
||||
"terminus-plugin-manager": "*",
|
||||
"terminus-serial": "*",
|
||||
"terminus-settings": "*",
|
||||
"terminus-ssh": "*",
|
||||
"terminus-terminal": "*"
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ import 'source-sans-pro/source-sans-pro.css'
|
||||
import 'source-code-pro/source-code-pro.css'
|
||||
import '@fortawesome/fontawesome-free/css/solid.css'
|
||||
import '@fortawesome/fontawesome-free/css/brands.css'
|
||||
import '@fortawesome/fontawesome-free/css/regular.css'
|
||||
import '@fortawesome/fontawesome-free/css/fontawesome.css'
|
||||
import 'ngx-toastr/toastr.css'
|
||||
import './preload.scss'
|
||||
|
@@ -58,8 +58,8 @@ findPlugins().then(async plugins => {
|
||||
window['safeModeReason'] = error
|
||||
try {
|
||||
await bootstrap(plugins, true)
|
||||
} catch (error) {
|
||||
console.error('Bootstrap failed:', error)
|
||||
} catch (error2) {
|
||||
console.error('Bootstrap failed:', error2)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -3,13 +3,13 @@ import * as path from 'path'
|
||||
const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires
|
||||
const nodeRequire = (global as any).require
|
||||
|
||||
function normalizePath (path: string): string {
|
||||
function normalizePath (p: string): string {
|
||||
const cygwinPrefix = '/cygdrive/'
|
||||
if (path.startsWith(cygwinPrefix)) {
|
||||
path = path.substring(cygwinPrefix.length).replace('/', '\\')
|
||||
path = path[0] + ':' + path.substring(1)
|
||||
if (p.startsWith(cygwinPrefix)) {
|
||||
p = p.substring(cygwinPrefix.length).replace('/', '\\')
|
||||
p = p[0] + ':' + p.substring(1)
|
||||
}
|
||||
return path
|
||||
return p
|
||||
}
|
||||
|
||||
global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
@@ -63,7 +63,6 @@ const builtinModules = [
|
||||
'ngx-toastr',
|
||||
'rxjs',
|
||||
'rxjs/operators',
|
||||
'rxjs-compat/Subject',
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
@@ -83,7 +82,7 @@ const originalRequire = (global as any).require
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalRequire.apply(this, arguments)
|
||||
return originalRequire.apply(this, [query])
|
||||
}
|
||||
|
||||
const originalModuleRequire = nodeModule.prototype.require
|
||||
@@ -173,8 +172,8 @@ export async function loadPlugins (foundPlugins: PluginInfo[], progress: Progres
|
||||
console.time(label)
|
||||
const packageModule = nodeRequire(foundPlugin.path)
|
||||
const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
||||
pluginModule['pluginName'] = foundPlugin.name
|
||||
pluginModule['bootstrap'] = packageModule.bootstrap
|
||||
pluginModule.pluginName = foundPlugin.name
|
||||
pluginModule.bootstrap = packageModule.bootstrap
|
||||
plugins.push(pluginModule)
|
||||
console.timeEnd(label)
|
||||
await new Promise(x => setTimeout(x, 50))
|
||||
|
@@ -9,6 +9,7 @@
|
||||
padding: 10px;
|
||||
background-image: none;
|
||||
width: auto;
|
||||
flex-basis: auto;
|
||||
|
||||
&.toast-error {
|
||||
background-color: #BD362F;
|
||||
|
@@ -12,7 +12,6 @@
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
|
@@ -35,11 +35,15 @@ module.exports = {
|
||||
externals: {
|
||||
electron: 'commonjs electron',
|
||||
'electron-config': 'commonjs electron-config',
|
||||
'electron-promise-ipc': 'commonjs electron-promise-ipc',
|
||||
'electron-vibrancy': 'commonjs electron-vibrancy',
|
||||
fs: 'commonjs fs',
|
||||
glasstron: 'commonjs glasstron',
|
||||
mz: 'commonjs mz',
|
||||
npm: 'commonjs npm',
|
||||
path: 'commonjs path',
|
||||
yargs: 'commonjs yargs',
|
||||
util: 'commonjs util',
|
||||
'source-map-support': 'commonjs source-map-support',
|
||||
'windows-swca': 'commonjs windows-swca',
|
||||
'windows-blurbehind': 'commonjs windows-blurbehind',
|
||||
},
|
||||
@@ -49,4 +53,6 @@ module.exports = {
|
||||
'process.type': '"main"',
|
||||
}),
|
||||
],
|
||||
// Ignore warnings due to yarg's dynamic module loading
|
||||
ignoreWarnings: [/node_modules\/yargs/],
|
||||
}
|
||||
|
2472
app/yarn.lock
2472
app/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ platform:
|
||||
- x64
|
||||
|
||||
environment:
|
||||
nodejs_version: "10"
|
||||
nodejs_version: "15"
|
||||
|
||||
version: "{build}"
|
||||
|
||||
|
16
build/mac/afterBuildHook.js
Normal file
16
build/mac/afterBuildHook.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const fs = require('fs')
|
||||
const signHook = require('./afterSignHook')
|
||||
|
||||
module.exports = async function (params) {
|
||||
// notarize the app on Mac OS only.
|
||||
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
return
|
||||
}
|
||||
console.log('afterBuild hook triggered')
|
||||
|
||||
let pkgName = fs.readdirSync('dist').find(x => x.endsWith('.pkg'))
|
||||
signHook({
|
||||
appOutDir: 'dist',
|
||||
_pathOverride: pkgName,
|
||||
})
|
||||
}
|
@@ -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 !== 'refs/heads/master' || process.env.GITHUB_REF && !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
if (process.platform !== 'darwin' || !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.packager.appInfo.productFilename}.app`)
|
||||
let appPath = path.join(params.appOutDir, params._pathOverride || `${params.packager.appInfo.productFilename}.app`)
|
||||
if (!fs.existsSync(appPath)) {
|
||||
throw new Error(`Cannot find application at: ${appPath}`)
|
||||
}
|
||||
|
@@ -10,5 +10,9 @@
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.microphone</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@@ -2,10 +2,31 @@
|
||||
appId: org.terminus
|
||||
productName: Terminus
|
||||
compression: normal
|
||||
npmRebuild: false
|
||||
afterSign: "./build/mac/afterSignHook.js"
|
||||
afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
|
||||
files:
|
||||
- "**/*"
|
||||
- '**/*'
|
||||
- dist
|
||||
- '!src'
|
||||
- '!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}'
|
||||
- '!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples,docs}'
|
||||
- '!**/node_modules/@angular/common/locales'
|
||||
- '!**/node_modules/@angular/compiler/src'
|
||||
- '!**/node_modules/node-gyp'
|
||||
- '!**/node_modules/**/*.d.ts'
|
||||
- '!**/node_modules/**/*.map'
|
||||
- '!**/node_modules/**/include/node'
|
||||
- '!**/node_modules/.bin'
|
||||
- '!**/node_modules/*/*/{esm5,fesm5,esm2015,fesm2015,_esm2015,_fesm2015}'
|
||||
- '!**/*.{woff,ttf,otf,eot}'
|
||||
- '!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}'
|
||||
- '!.editorconfig'
|
||||
- '!**/._*'
|
||||
- '!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}'
|
||||
- '!**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}'
|
||||
- '!**/{appveyor.yml,.travis.yml,circle.yml}'
|
||||
- '!**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json'
|
||||
extraResources:
|
||||
- builtin-plugins
|
||||
- extras
|
||||
@@ -20,18 +41,25 @@ nsis:
|
||||
oneClick: false
|
||||
artifactName: terminus-${version}-setup.${ext}
|
||||
installerIcon: "./build/windows/icon.ico"
|
||||
allowToChangeInstallationDirectory: true
|
||||
|
||||
mac:
|
||||
category: public.app-category.video
|
||||
icon: "./build/mac/icon.icns"
|
||||
artifactName: terminus-${version}-macos.${ext}
|
||||
artifactName: terminus-${version}-macos-${env.ARCH}.${ext}
|
||||
hardenedRuntime: true
|
||||
entitlements: "./build/mac/entitlements.plist"
|
||||
entitlementsInherit: "./build/mac/entitlements.plist"
|
||||
extendInfo:
|
||||
NSRequiresAquaSystemAppearance: false
|
||||
pkg:
|
||||
artifactName: terminus-${version}-macos.pkg
|
||||
NSCameraUsageDescription: "A subprocess requests access to the device's camera."
|
||||
NSMicrophoneUsageDescription: "A subprocess requests access to the device's microphone."
|
||||
NSLocationUsageDescription: "A subprocess requests access to the user's location information."
|
||||
NSDesktopFolderUsageDescription: "A subprocess requests access to the user's Desktop folder."
|
||||
NSDocumentsFolderUsageDescription: "A subprocess requests access to the user's Documents folder."
|
||||
NSDownloadsFolderUsageDescription: "A subprocess requests access to the user's Downloads folder."
|
||||
NSNetworkVolumesUsageDescription: 'A subprocess requests access to files on a network volume.'
|
||||
NSRemovableVolumesUsageDescription: 'A subprocess requests access to files on a removable volume.'
|
||||
|
||||
linux:
|
||||
category: Utilities
|
||||
@@ -48,6 +76,7 @@ deb:
|
||||
depends:
|
||||
- gconf2
|
||||
- gconf-service
|
||||
- gnome-keyring
|
||||
- libnotify4
|
||||
- libsecret-1-0
|
||||
- libappindicator1
|
||||
@@ -57,4 +86,4 @@ deb:
|
||||
rpm:
|
||||
depends:
|
||||
- screen
|
||||
- gnome-python2-gnomekeyring
|
||||
- gnome-keyring
|
||||
|
BIN
extras/UAC.exe
BIN
extras/UAC.exe
Binary file not shown.
71
package.json
71
package.json
@@ -1,67 +1,74 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||
"@sentry/cli": "^1.52.1",
|
||||
"@sentry/electron": "^1.2.1",
|
||||
"@sentry/cli": "^1.61.0",
|
||||
"@sentry/electron": "^2.0.4",
|
||||
"@types/electron-config": "^3.2.2",
|
||||
"@types/electron-debug": "^2.1.0",
|
||||
"@types/js-yaml": "^3.12.3",
|
||||
"@types/node": "12.7.12",
|
||||
"@types/webpack-env": "1.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.26.0",
|
||||
"@typescript-eslint/parser": "^2.27.0",
|
||||
"@types/fs-extra": "^8.1.1",
|
||||
"@types/js-yaml": "^3.12.5",
|
||||
"@types/node": "14.14.14",
|
||||
"@types/webpack-env": "^1.16.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.11.0",
|
||||
"@typescript-eslint/parser": "^4.11.0",
|
||||
"apply-loader": "2.0.0",
|
||||
"awesome-typescript-loader": "^5.0.0",
|
||||
"core-js": "^3.6.5",
|
||||
"awesome-typescript-loader": "^5.2.1",
|
||||
"compare-versions": "^3.6.0",
|
||||
"core-js": "^3.8.1",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.4.2",
|
||||
"electron": "^8.2.3",
|
||||
"electron-builder": "22.5.1",
|
||||
"electron": "^11.1.1",
|
||||
"electron-builder": "22.10.4",
|
||||
"electron-download": "^4.1.1",
|
||||
"electron-installer-snap": "^5.0.0",
|
||||
"electron-notarize": "^0.1.1",
|
||||
"electron-rebuild": "^1.10.1",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"file-loader": "^5.0.2",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"electron-installer-snap": "^5.1.0",
|
||||
"electron-notarize": "^1.0.0",
|
||||
"electron-rebuild": "^2.3.4",
|
||||
"eslint": "^7.6.0",
|
||||
"eslint-plugin-import": "^2.21.1",
|
||||
"file-loader": "^5.1.0",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"html-loader": "0.5.5",
|
||||
"json-loader": "0.5.7",
|
||||
"node-abi": "^2.15.0",
|
||||
"node-gyp": "^6.1.0",
|
||||
"node-sass": "^4.13.0",
|
||||
"lru-cache": "^6.0.0",
|
||||
"macos-release": "^2.4.1",
|
||||
"node-abi": "^2.19.3",
|
||||
"node-gyp": "^7.1.2",
|
||||
"node-sass": "^5.0.0",
|
||||
"npmlog": "4.1.2",
|
||||
"npx": "^10.2.0",
|
||||
"npx": "^10.2.2",
|
||||
"pug": "^2.0.4",
|
||||
"pug-html-loader": "1.1.5",
|
||||
"pug-lint": "^2.6.0",
|
||||
"pug-loader": "^2.4.0",
|
||||
"pug-static-loader": "2.0.0",
|
||||
"raw-loader": "4.0.1",
|
||||
"sass-loader": "^8.0.0",
|
||||
"shelljs": "0.8.3",
|
||||
"sass-loader": "^10.1.0",
|
||||
"shelljs": "0.8.4",
|
||||
"source-code-pro": "^2.30.2",
|
||||
"source-sans-pro": "3.6.0",
|
||||
"style-loader": "^1.1.4",
|
||||
"svg-inline-loader": "^0.8.0",
|
||||
"ssh2-streams": "^0.4.10",
|
||||
"style-loader": "^2.0.0",
|
||||
"svg-inline-loader": "^0.8.2",
|
||||
"to-string-loader": "1.1.6",
|
||||
"tslib": "^1.11.1",
|
||||
"typedoc": "^0.17.4",
|
||||
"typescript": "^3.8.3",
|
||||
"tslib": "^2.0.3",
|
||||
"typedoc": "^0.18.0",
|
||||
"typescript": "^3.9.7",
|
||||
"url-loader": "^3.0.0",
|
||||
"val-loader": "2.1.1",
|
||||
"webpack": "^5.0.0-beta.14",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack": "^5.11.0",
|
||||
"webpack-cli": "^4.2.0",
|
||||
"yaml-loader": "0.6.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"*/node-abi": "^2.14.0"
|
||||
"*/node-abi": "^2.19.3",
|
||||
"**/graceful-fs": "^4.2.4"
|
||||
},
|
||||
"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",
|
||||
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
|
||||
"start": "cross-env TERMINUS_DEV=1 electron app --debug",
|
||||
"start:prod": "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",
|
||||
|
@@ -1,17 +1,24 @@
|
||||
#!/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
|
||||
|
||||
process.env.ARCH = process.env.ARCH || process.arch
|
||||
|
||||
builder({
|
||||
dir: true,
|
||||
mac: ['pkg', 'zip'],
|
||||
arm64: process.env.ARCH === 'arm64',
|
||||
config: {
|
||||
extraMetadata: {
|
||||
version: vars.version,
|
||||
},
|
||||
},
|
||||
publish: isTag ? 'always' : 'onTag',
|
||||
}).catch(() => process.exit(1))
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
|
@@ -8,6 +8,7 @@ for (let dir of ['app', 'terminus-core', 'terminus-ssh', 'terminus-terminal']) {
|
||||
const build = rebuild({
|
||||
buildPath: path.resolve(__dirname, '../' + dir),
|
||||
electronVersion: vars.electronVersion,
|
||||
arch: process.env.ARCH ?? process.arch,
|
||||
force: true,
|
||||
})
|
||||
build.catch(e => {
|
||||
|
@@ -10,13 +10,13 @@ const npx = `${localBinPath}/npx`;
|
||||
log.info('deps', 'app')
|
||||
|
||||
sh.cd('app')
|
||||
sh.exec(`${npx} yarn install`)
|
||||
sh.exec(`${npx} yarn install --force`)
|
||||
sh.cd('..')
|
||||
|
||||
vars.builtinPlugins.forEach(plugin => {
|
||||
log.info('deps', plugin)
|
||||
sh.cd(plugin)
|
||||
sh.exec(`${npx} yarn install`)
|
||||
sh.exec(`${npx} yarn install --force`)
|
||||
sh.cd('..')
|
||||
})
|
||||
|
||||
|
@@ -15,10 +15,17 @@ vars.builtinPlugins.forEach(plugin => {
|
||||
sh.cp('-r', path.join('..', plugin), '.')
|
||||
sh.rm('-rf', path.join(plugin, 'node_modules'))
|
||||
sh.cd(plugin)
|
||||
sh.exec(`npm install --only=prod`)
|
||||
sh.exec(`yarn install --force --production`)
|
||||
|
||||
|
||||
log.info('rebuild', 'native')
|
||||
if (fs.existsSync('node_modules')) {
|
||||
rebuild(path.resolve('.'), vars.electronVersion, process.arch, [], true)
|
||||
rebuild({
|
||||
buildPath: path.resolve('.'),
|
||||
electronVersion: vars.electronVersion,
|
||||
arch: process.env.ARCH ?? process.arch,
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
sh.cd('..')
|
||||
})
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-community-color-schemes",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.123-nightly.0",
|
||||
"description": "Community color schemes for Terminus",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -17,7 +17,7 @@
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@angular/core": "^7",
|
||||
"@angular/core": "^9.1.9",
|
||||
"terminus-core": "*",
|
||||
"terminus-terminal": "*"
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ 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',
|
||||
|
1
terminus-core/.gitignore
vendored
1
terminus-core/.gitignore
vendored
@@ -1,2 +1 @@
|
||||
dist
|
||||
node_modules
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-core",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.123-nightly.0",
|
||||
"description": "Terminus core",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -29,17 +29,18 @@
|
||||
"mixpanel": "^0.10.2",
|
||||
"ng2-dnd": "^5.0.2",
|
||||
"ngx-perfect-scrollbar": "^8.0.0",
|
||||
"readable-stream": "2.3.7",
|
||||
"shell-escape": "^0.2.0",
|
||||
"uuid": "^7.0.1",
|
||||
"winston": "^3.2.1"
|
||||
"uuid": "^8.0.0",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": "^7",
|
||||
"@angular/common": "^7",
|
||||
"@angular/core": "^7",
|
||||
"@angular/forms": "^7",
|
||||
"@angular/platform-browser": "^7",
|
||||
"@angular/platform-browser-dynamic": "^7",
|
||||
"rxjs": "^5"
|
||||
"@angular/animations": "^9.1.9",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.11",
|
||||
"@angular/platform-browser-dynamic": "^9.1.11",
|
||||
"rxjs": "^6.6.3"
|
||||
}
|
||||
}
|
||||
|
@@ -33,5 +33,5 @@ export abstract class ConfigProvider {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
platformDefaults: {[platform: string]: any} = {}
|
||||
platformDefaults: Record<string, any> = {}
|
||||
}
|
||||
|
@@ -8,7 +8,5 @@ export interface HotkeyDescription {
|
||||
* must also provide the `hotkeys.foo` config options with the default values
|
||||
*/
|
||||
export abstract class HotkeyProvider {
|
||||
hotkeys: HotkeyDescription[] = []
|
||||
|
||||
abstract provide (): Promise<HotkeyDescription[]>
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import type { MenuItemConstructorOptions } from 'electron'
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { TabHeaderComponent } from '../components/tabHeader.component'
|
||||
|
||||
@@ -7,5 +8,5 @@ import { TabHeaderComponent } from '../components/tabHeader.component'
|
||||
export abstract class TabContextMenuItemProvider {
|
||||
weight = 0
|
||||
|
||||
abstract async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]>
|
||||
abstract async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]>
|
||||
}
|
||||
|
@@ -4,10 +4,13 @@ title-bar(
|
||||
)
|
||||
|
||||
.content(
|
||||
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top"'
|
||||
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"',
|
||||
[class.tabs-on-side]='hasVerticalTabs()',
|
||||
)
|
||||
.tab-bar
|
||||
.inset.background(*ngIf='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"')
|
||||
.inset.background(*ngIf='hostApp.platform == Platform.macOS \
|
||||
&& config.store.appearance.frame == "thin" \
|
||||
&& (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")')
|
||||
.tabs(
|
||||
dnd-sortable-container,
|
||||
[sortableData]='app.tabs',
|
||||
@@ -18,12 +21,12 @@ title-bar(
|
||||
[sortableIndex]='idx',
|
||||
(onDragStart)='onTabDragStart()',
|
||||
(onDragEnd)='onTabDragEnd()',
|
||||
|
||||
[index]='idx',
|
||||
[tab]='tab',
|
||||
[active]='tab == app.activeTab',
|
||||
[hasActivity]='tab.activity$|async',
|
||||
@animateTab,
|
||||
[@.disabled]='hasVerticalTabs()',
|
||||
(click)='app.selectTab(tab)',
|
||||
[class.fully-draggable]='hostApp.platform != Platform.macOS',
|
||||
[class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging',
|
||||
@@ -87,7 +90,8 @@ title-bar(
|
||||
)
|
||||
|
||||
window-controls.background(
|
||||
*ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
|
||||
*ngIf='config.store.appearance.frame == "thin" \
|
||||
&& (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
|
||||
)
|
||||
|
||||
start-page(*ngIf='ready && app.tabs.length == 0')
|
||||
|
@@ -15,10 +15,18 @@
|
||||
|
||||
$tabs-height: 38px;
|
||||
$tab-border-radius: 4px;
|
||||
$side-tab-width: 200px;
|
||||
|
||||
.wrap {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
flex: auto;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
@@ -26,15 +34,54 @@ $tab-border-radius: 4px;
|
||||
&.tabs-on-top {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.tabs-on-side {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
&.tabs-on-top {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.content.tabs-on-side > .tab-bar {
|
||||
height: 100%;
|
||||
width: $side-tab-width;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
flex-direction: column;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
|
||||
.tabs {
|
||||
width: $side-tab-width;
|
||||
flex: none;
|
||||
flex-direction: column;
|
||||
|
||||
tab-header {
|
||||
flex: 0 0 $tabs-height;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-space {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
&>.inset {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tab-bar {
|
||||
flex: none;
|
||||
height: $tabs-height;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.btn-tab-bar {
|
||||
line-height: $tabs-height + 2px;
|
||||
height: $tabs-height;
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
@@ -50,6 +97,8 @@ $tab-border-radius: 4px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
||||
align-items: center;
|
||||
|
||||
&.dropdown-toggle::after {
|
||||
display: none;
|
||||
}
|
||||
@@ -74,7 +123,9 @@ $tab-border-radius: 4px;
|
||||
|
||||
& > .inset {
|
||||
width: 85px;
|
||||
height: $tabs-height;
|
||||
flex: none;
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
window-controls {
|
||||
|
@@ -184,6 +184,10 @@ export class AppRootComponent {
|
||||
return false
|
||||
}
|
||||
|
||||
hasVerticalTabs () {
|
||||
return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right'
|
||||
}
|
||||
|
||||
async updateApp () {
|
||||
if ((await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
@@ -225,8 +229,8 @@ export class AppRootComponent {
|
||||
buttons = buttons.concat(provider.provide())
|
||||
})
|
||||
return buttons
|
||||
.filter(button => (button.weight || 0) > 0 === aboveZero)
|
||||
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
||||
.filter(button => (button.weight ?? 0) > 0 === aboveZero)
|
||||
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight ?? 0) - (b.weight ?? 0))
|
||||
}
|
||||
|
||||
private updateVibrancy () {
|
||||
|
@@ -14,6 +14,11 @@ 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
|
||||
*/
|
||||
|
@@ -50,7 +50,7 @@ export class SelectorModalComponent<T> {
|
||||
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.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)
|
||||
@@ -72,7 +72,7 @@ export class SelectorModalComponent<T> {
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
|
||||
iconIsSVG (icon: string): boolean {
|
||||
return icon?.startsWith('<')
|
||||
iconIsSVG (icon?: string): boolean {
|
||||
return icon?.startsWith('<') ?? false
|
||||
}
|
||||
}
|
||||
|
@@ -157,7 +157,11 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
/** @hidden */
|
||||
_spanners: SplitSpannerInfo[] = []
|
||||
|
||||
private focusedTab: BaseTabComponent
|
||||
/** @hidden */
|
||||
_allFocusMode = false
|
||||
|
||||
/** @hidden */
|
||||
private focusedTab: BaseTabComponent|null = null
|
||||
private maximizedTab: BaseTabComponent|null = null
|
||||
private hotkeysSubscription: Subscription
|
||||
private viewRefs: Map<BaseTabComponent, EmbeddedViewRef<any>> = new Map()
|
||||
@@ -207,7 +211,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
this.blurred$.subscribe(() => this.getAllTabs().forEach(x => x.emitBlurred()))
|
||||
|
||||
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
||||
if (!this.hasFocus) {
|
||||
if (!this.hasFocus || !this.focusedTab) {
|
||||
return
|
||||
}
|
||||
switch (hotkey) {
|
||||
@@ -254,12 +258,13 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
if (this._recoveredState) {
|
||||
await this.recoverContainer(this.root, this._recoveredState)
|
||||
this.layout()
|
||||
setImmediate(() => {
|
||||
setTimeout(() => {
|
||||
if (this.hasFocus) {
|
||||
this.getAllTabs().forEach(x => x.emitFocused())
|
||||
this.focusAnyIn(this.root)
|
||||
for (const tab of this.getAllTabs()) {
|
||||
this.focus(tab)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, 100)
|
||||
}
|
||||
this.initialized.next()
|
||||
this.initialized.complete()
|
||||
@@ -275,7 +280,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
return this.root.getAllTabs()
|
||||
}
|
||||
|
||||
getFocusedTab (): BaseTabComponent {
|
||||
getFocusedTab (): BaseTabComponent|null {
|
||||
return this.focusedTab
|
||||
}
|
||||
|
||||
@@ -290,10 +295,8 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
x.emitBlurred()
|
||||
}
|
||||
}
|
||||
if (tab) {
|
||||
tab.emitFocused()
|
||||
this.focusChanged.next(tab)
|
||||
}
|
||||
tab.emitFocused()
|
||||
this.focusChanged.next(tab)
|
||||
|
||||
if (this.maximizedTab !== tab) {
|
||||
this.maximizedTab = null
|
||||
@@ -309,7 +312,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
/**
|
||||
* Focuses the first available tab inside the given [[SplitContainer]]
|
||||
*/
|
||||
focusAnyIn (parent: BaseTabComponent | SplitContainer): void {
|
||||
focusAnyIn (parent?: BaseTabComponent | SplitContainer): void {
|
||||
if (!parent) {
|
||||
return
|
||||
}
|
||||
@@ -324,9 +327,9 @@ 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> {
|
||||
await this.initialized$.toPromise()
|
||||
tab.parent = this
|
||||
|
||||
let target = (relative ? this.getParentOf(relative) : null) || this.root
|
||||
let target = (relative ? this.getParentOf(relative) : null) ?? this.root
|
||||
let insertIndex = relative ? target.children.indexOf(relative) : -1
|
||||
|
||||
if (
|
||||
@@ -355,6 +358,9 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
target.children.splice(insertIndex, 0, tab)
|
||||
|
||||
this.recoveryStateChangedHint.next()
|
||||
|
||||
await this.initialized$.toPromise()
|
||||
|
||||
this.attachTabView(tab)
|
||||
|
||||
setImmediate(() => {
|
||||
@@ -374,11 +380,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 {
|
||||
@@ -390,6 +396,10 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
* Moves focus in the given direction
|
||||
*/
|
||||
navigate (dir: SplitDirection): void {
|
||||
if (!this.focusedTab) {
|
||||
return
|
||||
}
|
||||
|
||||
let rel: BaseTabComponent | SplitContainer = this.focusedTab
|
||||
let parent = this.getParentOf(rel)
|
||||
if (!parent) {
|
||||
@@ -434,7 +444,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
* @returns the immediate parent of `tab`
|
||||
*/
|
||||
getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer|null {
|
||||
root = root || this.root
|
||||
root = root ?? this.root
|
||||
for (const child of root.children) {
|
||||
if (child instanceof SplitContainer) {
|
||||
const r = this.getParentOf(tab, child)
|
||||
@@ -461,7 +471,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
|
||||
/** @hidden */
|
||||
async getCurrentProcess (): Promise<BaseTabProcess|null> {
|
||||
return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x) || null
|
||||
return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x) ?? null
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@@ -477,6 +487,12 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
}
|
||||
|
||||
layout (): void {
|
||||
this.root.normalize()
|
||||
this._spanners = []
|
||||
this.layoutInternal(this.root, 0, 0, 100, 100)
|
||||
}
|
||||
|
||||
private attachTabView (tab: BaseTabComponent) {
|
||||
const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any> // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
this.viewRefs.set(tab, ref)
|
||||
@@ -502,15 +518,9 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
}
|
||||
}
|
||||
|
||||
private layout () {
|
||||
this.root.normalize()
|
||||
this._spanners = []
|
||||
this.layoutInternal(this.root, 0, 0, 100, 100)
|
||||
}
|
||||
|
||||
private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
|
||||
const size = root.orientation === 'v' ? h : w
|
||||
const sizes = root.ratios.map(x => x * size)
|
||||
const sizes = root.ratios.map(ratio => ratio * size)
|
||||
|
||||
root.x = x
|
||||
root.y = y
|
||||
@@ -526,21 +536,24 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
if (child instanceof SplitContainer) {
|
||||
this.layoutInternal(child, childX, childY, childW, childH)
|
||||
} else {
|
||||
const element = this.viewRefs.get(child)!.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 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', this._allFocusMode || child === this.focusedTab)
|
||||
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%'
|
||||
if (child === this.maximizedTab) {
|
||||
element.style.left = '5%'
|
||||
element.style.top = '5%'
|
||||
element.style.width = '90%'
|
||||
element.style.height = '90%'
|
||||
}
|
||||
}
|
||||
}
|
||||
offset += sizes[i]
|
||||
@@ -569,6 +582,7 @@ 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)
|
||||
@@ -586,7 +600,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
||||
@Injectable()
|
||||
export class SplitTabRecoveryProvider extends TabRecoveryProvider {
|
||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||
if (recoveryToken && recoveryToken.type === 'app:split-tab') {
|
||||
if (recoveryToken.type === 'app:split-tab') {
|
||||
return {
|
||||
type: SplitTabComponent,
|
||||
options: { _recoveredState: recoveryToken },
|
||||
|
@@ -34,8 +34,8 @@ export class SplitTabSpannerComponent {
|
||||
let current = start
|
||||
const oldPosition: number = this.isVertical ? this.element.nativeElement.offsetTop : this.element.nativeElement.offsetLeft
|
||||
|
||||
const dragHandler = (e: MouseEvent) => {
|
||||
current = this.isVertical ? e.pageY : e.pageX
|
||||
const dragHandler = (dragEvent: MouseEvent) => {
|
||||
current = this.isVertical ? dragEvent.pageY : dragEvent.pageX
|
||||
const newPosition = oldPosition + (current - start)
|
||||
if (this.isVertical) {
|
||||
this.element.nativeElement.style.top = `${newPosition - this.marginOffset}px`
|
||||
|
@@ -26,10 +26,10 @@ export class StartPageComponent {
|
||||
.map(provider => provider.provide())
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.filter(x => !!x.click)
|
||||
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
||||
.sort((a: ToolbarButton, b: ToolbarButton) => (a.weight ?? 0) - (b.weight ?? 0))
|
||||
}
|
||||
|
||||
sanitizeIcon (icon: string): any {
|
||||
return this.domSanitizer.bypassSecurityTrustHtml(icon || '')
|
||||
sanitizeIcon (icon?: string): any {
|
||||
return this.domSanitizer.bypassSecurityTrustHtml(icon ?? '')
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
.progressbar([style.width]='progress + "%"', *ngIf='progress != null')
|
||||
.index(
|
||||
.index(*ngIf='!config.store.terminal.hideTabIndex',
|
||||
#handle,
|
||||
[style.background-color]='tab.color',
|
||||
) {{index + 1}}
|
||||
.name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}}
|
||||
button((click)='app.closeTab(tab, true)') ×
|
||||
button(*ngIf='!config.store.terminal.hideCloseButton',(click)='app.closeTab(tab, true)') ×
|
||||
|
@@ -13,6 +13,11 @@ $tabs-height: 38px;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
&.vertical {
|
||||
flex: none;
|
||||
height: $tabs-height;
|
||||
}
|
||||
|
||||
.index {
|
||||
flex: none;
|
||||
font-weight: bold;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import type { MenuItemConstructorOptions } from 'electron'
|
||||
import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core'
|
||||
import { SortableComponent } from 'ng2-dnd'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
@@ -9,10 +10,11 @@ import { HotkeysService } from '../services/hotkeys.service'
|
||||
import { ElectronService } from '../services/electron.service'
|
||||
import { AppService } from '../services/app.service'
|
||||
import { HostAppService, Platform } from '../services/hostApp.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
|
||||
/** @hidden */
|
||||
export interface SortableComponentProxy {
|
||||
setDragHandle (_: HTMLElement)
|
||||
setDragHandle: (_: HTMLElement) => void
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@@ -31,6 +33,7 @@ export class TabHeaderComponent {
|
||||
|
||||
private constructor (
|
||||
public app: AppService,
|
||||
public config: ConfigService,
|
||||
private electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
private ngbModal: NgbModal,
|
||||
@@ -69,8 +72,8 @@ export class TabHeaderComponent {
|
||||
}).catch(() => null)
|
||||
}
|
||||
|
||||
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
let items: Electron.MenuItemConstructorOptions[] = []
|
||||
async buildContextMenu (): Promise<MenuItemConstructorOptions[]> {
|
||||
let items: MenuItemConstructorOptions[] = []
|
||||
for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this.tab, this)))) {
|
||||
items.push({ type: 'separator' })
|
||||
items = items.concat(section)
|
||||
|
@@ -9,18 +9,25 @@
|
||||
.form-line
|
||||
.header
|
||||
.title Enable analytics
|
||||
.description Help us track the number of Terminus installs across the world!
|
||||
.description Help track the number of Terminus installs across the world!
|
||||
toggle([(ngModel)]='config.store.enableAnalytics')
|
||||
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Enable SSH plugin
|
||||
.title Enable global hotkey (#[strong Ctrl-Space])
|
||||
.description Toggles the Terminus window visibility
|
||||
toggle([(ngModel)]='enableGlobalHotkey')
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Enable #[strong SSH] plugin
|
||||
.description Adds an SSH connection manager UI to Terminus
|
||||
toggle([(ngModel)]='enableSSH')
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Enable Serial plugin
|
||||
.title Enable #[strong Serial] plugin
|
||||
.description Allows attaching Terminus to serial ports
|
||||
toggle([(ngModel)]='enableSerial')
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import { HostAppService } from '../services/hostApp.service'
|
||||
export class WelcomeTabComponent extends BaseTabComponent {
|
||||
enableSSH = false
|
||||
enableSerial = false
|
||||
enableGlobalHotkey = true
|
||||
|
||||
constructor (
|
||||
private hostApp: HostAppService,
|
||||
@@ -33,6 +34,9 @@ export class WelcomeTabComponent extends BaseTabComponent {
|
||||
if (!this.enableSerial) {
|
||||
this.config.store.pluginBlacklist.push('serial')
|
||||
}
|
||||
if (!this.enableGlobalHotkey) {
|
||||
this.config.store.hotkeys['toggle-window'] = []
|
||||
}
|
||||
this.config.save()
|
||||
this.hostApp.getWindow().reload()
|
||||
}
|
||||
|
@@ -12,7 +12,8 @@ button {
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
|
||||
align-items: center;
|
||||
|
||||
&:not(:hover):not(:active) {
|
||||
background: transparent;
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@ appearance:
|
||||
dock: off
|
||||
dockScreen: current
|
||||
dockFill: 0.5
|
||||
dockHideOnBlur: false
|
||||
dockAlwaysOnTop: true
|
||||
tabsLocation: top
|
||||
cycleTabs: true
|
||||
theme: Standard
|
||||
|
@@ -36,7 +36,7 @@ import { ConfigService } from './services/config.service'
|
||||
import { StandardTheme, StandardCompactTheme, PaperTheme } from './theme'
|
||||
import { CoreConfigProvider } from './config'
|
||||
import { AppHotkeyProvider } from './hotkeys'
|
||||
import { TaskCompletionContextMenu, CommonOptionsContextMenu, CloseContextMenu } from './tabContextMenu'
|
||||
import { TaskCompletionContextMenu, CommonOptionsContextMenu, TabManagementContextMenu } from './tabContextMenu'
|
||||
|
||||
import 'perfect-scrollbar/css/perfect-scrollbar.css'
|
||||
import 'ng2-dnd/bundles/style.css'
|
||||
@@ -54,7 +54,7 @@ const PROVIDERS = [
|
||||
{ provide: Theme, useClass: PaperTheme, multi: true },
|
||||
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: CommonOptionsContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: CloseContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: TabManagementContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: TaskCompletionContextMenu, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: SplitTabRecoveryProvider, multi: true },
|
||||
{ provide: PERFECT_SCROLLBAR_CONFIG, useValue: { suppressScrollX: true } },
|
||||
|
@@ -46,10 +46,10 @@ class CompletionObserver {
|
||||
export class AppService {
|
||||
tabs: BaseTabComponent[] = []
|
||||
|
||||
get activeTab (): BaseTabComponent { return this._activeTab }
|
||||
get activeTab (): BaseTabComponent|null { return this._activeTab ?? null }
|
||||
|
||||
private lastTabIndex = 0
|
||||
private _activeTab: BaseTabComponent
|
||||
private _activeTab?: BaseTabComponent
|
||||
private closedTabsStack: RecoveryToken[] = []
|
||||
|
||||
private activeTabChange = new Subject<BaseTabComponent>()
|
||||
@@ -97,9 +97,7 @@ export class AppService {
|
||||
}
|
||||
}
|
||||
|
||||
hostApp.windowFocused$.subscribe(() => {
|
||||
this._activeTab?.emitFocused()
|
||||
})
|
||||
hostApp.windowFocused$.subscribe(() => this._activeTab?.emitFocused())
|
||||
|
||||
this.tabClosed$.subscribe(async tab => {
|
||||
const token = await tab.getRecoveryToken()
|
||||
@@ -192,7 +190,7 @@ export class AppService {
|
||||
this._activeTab.emitFocused()
|
||||
return
|
||||
}
|
||||
if (this.tabs.includes(this._activeTab)) {
|
||||
if (this._activeTab && this.tabs.includes(this._activeTab)) {
|
||||
this.lastTabIndex = this.tabs.indexOf(this._activeTab)
|
||||
} else {
|
||||
this.lastTabIndex = 0
|
||||
@@ -203,12 +201,10 @@ export class AppService {
|
||||
}
|
||||
this._activeTab = tab
|
||||
this.activeTabChange.next(tab)
|
||||
if (this._activeTab) {
|
||||
setImmediate(() => {
|
||||
this._activeTab.emitFocused()
|
||||
})
|
||||
this.hostApp.setTitle(this._activeTab.title)
|
||||
}
|
||||
setImmediate(() => {
|
||||
this._activeTab?.emitFocused()
|
||||
})
|
||||
this.hostApp.setTitle(this._activeTab.title)
|
||||
}
|
||||
|
||||
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
||||
@@ -231,6 +227,9 @@ export class AppService {
|
||||
}
|
||||
|
||||
nextTab (): void {
|
||||
if (!this._activeTab) {
|
||||
return
|
||||
}
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex < this.tabs.length - 1) {
|
||||
@@ -242,6 +241,9 @@ export class AppService {
|
||||
}
|
||||
|
||||
previousTab (): void {
|
||||
if (!this._activeTab) {
|
||||
return
|
||||
}
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex > 0) {
|
||||
@@ -253,6 +255,9 @@ export class AppService {
|
||||
}
|
||||
|
||||
moveSelectedTabLeft (): void {
|
||||
if (!this._activeTab) {
|
||||
return
|
||||
}
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex > 0) {
|
||||
@@ -264,6 +269,9 @@ export class AppService {
|
||||
}
|
||||
|
||||
moveSelectedTabRight (): void {
|
||||
if (!this._activeTab) {
|
||||
return
|
||||
}
|
||||
if (this.tabs.length > 1) {
|
||||
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||
if (tabIndex < this.tabs.length - 1) {
|
||||
|
@@ -97,7 +97,7 @@ export class ConfigService {
|
||||
private changed = new Subject<void>()
|
||||
private _store: any
|
||||
private defaults: any
|
||||
private servicesCache: { [id: string]: Function[] }|null = null
|
||||
private servicesCache: Record<string, Function[]>|null = null // eslint-disable-line @typescript-eslint/ban-types
|
||||
|
||||
get changed$ (): Observable<void> { return this.changed }
|
||||
|
||||
@@ -109,10 +109,7 @@ export class ConfigService {
|
||||
) {
|
||||
this.path = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||
this.defaults = configProviders.map(provider => {
|
||||
let defaults = {}
|
||||
if (provider.platformDefaults) {
|
||||
defaults = configMerge(defaults, provider.platformDefaults[hostApp.platform] || {})
|
||||
}
|
||||
let defaults = provider.platformDefaults[hostApp.platform] || {}
|
||||
if (provider.defaults) {
|
||||
defaults = configMerge(defaults, provider.defaults)
|
||||
}
|
||||
@@ -159,7 +156,7 @@ export class ConfigService {
|
||||
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(JSON.parse(JSON.stringify(this.store)))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,15 +186,15 @@ export class ConfigService {
|
||||
*
|
||||
* @typeparam T Base provider type
|
||||
*/
|
||||
enabledServices<T extends object> (services: T[]): T[] {
|
||||
enabledServices<T extends object> (services: T[]): T[] { // eslint-disable-line @typescript-eslint/ban-types
|
||||
if (!this.servicesCache) {
|
||||
this.servicesCache = {}
|
||||
const ngModule = window['rootModule'].ɵinj
|
||||
for (const imp of ngModule.imports) {
|
||||
const module = imp['ngModule'] || imp
|
||||
const module = imp.ngModule || imp
|
||||
if (module.ɵinj?.providers) {
|
||||
this.servicesCache[module['pluginName']] = module.ɵinj.providers.map(provider => {
|
||||
return provider['useClass'] || provider
|
||||
this.servicesCache[module.pluginName] = module.ɵinj.providers.map(provider => {
|
||||
return provider.useClass || provider
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import type { Display } from 'electron'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { ElectronService } from '../services/electron.service'
|
||||
@@ -11,8 +12,8 @@ export class DockingService {
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
) {
|
||||
electron.screen.on('display-removed', () => this.repositionWindow())
|
||||
electron.screen.on('display-metrics-changed', () => this.repositionWindow())
|
||||
hostApp.displaysChanged$.subscribe(() => this.repositionWindow())
|
||||
hostApp.displayMetricsChanged$.subscribe(() => this.repositionWindow())
|
||||
}
|
||||
|
||||
dock (): void {
|
||||
@@ -25,6 +26,7 @@ export class DockingService {
|
||||
|
||||
let display = this.electron.screen.getAllDisplays()
|
||||
.filter(x => x.id === this.config.store.appearance.dockScreen)[0]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!display) {
|
||||
display = this.getCurrentScreen()
|
||||
}
|
||||
@@ -53,17 +55,19 @@ export class DockingService {
|
||||
newBounds.y = display.bounds.y
|
||||
}
|
||||
|
||||
this.hostApp.setAlwaysOnTop(true)
|
||||
const alwaysOnTop = this.config.store.appearance.dockAlwaysOnTop
|
||||
|
||||
this.hostApp.setAlwaysOnTop(alwaysOnTop)
|
||||
setImmediate(() => {
|
||||
this.hostApp.setBounds(newBounds)
|
||||
})
|
||||
}
|
||||
|
||||
getCurrentScreen (): Electron.Display {
|
||||
getCurrentScreen (): Display {
|
||||
return this.electron.screen.getDisplayNearestPoint(this.electron.screen.getCursorScreenPoint())
|
||||
}
|
||||
|
||||
getScreens (): Electron.Display[] {
|
||||
getScreens (): Display[] {
|
||||
const primaryDisplayID = this.electron.screen.getPrimaryDisplay().id
|
||||
return this.electron.screen.getAllDisplays().sort((a, b) =>
|
||||
a.bounds.x === b.bounds.x ? a.bounds.y - b.bounds.y : a.bounds.x - b.bounds.x
|
||||
@@ -71,7 +75,7 @@ export class DockingService {
|
||||
return {
|
||||
...display,
|
||||
id: display.id,
|
||||
name: display.id === primaryDisplayID ? 'Primary Display' : `Display ${index +1}`,
|
||||
name: display.id === primaryDisplayID ? 'Primary Display' : `Display ${index + 1}`,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { TouchBar, BrowserWindow, Menu, MenuItem, NativeImage } from 'electron'
|
||||
import { App, IpcRenderer, Shell, Dialog, Clipboard, GlobalShortcut, Screen, Remote, AutoUpdater, TouchBar, BrowserWindow, Menu, MenuItem, NativeImage, MessageBoxOptions } from 'electron'
|
||||
|
||||
export interface MessageBoxResponse {
|
||||
response: number
|
||||
@@ -8,16 +8,16 @@ export interface MessageBoxResponse {
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ElectronService {
|
||||
app: Electron.App
|
||||
ipcRenderer: Electron.IpcRenderer
|
||||
shell: Electron.Shell
|
||||
dialog: Electron.Dialog
|
||||
clipboard: Electron.Clipboard
|
||||
globalShortcut: Electron.GlobalShortcut
|
||||
app: App
|
||||
ipcRenderer: IpcRenderer
|
||||
shell: Shell
|
||||
dialog: Dialog
|
||||
clipboard: Clipboard
|
||||
globalShortcut: GlobalShortcut
|
||||
nativeImage: typeof NativeImage
|
||||
screen: Electron.Screen
|
||||
remote: Electron.Remote
|
||||
autoUpdater: Electron.AutoUpdater
|
||||
screen: Screen
|
||||
remote: Remote
|
||||
autoUpdater: AutoUpdater
|
||||
TouchBar: typeof TouchBar
|
||||
BrowserWindow: typeof BrowserWindow
|
||||
Menu: typeof Menu
|
||||
@@ -44,8 +44,8 @@ export class ElectronService {
|
||||
}
|
||||
|
||||
async showMessageBox (
|
||||
browserWindow: Electron.BrowserWindow,
|
||||
options: Electron.MessageBoxOptions
|
||||
browserWindow: BrowserWindow,
|
||||
options: MessageBoxOptions
|
||||
): Promise<MessageBoxResponse> {
|
||||
return this.dialog.showMessageBox(browserWindow, options)
|
||||
}
|
||||
|
@@ -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 * as uuidv4 from 'uuid/v4'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class HomeBaseService {
|
||||
@@ -58,7 +58,7 @@ export class HomeBaseService {
|
||||
|
||||
getAnalyticsProperties (): Record<string, string> {
|
||||
return {
|
||||
distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase
|
||||
distinct_id: window.localStorage.analyticsUserID,
|
||||
platform: process.platform,
|
||||
os: os.release(),
|
||||
version: this.appVersion,
|
||||
|
@@ -1,13 +1,16 @@
|
||||
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
|
||||
import * as path from 'path'
|
||||
import shellEscape from 'shell-escape'
|
||||
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'
|
||||
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
|
||||
|
||||
export enum Platform {
|
||||
Linux, macOS, Windows,
|
||||
Linux = 'Linux',
|
||||
macOS = 'macOS',
|
||||
Windows = 'Windows',
|
||||
}
|
||||
|
||||
export interface Bounds {
|
||||
@@ -42,6 +45,7 @@ export class HostAppService {
|
||||
private windowMoved = new Subject<void>()
|
||||
private windowFocused = new Subject<void>()
|
||||
private displayMetricsChanged = new Subject<void>()
|
||||
private displaysChanged = new Subject<void>()
|
||||
private logger: Logger
|
||||
private windowId: number
|
||||
|
||||
@@ -91,6 +95,8 @@ export class HostAppService {
|
||||
|
||||
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
|
||||
|
||||
get displaysChanged$ (): Observable<void> { return this.displaysChanged }
|
||||
|
||||
private constructor (
|
||||
private zone: NgZone,
|
||||
private electron: ElectronService,
|
||||
@@ -140,6 +146,10 @@ export class HostAppService {
|
||||
this.zone.run(() => this.displayMetricsChanged.next())
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:displays-changed', () => {
|
||||
this.zone.run(() => this.displaysChanged.next())
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => {
|
||||
this.logger.info('Second instance', argv)
|
||||
const op = argv._[0]
|
||||
@@ -166,10 +176,7 @@ export class HostAppService {
|
||||
this.configChangeBroadcast.next()
|
||||
}))
|
||||
|
||||
if (
|
||||
isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED) &&
|
||||
!isWindowsBuild(WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED)
|
||||
) {
|
||||
if (isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
|
||||
electron.ipcRenderer.send('window-set-disable-vibrancy-while-dragging', true)
|
||||
}
|
||||
}
|
||||
@@ -177,8 +184,8 @@ export class HostAppService {
|
||||
/**
|
||||
* Returns the current remote [[BrowserWindow]]
|
||||
*/
|
||||
getWindow (): Electron.BrowserWindow {
|
||||
return this.electron.BrowserWindow.fromId(this.windowId)
|
||||
getWindow (): BrowserWindow {
|
||||
return this.electron.BrowserWindow.fromId(this.windowId)!
|
||||
}
|
||||
|
||||
newWindow (): void {
|
||||
@@ -228,7 +235,7 @@ 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)) {
|
||||
if (this.platform === Platform.Windows && !isWindowsBuild(WIN_BUILD_FLUENT_BG_SUPPORTED)) {
|
||||
type = null
|
||||
}
|
||||
document.body.classList.toggle('vibrant', enable)
|
||||
@@ -239,18 +246,18 @@ export class HostAppService {
|
||||
this.electron.ipcRenderer.send('window-set-title', title)
|
||||
}
|
||||
|
||||
setTouchBar (touchBar: Electron.TouchBar): void {
|
||||
setTouchBar (touchBar: TouchBar): void {
|
||||
this.getWindow().setTouchBar(touchBar)
|
||||
}
|
||||
|
||||
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]): void {
|
||||
popupContextMenu (menuDefinition: MenuItemConstructorOptions[]): void {
|
||||
this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies other windows of config file changes
|
||||
*/
|
||||
broadcastConfigChange (configStore: {[k: string]: any}): void {
|
||||
broadcastConfigChange (configStore: Record<string, any>): void {
|
||||
this.electron.ipcRenderer.send('app:config-change', configStore)
|
||||
}
|
||||
|
||||
|
@@ -172,7 +172,7 @@ export class HotkeysService {
|
||||
return (
|
||||
await Promise.all(
|
||||
this.config.enabledServices(this.hotkeyProviders)
|
||||
.map(async x => x.provide ? x.provide() : x.hotkeys)
|
||||
.map(async x => x.provide())
|
||||
)
|
||||
).reduce((a, b) => a.concat(b))
|
||||
}
|
||||
@@ -189,6 +189,7 @@ export class HotkeysService {
|
||||
|
||||
try {
|
||||
let electronKeySpec = item[0]
|
||||
electronKeySpec = electronKeySpec.replace('Meta', 'Super')
|
||||
electronKeySpec = electronKeySpec.replace('⌘', 'Command')
|
||||
electronKeySpec = electronKeySpec.replace('⌥', 'Alt')
|
||||
electronKeySpec = electronKeySpec.replace(/-/g, '+')
|
||||
@@ -221,7 +222,7 @@ export class HotkeysService {
|
||||
if (!(value instanceof Array)) {
|
||||
continue
|
||||
}
|
||||
if (value) {
|
||||
if (value.length > 0) {
|
||||
value = value.map((item: string | string[]) => typeof item === 'string' ? [item] : item)
|
||||
keys[key] = value
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ const initializeWinston = (electron: ElectronService) => {
|
||||
|
||||
export class Logger {
|
||||
constructor (
|
||||
private winstonLogger: any,
|
||||
private winstonLogger: winston.Logger,
|
||||
private name: string,
|
||||
) {}
|
||||
|
||||
@@ -54,15 +54,13 @@ export class Logger {
|
||||
|
||||
private doLog (level: string, ...args: any[]): void {
|
||||
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||
if (this.winstonLogger) {
|
||||
this.winstonLogger[level](...args)
|
||||
}
|
||||
this.winstonLogger[level](...args)
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LogService {
|
||||
private log: any
|
||||
private log: winston.Logger
|
||||
|
||||
/** @hidden */
|
||||
private constructor (electron: ElectronService) {
|
||||
|
@@ -44,7 +44,7 @@ export class ShellIntegrationService {
|
||||
'extras',
|
||||
'automator-workflows',
|
||||
)
|
||||
this.automatorWorkflowsDestination = path.join(process.env.HOME as string, 'Library', 'Services')
|
||||
this.automatorWorkflowsDestination = path.join(process.env.HOME!, 'Library', 'Services')
|
||||
}
|
||||
this.updatePaths()
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export class ShellIntegrationService {
|
||||
}
|
||||
|
||||
async install (): Promise<void> {
|
||||
const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
|
||||
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) {
|
||||
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
||||
@@ -73,10 +73,10 @@ export class ShellIntegrationService {
|
||||
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')) {
|
||||
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')) {
|
||||
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')
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ export class TabRecoveryService {
|
||||
enabled = false
|
||||
|
||||
private constructor (
|
||||
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
|
||||
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[]|null,
|
||||
private config: ConfigService,
|
||||
log: LogService
|
||||
) {
|
||||
@@ -23,35 +23,28 @@ export class TabRecoveryService {
|
||||
return
|
||||
}
|
||||
window.localStorage.tabsRecovery = JSON.stringify(
|
||||
await Promise.all(
|
||||
(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
|
||||
})
|
||||
.map(async tab => tab.getRecoveryToken().then(r => {
|
||||
if (r) {
|
||||
r.tabTitle = tab.title
|
||||
if (tab.color) {
|
||||
r.tabColor = tab.color
|
||||
}
|
||||
}
|
||||
return token
|
||||
})
|
||||
.filter(token => !!token)
|
||||
)
|
||||
return r
|
||||
}))
|
||||
)).filter(token => !!token)
|
||||
)
|
||||
}
|
||||
|
||||
async recoverTab (token: RecoveryToken): Promise<RecoveredTab|null> {
|
||||
for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
||||
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.color = token.tabColor ?? null
|
||||
tab.options.title = token.tabTitle || ''
|
||||
return tab
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ export class TabsService {
|
||||
const componentRef = componentFactory.create(this.injector)
|
||||
const tab = componentRef.instance
|
||||
tab.hostView = componentRef.hostView
|
||||
Object.assign(tab, inputs || {})
|
||||
Object.assign(tab, inputs ?? {})
|
||||
return tab
|
||||
}
|
||||
|
||||
|
@@ -18,11 +18,11 @@ export class ThemesService {
|
||||
}
|
||||
|
||||
findTheme (name: string): Theme|null {
|
||||
return this.config.enabledServices(this.themes).find(x => x.name === name) || null
|
||||
return this.config.enabledServices(this.themes).find(x => x.name === name) ?? null
|
||||
}
|
||||
|
||||
findCurrentTheme (): Theme {
|
||||
return this.findTheme(this.config.store.appearance.theme) || this.findTheme('Standard')!
|
||||
return this.findTheme(this.config.store.appearance.theme) ?? this.findTheme('Standard')!
|
||||
}
|
||||
|
||||
applyTheme (theme: Theme): void {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { NativeImage, SegmentedControlSegment, TouchBarSegmentedControl } from 'electron'
|
||||
import { Injectable, Inject, NgZone } from '@angular/core'
|
||||
import { TouchBarSegmentedControl, SegmentedControlSegment } from 'electron'
|
||||
import { AppService } from './app.service'
|
||||
import { ConfigService } from './config.service'
|
||||
import { ElectronService } from './electron.service'
|
||||
@@ -12,7 +12,7 @@ export class TouchbarService {
|
||||
private tabsSegmentedControl: TouchBarSegmentedControl
|
||||
private buttonsSegmentedControl: TouchBarSegmentedControl
|
||||
private tabSegments: SegmentedControlSegment[] = []
|
||||
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
|
||||
private nsImageCache: Record<string, NativeImage> = {}
|
||||
|
||||
private constructor (
|
||||
private app: AppService,
|
||||
@@ -33,6 +33,7 @@ export class TouchbarService {
|
||||
app.tabOpened$.subscribe(tab => {
|
||||
tab.titleChange$.subscribe(title => {
|
||||
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (segment) {
|
||||
segment.label = this.shortenTitle(title)
|
||||
this.tabsSegmentedControl.segments = this.tabSegments
|
||||
@@ -41,6 +42,7 @@ export class TouchbarService {
|
||||
tab.activity$.subscribe(hasActivity => {
|
||||
const showIcon = this.app.activeTab !== tab && hasActivity
|
||||
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (segment) {
|
||||
segment.icon = showIcon ? activityIcon : undefined
|
||||
}
|
||||
@@ -53,7 +55,7 @@ export class TouchbarService {
|
||||
label: this.shortenTitle(tab.title),
|
||||
}))
|
||||
this.tabsSegmentedControl.segments = this.tabSegments
|
||||
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
|
||||
this.tabsSegmentedControl.selectedIndex = this.app.activeTab ? this.app.tabs.indexOf(this.app.activeTab) : 0
|
||||
}
|
||||
|
||||
update (): void {
|
||||
@@ -66,14 +68,14 @@ export class TouchbarService {
|
||||
buttons = buttons.concat(provider.provide())
|
||||
})
|
||||
buttons = buttons.filter(x => !!x.touchBarNSImage)
|
||||
buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
||||
buttons.sort((a, b) => (a.weight ?? 0) - (b.weight ?? 0))
|
||||
this.tabSegments = this.app.tabs.map(tab => ({
|
||||
label: this.shortenTitle(tab.title),
|
||||
}))
|
||||
|
||||
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
|
||||
segments: this.tabSegments,
|
||||
selectedIndex: this.app.tabs.indexOf(this.app.activeTab),
|
||||
selectedIndex: this.app.activeTab ? this.app.tabs.indexOf(this.app.activeTab) : undefined,
|
||||
change: (selectedIndex) => this.zone.run(() => {
|
||||
this.app.selectTab(this.app.tabs[selectedIndex])
|
||||
}),
|
||||
@@ -100,15 +102,16 @@ export class TouchbarService {
|
||||
this.hostApp.setTouchBar(touchBar)
|
||||
}
|
||||
|
||||
private getButton (button: ToolbarButton): Electron.SegmentedControlSegment {
|
||||
private getButton (button: ToolbarButton): SegmentedControlSegment {
|
||||
return {
|
||||
label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle || button.title),
|
||||
label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle ?? button.title),
|
||||
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : undefined,
|
||||
// click: () => this.zone.run(() => button.click()),
|
||||
}
|
||||
}
|
||||
|
||||
private getCachedNSImage (name: string) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!this.nsImageCache[name]) {
|
||||
this.nsImageCache[name] = this.electron.nativeImage.createFromNamedImage(name, [0, 0, 1])
|
||||
}
|
||||
|
@@ -1,14 +1,9 @@
|
||||
import axios from 'axios'
|
||||
import * as fs from 'fs'
|
||||
import os from 'os'
|
||||
|
||||
import { spawn } from 'mz/child_process'
|
||||
|
||||
import { Injectable } from '@angular/core'
|
||||
import { 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,7 +14,6 @@ export class UpdaterService {
|
||||
private downloaded: Promise<boolean>
|
||||
private electronUpdaterAvailable = true
|
||||
private updateURL: string
|
||||
private autoUpdater: AppUpdater
|
||||
|
||||
private constructor (
|
||||
log: LogService,
|
||||
@@ -33,26 +27,25 @@ export class UpdaterService {
|
||||
return
|
||||
}
|
||||
|
||||
this.autoUpdater = electron.remote.require('electron-updater').autoUpdater
|
||||
|
||||
this.autoUpdater.autoInstallOnAppQuit = !!config.store.enableAutomaticUpdates
|
||||
|
||||
this.autoUpdater.on('update-available', () => {
|
||||
electron.autoUpdater.on('update-available', () => {
|
||||
this.logger.info('Update available')
|
||||
this.autoUpdater.downloadUpdate()
|
||||
})
|
||||
this.autoUpdater.once('update-not-available', () => {
|
||||
|
||||
electron.autoUpdater.once('update-not-available', () => {
|
||||
this.logger.info('No updates')
|
||||
})
|
||||
|
||||
this.downloaded = new Promise<boolean>(resolve => {
|
||||
this.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||
electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||
})
|
||||
|
||||
if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
|
||||
this.logger.debug('Checking for updates')
|
||||
try {
|
||||
this.autoUpdater.checkForUpdates()
|
||||
electron.autoUpdater.setFeedURL({
|
||||
url: `https://update.electronjs.org/eugeny/terminus/${process.platform}-${process.arch}/${electron.app.getVersion()}`,
|
||||
})
|
||||
electron.autoUpdater.checkForUpdates()
|
||||
} catch (e) {
|
||||
this.electronUpdaterAvailable = false
|
||||
this.logger.info('Electron updater unavailable, falling back', e)
|
||||
@@ -84,21 +77,8 @@ export class UpdaterService {
|
||||
if (!this.electronUpdaterAvailable) {
|
||||
this.electron.shell.openExternal(this.updateURL)
|
||||
} else {
|
||||
if (process.platform === 'win32') {
|
||||
let downloadpath = await this.autoUpdater.downloadUpdate()
|
||||
fs.exists(downloadpath[0], (exists) => {
|
||||
if (exists) {
|
||||
fs.copyFile(downloadpath[0], os.tmpdir() + 'terminus-installer-temp.exe', (err) => {
|
||||
if (!err) {
|
||||
spawn(os.tmpdir() + 'terminus-installer-temp.exe', ['--force-run'], { detached: true, stdio: 'ignore' })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await this.downloaded
|
||||
this.autoUpdater.quitAndInstall(false, true)
|
||||
}
|
||||
await this.downloaded
|
||||
this.electron.autoUpdater.quitAndInstall()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,17 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import type { MenuItemConstructorOptions } from 'electron'
|
||||
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 CloseContextMenu extends TabContextMenuItemProvider {
|
||||
weight = -5
|
||||
export class TabManagementContextMenu extends TabContextMenuItemProvider {
|
||||
weight = 99
|
||||
|
||||
constructor (
|
||||
private app: AppService,
|
||||
@@ -18,8 +20,8 @@ export class CloseContextMenu extends TabContextMenuItemProvider {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
let items = [
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
let items: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Close',
|
||||
click: () => this.zone.run(() => {
|
||||
@@ -59,6 +61,24 @@ export class CloseContextMenu extends TabContextMenuItemProvider {
|
||||
}),
|
||||
},
|
||||
]
|
||||
} 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 MenuItemConstructorOptions[],
|
||||
})
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
@@ -86,12 +106,14 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
let items: MenuItemConstructorOptions[] = []
|
||||
if (tabHeader) {
|
||||
return [
|
||||
items = [
|
||||
...items,
|
||||
{
|
||||
label: 'Rename',
|
||||
click: () => this.zone.run(() => tabHeader?.showRenameTabModal()),
|
||||
click: () => this.zone.run(() => tabHeader.showRenameTabModal()),
|
||||
},
|
||||
{
|
||||
label: 'Duplicate',
|
||||
@@ -99,7 +121,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
},
|
||||
{
|
||||
label: 'Color',
|
||||
sublabel: COLORS.find(x => x.value === tab.color)!.name,
|
||||
sublabel: COLORS.find(x => x.value === tab.color)?.name,
|
||||
submenu: COLORS.map(color => ({
|
||||
label: color.name,
|
||||
type: 'radio',
|
||||
@@ -107,11 +129,11 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
click: () => this.zone.run(() => {
|
||||
tab.color = color.value
|
||||
}),
|
||||
})) as Electron.MenuItemConstructorOptions[],
|
||||
})) as MenuItemConstructorOptions[],
|
||||
},
|
||||
]
|
||||
}
|
||||
return []
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,9 +147,9 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
async getItems (tab: BaseTabComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
const process = await tab.getCurrentProcess()
|
||||
let items: Electron.MenuItemConstructorOptions[] = []
|
||||
const items: MenuItemConstructorOptions[] = []
|
||||
|
||||
const extTab: (BaseTabComponent & { __completionNotificationEnabled?: boolean, __outputNotificationSubscription?: Subscription|null }) = tab
|
||||
|
||||
|
@@ -6,7 +6,8 @@ app-root {
|
||||
|
||||
.btn-tab-bar {
|
||||
line-height: 29px !important;
|
||||
|
||||
height: 27px !important;
|
||||
align-items: center;
|
||||
svg {
|
||||
height: 14px;
|
||||
}
|
||||
|
@@ -137,7 +137,7 @@ app-root {
|
||||
.btn-tab-bar {
|
||||
background: transparent;
|
||||
line-height: 42px;
|
||||
|
||||
align-items: center;
|
||||
svg, path {
|
||||
fill: $black;
|
||||
fill-opacity: 0.75;
|
||||
|
@@ -29,7 +29,7 @@ body {
|
||||
background: $body-bg;
|
||||
|
||||
&.vibrant {
|
||||
background: rgba(0,0,0,.4);
|
||||
background: rgba(0,0,0,.65);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +358,7 @@ search-panel {
|
||||
.btn-secondary:not(:disabled):not(.disabled) {
|
||||
&.active, &:active {
|
||||
background: #191e23;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,7 +4,6 @@ export const WIN_BUILD_CONPTY_SUPPORTED = 17692
|
||||
export const WIN_BUILD_CONPTY_STABLE = 18309
|
||||
export const WIN_BUILD_WSL_EXE_DISTRO_FLAG = 17763
|
||||
export const WIN_BUILD_FLUENT_BG_SUPPORTED = 17063
|
||||
export const WIN_BUILD_FLUENT_BG_MOVE_BUG_FIXED = 18917
|
||||
|
||||
export function isWindowsBuild (build: number): boolean {
|
||||
return process.platform === 'win32' && parseFloat(os.release()) >= 10 && parseInt(os.release().split('.')[2]) >= build
|
||||
|
@@ -4,7 +4,7 @@ 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',
|
||||
|
@@ -2,22 +2,24 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/js-yaml@^3.9.0":
|
||||
version "3.12.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.3.tgz#abf383c5b639d0aa8b8c4a420d6a85f703357d6c"
|
||||
integrity sha512-otRe77JNNWzoVGLKw8TCspKswRoQToys4tuL6XYVBFxjgeM0RUrx7m3jkaTdxILxeGry3zM8mGYkGXMeQ02guA==
|
||||
|
||||
"@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==
|
||||
"@dabh/diagnostics@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
|
||||
integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
colorspace "1.1.x"
|
||||
enabled "2.0.x"
|
||||
kuler "^2.0.0"
|
||||
|
||||
"@types/js-yaml@^3.9.0":
|
||||
version "3.12.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.5.tgz#136d5e6a57a931e1cce6f9d8126aa98a9c92a6bb"
|
||||
integrity sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww==
|
||||
|
||||
"@types/semver@^7.3.1":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
|
||||
integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
|
||||
|
||||
"@types/shell-escape@^0.2.0":
|
||||
version "0.2.0"
|
||||
@@ -45,12 +47,10 @@ argparse@^1.0.7:
|
||||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
async@^2.6.1:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381"
|
||||
integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==
|
||||
dependencies:
|
||||
lodash "^4.17.11"
|
||||
async@^3.1.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
|
||||
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
|
||||
|
||||
at-least-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -65,14 +65,14 @@ axios@^0.19.0:
|
||||
follow-redirects "1.5.10"
|
||||
|
||||
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.5.3"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
|
||||
integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==
|
||||
|
||||
builder-util-runtime@8.6.1:
|
||||
version "8.6.1"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.6.1.tgz#cf9a268fa51704de24f3c085aa8d1d1b3767d9ea"
|
||||
integrity sha512-gwIUtMaICmc+e2EC3u3byXcwCyfhtG40LJRNnGfs8AYqacKl4ZLP50ab+uDttn7QAXe0LfMAuKz9v8bCODV0yg==
|
||||
builder-util-runtime@8.7.2:
|
||||
version "8.7.2"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72"
|
||||
integrity sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
sax "^1.2.4"
|
||||
@@ -95,9 +95,9 @@ color-name@^1.0.0:
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-string@^1.5.2:
|
||||
version "1.5.3"
|
||||
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc"
|
||||
integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6"
|
||||
integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==
|
||||
dependencies:
|
||||
color-name "^1.0.0"
|
||||
simple-swizzle "^0.2.2"
|
||||
@@ -110,15 +110,10 @@ color@3.0.x:
|
||||
color-convert "^1.9.1"
|
||||
color-string "^1.5.2"
|
||||
|
||||
colornames@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96"
|
||||
integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=
|
||||
|
||||
colors@^1.2.1:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
|
||||
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
colorspace@1.1.x:
|
||||
version "1.1.2"
|
||||
@@ -129,9 +124,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.7.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f"
|
||||
integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
@@ -153,55 +148,39 @@ debug@^3.1.0:
|
||||
ms "^2.1.1"
|
||||
|
||||
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==
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
|
||||
integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
ms "2.1.2"
|
||||
|
||||
deepmerge@^4.1.1:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
|
||||
|
||||
diagnostics@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a"
|
||||
integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==
|
||||
dependencies:
|
||||
colorspace "1.1.x"
|
||||
enabled "1.0.x"
|
||||
kuler "1.0.x"
|
||||
|
||||
electron-updater@^4.0.6:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.0.tgz#f66c253b25431d9aeb04fbd33c79062f33943d44"
|
||||
integrity sha512-5K3vPgeiBGQaaCcZzQP00QYhGsh0l/q0mwzGWVZq1BHJ5akA+BpsY+EPiI9JzBhNVIdNlUvSKr5azUdbMwZeig==
|
||||
version "4.3.5"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.5.tgz#4fb36f593a031c87ea07ee141c9f064d5deffb15"
|
||||
integrity sha512-5jjN7ebvfj1cLI0VZMdCnJk6aC4bP+dy7ryBf21vArR0JzpRVk0OZHA2QBD+H5rm6ZSeDYHOY6+8PrMEqJ4wlQ==
|
||||
dependencies:
|
||||
"@types/semver" "^7.1.0"
|
||||
builder-util-runtime "8.6.1"
|
||||
fs-extra "^9.0.0"
|
||||
js-yaml "^3.13.1"
|
||||
"@types/semver" "^7.3.1"
|
||||
builder-util-runtime "8.7.2"
|
||||
fs-extra "^9.0.1"
|
||||
js-yaml "^3.14.0"
|
||||
lazy-val "^1.0.4"
|
||||
lodash.isequal "^4.5.0"
|
||||
semver "^7.1.3"
|
||||
semver "^7.3.2"
|
||||
|
||||
enabled@1.0.x:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93"
|
||||
integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=
|
||||
dependencies:
|
||||
env-variable "0.0.x"
|
||||
|
||||
env-variable@0.0.x:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88"
|
||||
integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==
|
||||
enabled@2.0.x:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
|
||||
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
|
||||
|
||||
es6-promise@^4.0.3:
|
||||
version "4.2.6"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f"
|
||||
integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==
|
||||
version "4.2.8"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
|
||||
|
||||
es6-promisify@^5.0.0:
|
||||
version "5.0.0"
|
||||
@@ -216,14 +195,19 @@ esprima@^4.0.0:
|
||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
|
||||
fast-safe-stringify@^2.0.4:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2"
|
||||
integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
|
||||
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
|
||||
|
||||
fecha@^2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
|
||||
integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==
|
||||
fecha@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41"
|
||||
integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==
|
||||
|
||||
fn.name@1.x.x:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||
|
||||
follow-redirects@1.5.10:
|
||||
version "1.5.10"
|
||||
@@ -232,10 +216,10 @@ 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@^9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc"
|
||||
integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==
|
||||
dependencies:
|
||||
at-least-node "^1.0.0"
|
||||
graceful-fs "^4.2.0"
|
||||
@@ -243,9 +227,9 @@ fs-extra@^9.0.0:
|
||||
universalify "^1.0.0"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02"
|
||||
integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||
|
||||
https-proxy-agent@3.0.0:
|
||||
version "3.0.0"
|
||||
@@ -256,48 +240,46 @@ https-proxy-agent@3.0.0:
|
||||
debug "^3.1.0"
|
||||
|
||||
inherits@^2.0.3, inherits@~2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
is-arrayish@^0.3.1:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
||||
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
|
||||
|
||||
is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||
is-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
|
||||
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
js-yaml@^3.13.1, js-yaml@^3.9.0:
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
||||
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
|
||||
js-yaml@^3.14.0, 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==
|
||||
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==
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||
dependencies:
|
||||
universalify "^1.0.0"
|
||||
universalify "^2.0.0"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
kuler@1.0.x:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6"
|
||||
integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==
|
||||
dependencies:
|
||||
colornames "^1.1.1"
|
||||
kuler@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
|
||||
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
|
||||
|
||||
lazy-val@^1.0.4:
|
||||
version "1.0.4"
|
||||
@@ -309,19 +291,14 @@ lodash.isequal@^4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
||||
|
||||
lodash@^4.17.11:
|
||||
version "4.17.14"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
|
||||
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
|
||||
|
||||
logform@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360"
|
||||
integrity sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==
|
||||
logform@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
|
||||
integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==
|
||||
dependencies:
|
||||
colors "^1.2.1"
|
||||
fast-safe-stringify "^2.0.4"
|
||||
fecha "^2.3.3"
|
||||
fecha "^4.2.0"
|
||||
ms "^2.1.1"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
@@ -337,7 +314,7 @@ ms@2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
ms@^2.1.1:
|
||||
ms@2.1.2, ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
@@ -355,25 +332,27 @@ ngx-perfect-scrollbar@^8.0.0:
|
||||
perfect-scrollbar "^1.4.0"
|
||||
resize-observer-polyfill "^1.5.0"
|
||||
|
||||
one-time@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e"
|
||||
integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=
|
||||
one-time@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
|
||||
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
|
||||
dependencies:
|
||||
fn.name "1.x.x"
|
||||
|
||||
perfect-scrollbar@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.4.0.tgz#5d014ef9775e1f43058a1dbae9ed1daf0e7091f1"
|
||||
integrity sha512-/2Sk/khljhdrsamjJYS5NjrH+GKEHEwh7zFSiYyxROyYKagkE4kSn2zDQDRTOMo8mpT2jikxx6yI1dG7lNP/hw==
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.0.tgz#821d224ed8ff61990c23f26db63048cdc75b6b83"
|
||||
integrity sha512-NrNHJn5mUGupSiheBTy6x+6SXCFbLlm8fVZh9moIzw/LgqElN5q4ncR4pbCBCYuCJ8Kcl9mYM0NgDxvW+b4LxA==
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
|
||||
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
readable-stream@^2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
|
||||
readable-stream@2.3.7, readable-stream@^2.3.7:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
@@ -383,10 +362,10 @@ readable-stream@^2.3.6:
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.1.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9"
|
||||
integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==
|
||||
readable-stream@^3.4.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
@@ -402,15 +381,20 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
sax@^1.2.4:
|
||||
version "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@^7.3.2:
|
||||
version "7.3.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||
|
||||
shell-escape@^0.2.0:
|
||||
version "0.2.0"
|
||||
@@ -435,11 +419,11 @@ stack-trace@0.0.x:
|
||||
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
|
||||
|
||||
string_decoder@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
|
||||
integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
@@ -463,35 +447,40 @@ universalify@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
||||
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
uuid@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.1.tgz#95ed6ff3d8c881cbf85f0f05cc3915ef994818ef"
|
||||
integrity sha512-yqjRXZzSJm9Dbl84H2VDHpM3zMjzSJQ+hn6C4zqd5ilW+7P4ZmLEEqwho9LjP+tGuZlF4xrHQXT0h9QZUS/pWA==
|
||||
uuid@^8.0.0:
|
||||
version "8.3.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
|
||||
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
|
||||
|
||||
winston-transport@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.3.0.tgz#df68c0c202482c448d9b47313c07304c2d7c2c66"
|
||||
integrity sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==
|
||||
winston-transport@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
|
||||
integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
|
||||
dependencies:
|
||||
readable-stream "^2.3.6"
|
||||
readable-stream "^2.3.7"
|
||||
triple-beam "^1.2.0"
|
||||
|
||||
winston@*, winston@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/winston/-/winston-3.2.1.tgz#63061377976c73584028be2490a1846055f77f07"
|
||||
integrity sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==
|
||||
winston@*, winston@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
|
||||
integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
|
||||
dependencies:
|
||||
async "^2.6.1"
|
||||
diagnostics "^1.1.1"
|
||||
is-stream "^1.1.0"
|
||||
logform "^2.1.1"
|
||||
one-time "0.0.4"
|
||||
readable-stream "^3.1.1"
|
||||
"@dabh/diagnostics" "^2.0.2"
|
||||
async "^3.1.0"
|
||||
is-stream "^2.0.0"
|
||||
logform "^2.2.0"
|
||||
one-time "^1.0.0"
|
||||
readable-stream "^3.4.0"
|
||||
stack-trace "0.0.x"
|
||||
triple-beam "^1.3.0"
|
||||
winston-transport "^4.3.0"
|
||||
winston-transport "^4.4.0"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-plugin-manager",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.123-nightly.0",
|
||||
"description": "Terminus' plugin manager",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -19,16 +19,17 @@
|
||||
"devDependencies": {
|
||||
"@types/semver": "^7.1.0",
|
||||
"axios": "^0.19.0",
|
||||
"electron-promise-ipc": "^2.2.4",
|
||||
"mz": "^2.6.0",
|
||||
"semver": "^7.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^7",
|
||||
"@angular/core": "^7",
|
||||
"@angular/forms": "^7",
|
||||
"@angular/platform-browser": "^7",
|
||||
"@ng-bootstrap/ng-bootstrap": "^1",
|
||||
"rxjs": "^5",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.11",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||
"rxjs": "^6.5.5",
|
||||
"terminus-core": "*",
|
||||
"terminus-settings": "*"
|
||||
}
|
||||
|
@@ -22,10 +22,10 @@
|
||||
button.btn.btn-primary.ml-2(
|
||||
*ngIf='knownUpgrades[plugin.name]',
|
||||
(click)='upgradePlugin(plugin)',
|
||||
[disabled]='busy[plugin.name] != undefined'
|
||||
[disabled]='busy.has(plugin.name)'
|
||||
)
|
||||
i.fas.fa-fw.fa-arrow-up(*ngIf='busy[plugin.name] != BusyState.Installing')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
||||
i.fas.fa-fw.fa-arrow-up(*ngIf='busy.get(plugin.name) != BusyState.Installing')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Installing')
|
||||
span Upgrade ({{knownUpgrades[plugin.name].version}})
|
||||
|
||||
button.btn.btn-link.text-primary.ml-2(
|
||||
@@ -43,10 +43,10 @@
|
||||
button.btn.btn-link.text-danger.ml-2(
|
||||
(click)='uninstallPlugin(plugin)',
|
||||
*ngIf='!plugin.isBuiltin',
|
||||
[disabled]='busy[plugin.name] != undefined'
|
||||
[disabled]='busy.has(plugin.name)'
|
||||
)
|
||||
i.fas.fa-fw.fa-trash(*ngIf='busy[plugin.name] != BusyState.Uninstalling')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Uninstalling')
|
||||
i.fas.fa-fw.fa-trash(*ngIf='busy.get(plugin.name) != BusyState.Uninstalling')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Uninstalling')
|
||||
|
||||
div
|
||||
h3.mt-4 Available
|
||||
@@ -69,10 +69,10 @@ div
|
||||
.list-group-item.d-flex.align-items-center(*ngIf='!isAlreadyInstalled(plugin)')
|
||||
button.btn.btn-primary.mr-3(
|
||||
(click)='installPlugin(plugin)',
|
||||
[disabled]='busy[plugin.name] != undefined'
|
||||
[disabled]='busy.has(plugin.name)'
|
||||
)
|
||||
i.fas.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
||||
i.fas.fa-fw.fa-download(*ngIf='busy.get(plugin.name) != BusyState.Installing')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy.get(plugin.name) == BusyState.Installing')
|
||||
|
||||
div((click)='showPluginInfo(plugin)')
|
||||
div
|
||||
|
@@ -7,7 +7,7 @@ import { Component, Input } from '@angular/core'
|
||||
import { ConfigService, ElectronService } from 'terminus-core'
|
||||
import { PluginInfo, PluginManagerService } from '../services/pluginManager.service'
|
||||
|
||||
enum BusyState { Installing, Uninstalling }
|
||||
enum BusyState { Installing = 'Installing', Uninstalling = 'Uninstalling' }
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
@@ -19,8 +19,8 @@ export class PluginsSettingsTabComponent {
|
||||
@Input() availablePlugins$: Observable<PluginInfo[]>
|
||||
@Input() availablePluginsQuery$ = new BehaviorSubject<string>('')
|
||||
@Input() availablePluginsReady = false
|
||||
@Input() knownUpgrades: {[id: string]: PluginInfo|null} = {}
|
||||
@Input() busy: {[id: string]: BusyState} = {}
|
||||
@Input() knownUpgrades: Record<string, PluginInfo|null> = {}
|
||||
@Input() busy = new Map<string, BusyState>()
|
||||
@Input() erroredPlugin: string
|
||||
@Input() errorMessage: string
|
||||
|
||||
@@ -55,7 +55,7 @@ export class PluginsSettingsTabComponent {
|
||||
}
|
||||
|
||||
openPluginsFolder (): void {
|
||||
this.electron.shell.openItem(this.pluginManager.userPluginsPath)
|
||||
this.electron.shell.openPath(this.pluginManager.userPluginsPath)
|
||||
}
|
||||
|
||||
searchAvailable (query: string) {
|
||||
@@ -67,29 +67,29 @@ export class PluginsSettingsTabComponent {
|
||||
}
|
||||
|
||||
async installPlugin (plugin: PluginInfo): Promise<void> {
|
||||
this.busy[plugin.name] = BusyState.Installing
|
||||
this.busy.set(plugin.name, BusyState.Installing)
|
||||
try {
|
||||
await this.pluginManager.installPlugin(plugin)
|
||||
delete this.busy[plugin.name]
|
||||
this.busy.delete(plugin.name)
|
||||
this.config.requestRestart()
|
||||
} catch (err) {
|
||||
this.erroredPlugin = plugin.name
|
||||
this.errorMessage = err
|
||||
delete this.busy[plugin.name]
|
||||
this.busy.delete(plugin.name)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
||||
this.busy[plugin.name] = BusyState.Uninstalling
|
||||
this.busy.set(plugin.name, BusyState.Uninstalling)
|
||||
try {
|
||||
await this.pluginManager.uninstallPlugin(plugin)
|
||||
delete this.busy[plugin.name]
|
||||
this.busy.delete(plugin.name)
|
||||
this.config.requestRestart()
|
||||
} catch (err) {
|
||||
this.erroredPlugin = plugin.name
|
||||
this.errorMessage = err
|
||||
delete this.busy[plugin.name]
|
||||
this.busy.delete(plugin.name)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import promiseIpc from 'electron-promise-ipc'
|
||||
import { Observable, from } from 'rxjs'
|
||||
import { map } from 'rxjs/operators'
|
||||
import { Injectable } from '@angular/core'
|
||||
@@ -31,39 +32,15 @@ export class PluginManagerService {
|
||||
userPluginsPath: string = (window as any).userPluginsPath
|
||||
installedPlugins: PluginInfo[] = (window as any).installedPlugins
|
||||
|
||||
private npmReady: Promise<void>
|
||||
private npm: any
|
||||
|
||||
private constructor (
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('pluginManager')
|
||||
}
|
||||
|
||||
async getNPM (): Promise<any> {
|
||||
if (!this.npm) {
|
||||
if (!this.npmReady) {
|
||||
this.npmReady = new Promise(resolve => {
|
||||
const npm = (global as any).require('npm')
|
||||
npm.load({
|
||||
prefix: this.userPluginsPath,
|
||||
}, err => {
|
||||
if (err) {
|
||||
this.logger.error(err)
|
||||
}
|
||||
this.npm = npm
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
await this.npmReady
|
||||
}
|
||||
return this.npm
|
||||
}
|
||||
|
||||
listAvailable (query?: string): Observable<PluginInfo[]> {
|
||||
return from(
|
||||
axios.get(`https://www.npmjs.com/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query || '')}&from=0&size=1000`, {
|
||||
axios.get(`https://www.npmjs.com/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query ?? '')}&from=0&size=1000`, {
|
||||
headers: {
|
||||
'x-spiferack': '1',
|
||||
},
|
||||
@@ -84,21 +61,23 @@ export class PluginManagerService {
|
||||
}
|
||||
|
||||
async installPlugin (plugin: PluginInfo): Promise<void> {
|
||||
(await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => {
|
||||
if (err) {
|
||||
this.logger.error(err)
|
||||
}
|
||||
try {
|
||||
await (promiseIpc as any).send('plugin-manager:install', this.userPluginsPath, plugin.packageName, plugin.version)
|
||||
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
||||
this.installedPlugins.push(plugin)
|
||||
})
|
||||
} catch (err) {
|
||||
this.logger.error(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
async uninstallPlugin (plugin: PluginInfo): Promise<void> {
|
||||
(await this.getNPM()).commands.remove([plugin.packageName], err => {
|
||||
if (err) {
|
||||
this.logger.error(err)
|
||||
}
|
||||
try {
|
||||
await (promiseIpc as any).send('plugin-manager:uninstall', this.userPluginsPath, plugin.packageName)
|
||||
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
||||
})
|
||||
} catch (err) {
|
||||
this.logger.error(err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ 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',
|
||||
@@ -46,8 +46,8 @@ module.exports = {
|
||||
externals: [
|
||||
'fs',
|
||||
'net',
|
||||
'npm',
|
||||
'path',
|
||||
'electron-promise-ipc',
|
||||
/^rxjs/,
|
||||
/^@angular/,
|
||||
/^@ng-bootstrap/,
|
||||
|
@@ -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" "*"
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
|
||||
integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
|
||||
|
||||
any-promise@^1.0.0:
|
||||
version "1.3.0"
|
||||
@@ -26,6 +19,14 @@ axios@^0.19.0:
|
||||
dependencies:
|
||||
follow-redirects "1.5.10"
|
||||
|
||||
call-bind@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce"
|
||||
integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.0"
|
||||
|
||||
debug@=3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
@@ -33,6 +34,50 @@ debug@=3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
define-properties@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
|
||||
dependencies:
|
||||
object-keys "^1.0.12"
|
||||
|
||||
electron-promise-ipc@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/electron-promise-ipc/-/electron-promise-ipc-2.2.4.tgz#b82daf86ca6d0f0b8655937fdbe9a554590deeea"
|
||||
integrity sha512-xCkFEeuru9l7H/+m1gpK4F1utexvTT7+n1PTquP2MVTpmBmpgFBlLqSXC7TqwpROkHRm9wGpaCJEx0djonnSEg==
|
||||
dependencies:
|
||||
is-electron-renderer "^2.0.1"
|
||||
object.entries "^1.1.3"
|
||||
serialize-error "^5.0.0"
|
||||
uuid "^3.0.1"
|
||||
|
||||
es-abstract@^1.18.0-next.1:
|
||||
version "1.18.0-next.1"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
|
||||
integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
|
||||
dependencies:
|
||||
es-to-primitive "^1.2.1"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.1"
|
||||
is-callable "^1.2.2"
|
||||
is-negative-zero "^2.0.0"
|
||||
is-regex "^1.1.1"
|
||||
object-inspect "^1.8.0"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.1"
|
||||
string.prototype.trimend "^1.0.1"
|
||||
string.prototype.trimstart "^1.0.1"
|
||||
|
||||
es-to-primitive@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||
integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
|
||||
dependencies:
|
||||
is-callable "^1.1.4"
|
||||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
follow-redirects@1.5.10:
|
||||
version "1.5.10"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
|
||||
@@ -40,6 +85,66 @@ follow-redirects@1.5.10:
|
||||
dependencies:
|
||||
debug "=3.1.0"
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
get-intrinsic@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49"
|
||||
integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
has-symbols@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
is-callable@^1.1.4, is-callable@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
|
||||
integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
|
||||
|
||||
is-date-object@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
|
||||
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
|
||||
|
||||
is-electron-renderer@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz#a469d056f975697c58c98c6023eb0aa79af895a2"
|
||||
integrity sha1-pGnQVvl1aXxYyYxgI+sKp5r4laI=
|
||||
|
||||
is-negative-zero@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
|
||||
integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
|
||||
|
||||
is-regex@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9"
|
||||
integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
|
||||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-symbol@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
|
||||
integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
|
||||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
@@ -59,10 +164,63 @@ object-assign@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-inspect@^1.8.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
|
||||
integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
|
||||
|
||||
object-keys@^1.0.12, object-keys@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||
|
||||
object.assign@^4.1.1:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
|
||||
integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
has-symbols "^1.0.1"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
object.entries@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6"
|
||||
integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.18.0-next.1"
|
||||
has "^1.0.3"
|
||||
|
||||
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==
|
||||
version "7.3.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||
|
||||
serialize-error@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-5.0.0.tgz#a7ebbcdb03a5d71a6ed8461ffe0fc1a1afed62ac"
|
||||
integrity sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==
|
||||
dependencies:
|
||||
type-fest "^0.8.0"
|
||||
|
||||
string.prototype.trimend@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b"
|
||||
integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
string.prototype.trimstart@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa"
|
||||
integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
thenify-all@^1.0.0:
|
||||
version "1.6.0"
|
||||
@@ -72,8 +230,18 @@ thenify-all@^1.0.0:
|
||||
thenify ">= 3.1.0 < 4"
|
||||
|
||||
"thenify@>= 3.1.0 < 4":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839"
|
||||
integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
|
||||
integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
type-fest@^0.8.0:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
uuid@^3.0.1:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
|
0
terminus-serial/.gitignore
vendored
Normal file
0
terminus-serial/.gitignore
vendored
Normal file
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-serial",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.123-nightly.0",
|
||||
"description": "Serial connection manager for Terminus",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -17,19 +17,20 @@
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "12.7.3",
|
||||
"@types/node": "14.14.14",
|
||||
"@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"
|
||||
"cli-spinner": "^0.2.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^7",
|
||||
"@angular/core": "^7",
|
||||
"@angular/forms": "^7",
|
||||
"@ng-bootstrap/ng-bootstrap": "^1",
|
||||
"rxjs": "^5",
|
||||
"@angular/animations": "^9.1.9",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.11",
|
||||
"@angular/platform-browser-dynamic": "^9.1.11",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.2.0",
|
||||
"rxjs": "^6.6.3",
|
||||
"terminus-core": "*",
|
||||
"terminus-settings": "*",
|
||||
"terminus-terminal": "*"
|
||||
|
@@ -44,7 +44,7 @@ export class SerialSession extends BaseSession {
|
||||
|
||||
constructor (public connection: SerialConnection) {
|
||||
super()
|
||||
this.scripts = connection.scripts || []
|
||||
this.scripts = connection.scripts ?? []
|
||||
}
|
||||
|
||||
async start (): Promise<void> {
|
||||
|
@@ -28,7 +28,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
||||
weight: 5,
|
||||
title: 'Serial connections',
|
||||
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
|
||||
click: async () => {
|
||||
click: () => {
|
||||
this.activate()
|
||||
},
|
||||
}]
|
||||
|
@@ -37,7 +37,7 @@ export class EditConnectionModalComponent {
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
this.connection.scripts = this.connection.scripts || []
|
||||
this.connection.scripts = this.connection.scripts ?? []
|
||||
this.foundPorts = await this.serial.listPorts()
|
||||
}
|
||||
|
||||
|
@@ -11,13 +11,13 @@ import { Subscription } from 'rxjs'
|
||||
/** @hidden */
|
||||
@Component({
|
||||
selector: 'serial-tab',
|
||||
template: BaseTerminalTabComponent.template + require<string>('./serialTab.component.pug'),
|
||||
template: BaseTerminalTabComponent.template + (require('./serialTab.component.pug') as string),
|
||||
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||
animations: BaseTerminalTabComponent.animations,
|
||||
})
|
||||
export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
connection: SerialConnection
|
||||
session: SerialSession
|
||||
connection?: SerialConnection
|
||||
session?: SerialSession
|
||||
serialPort: any
|
||||
private homeEndSubscription: Subscription
|
||||
|
||||
@@ -52,7 +52,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
super.ngOnInit()
|
||||
|
||||
setImmediate(() => {
|
||||
this.setTitle(this.connection.name)
|
||||
this.setTitle(this.connection!.name)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
|
||||
this.session = this.injector.get(SerialService).createSession(this.connection)
|
||||
this.session.serviceMessage$.subscribe(msg => {
|
||||
this.write('\r\n' + colors.black.bgWhite(' serial ') + ' ' + msg + '\r\n')
|
||||
this.session.resize(this.size.columns, this.size.rows)
|
||||
this.write(`\r\n${colors.black.bgWhite(' serial ')} ${msg}\r\n`)
|
||||
this.session?.resize(this.size.columns, this.size.rows)
|
||||
})
|
||||
this.attachSessionHandlers()
|
||||
this.write(`Connecting to `)
|
||||
@@ -108,7 +108,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||
name: x.toString(), result: x,
|
||||
})))
|
||||
this.serialPort.update({ baudRate: rate })
|
||||
this.connection.baudrate = rate
|
||||
this.connection!.baudrate = rate
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
|
@@ -7,12 +7,12 @@ import { SerialTabComponent } from './components/serialTab.component'
|
||||
@Injectable()
|
||||
export class RecoveryProvider extends TabRecoveryProvider {
|
||||
async recover (recoveryToken: RecoveryToken): Promise<RecoveredTab|null> {
|
||||
if (recoveryToken?.type === 'app:serial-tab') {
|
||||
if (recoveryToken.type === 'app:serial-tab') {
|
||||
return {
|
||||
type: SerialTabComponent,
|
||||
options: {
|
||||
connection: recoveryToken['connection'],
|
||||
savedState: recoveryToken['savedState'],
|
||||
connection: recoveryToken.connection,
|
||||
savedState: recoveryToken.savedState,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@@ -57,7 +57,6 @@ export class SerialService {
|
||||
this.toastr.error(e.message)
|
||||
reject(e)
|
||||
}
|
||||
|
||||
})
|
||||
return serial
|
||||
}
|
||||
@@ -125,10 +124,10 @@ export class SerialService {
|
||||
{ connection }
|
||||
) as SerialTabComponent
|
||||
if (connection.color) {
|
||||
(this.app.getParentTab(tab) || tab).color = connection.color
|
||||
(this.app.getParentTab(tab) ?? tab).color = connection.color
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.app.activeTab.emitFocused()
|
||||
this.app.activeTab?.emitFocused()
|
||||
})
|
||||
return tab
|
||||
} catch (error) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "terminus-settings",
|
||||
"version": "1.0.104-nightly.0",
|
||||
"version": "1.0.123-nightly.0",
|
||||
"description": "Terminus terminal settings page",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
@@ -20,12 +20,13 @@
|
||||
"@types/deep-equal": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^7",
|
||||
"@angular/core": "^7",
|
||||
"@angular/forms": "^7",
|
||||
"@angular/platform-browser": "^7",
|
||||
"@ng-bootstrap/ng-bootstrap": "^1",
|
||||
"rxjs": "^5",
|
||||
"@angular/animations": "^9.1.9",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.11",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||
"rxjs": "^6.5.5",
|
||||
"terminus-core": "*"
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ import { HotkeyInputModalComponent } from './hotkeyInputModal.component'
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MultiHotkeyInputComponent {
|
||||
@Input() model: string[][]
|
||||
@Input() model: string[][] = []
|
||||
@Output() modelChange = new EventEmitter()
|
||||
|
||||
constructor (
|
||||
@@ -18,9 +18,6 @@ export class MultiHotkeyInputComponent {
|
||||
) { }
|
||||
|
||||
ngOnInit (): void {
|
||||
if (!this.model) {
|
||||
this.model = []
|
||||
}
|
||||
if (typeof this.model === 'string') {
|
||||
this.model = [this.model]
|
||||
}
|
||||
|
@@ -43,18 +43,32 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
||||
ngbButton,
|
||||
[value]='"top"'
|
||||
)
|
||||
| On the top
|
||||
| Top
|
||||
label.btn.btn-secondary(ngbButtonLabel)
|
||||
input(
|
||||
type='radio',
|
||||
ngbButton,
|
||||
[value]='"bottom"'
|
||||
)
|
||||
| At the bottom
|
||||
| Bottom
|
||||
label.btn.btn-secondary(ngbButtonLabel)
|
||||
input(
|
||||
type='radio',
|
||||
ngbButton,
|
||||
[value]='"left"'
|
||||
)
|
||||
| Left
|
||||
label.btn.btn-secondary(ngbButtonLabel)
|
||||
input(
|
||||
type='radio',
|
||||
ngbButton,
|
||||
[value]='"right"'
|
||||
)
|
||||
| Right
|
||||
|
||||
.form-line(*ngIf='hostApp.platform !== Platform.Linux')
|
||||
.form-line
|
||||
.header
|
||||
.title(*ngIf='hostApp.platform === Platform.Windows') Acrylic background
|
||||
.title(*ngIf='hostApp.platform !== Platform.macOS') Acrylic background
|
||||
.title(*ngIf='hostApp.platform === Platform.macOS') Vibrancy
|
||||
.description Gives the window a blurred transparent background
|
||||
|
||||
@@ -207,6 +221,15 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
||||
)
|
||||
| {{screen.name}}
|
||||
|
||||
.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||
.header
|
||||
.title Dock always on top
|
||||
.description Keep docked terminal always on top
|
||||
toggle(
|
||||
[(ngModel)]='config.store.appearance.dockAlwaysOnTop',
|
||||
(ngModelChange)='config.save(); docking.dock()',
|
||||
)
|
||||
|
||||
.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||
.header
|
||||
.title Docked terminal size
|
||||
@@ -219,6 +242,15 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
||||
step='0.01'
|
||||
)
|
||||
|
||||
.form-line(*ngIf='config.store.appearance.dock != "off"')
|
||||
.header
|
||||
.title Hide dock on blur
|
||||
.description Hides the docked terminal when you click away.
|
||||
toggle(
|
||||
[(ngModel)]='config.store.appearance.dockHideOnBlur',
|
||||
(ngModelChange)='config.save(); ',
|
||||
)
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Debugging
|
||||
@@ -270,7 +302,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
||||
th ID
|
||||
th Hotkey
|
||||
ng-container(*ngFor='let hotkey of hotkeyDescriptions')
|
||||
tr(*ngIf='!hotkeyFilter || hotkey.name.toLowerCase().includes(hotkeyFilter.toLowerCase())')
|
||||
tr(*ngIf='!hotkeyFilter || hotkeyFilterFn(hotkey, hotkeyFilter)')
|
||||
td {{hotkey.name}}
|
||||
td {{hotkey.id}}
|
||||
td.pr-5
|
||||
|
@@ -65,19 +65,15 @@ export class SettingsTabComponent extends BaseTabComponent {
|
||||
const onConfigChange = () => {
|
||||
this.configFile = config.readRaw()
|
||||
this.padWindowControls = hostApp.platform === Platform.macOS
|
||||
&& config.store.appearance.tabsLocation === 'bottom'
|
||||
&& config.store.appearance.tabsLocation !== 'top'
|
||||
}
|
||||
|
||||
this.configSubscription = config.changed$.subscribe(onConfigChange)
|
||||
onConfigChange()
|
||||
|
||||
const onScreenChange = () => {
|
||||
hostApp.displaysChanged$.subscribe(() => {
|
||||
this.zone.run(() => this.screens = this.docking.getScreens())
|
||||
}
|
||||
|
||||
electron.screen.on('display-added', onScreenChange)
|
||||
electron.screen.on('display-removed', onScreenChange)
|
||||
electron.screen.on('display-metrics-changed', onScreenChange)
|
||||
})
|
||||
|
||||
hotkeys.getHotkeyDescriptions().then(descriptions => {
|
||||
this.hotkeyDescriptions = descriptions
|
||||
@@ -144,4 +140,10 @@ export class SettingsTabComponent extends BaseTabComponent {
|
||||
}
|
||||
ptr[prop] = value
|
||||
}
|
||||
|
||||
hotkeyFilterFn (hotkey: HotkeyDescription, query: string): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||
const s = hotkey.name + (this.getHotkey(hotkey.id) || []).toString()
|
||||
return s.toLowerCase().includes(query.toLowerCase())
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user