Compare commits

..

49 Commits

Author SHA1 Message Date
Eugene
6d3a71840b Revert "Cross Compile linux armhf/arm64 artifacts" 2023-06-26 16:27:51 +02:00
Eugene
a7ca0fb1a3 Merge pull request #8613 from Jai-JAP/master 2023-06-26 16:27:47 +02:00
Jai A P
a07e7ddf16 Update build-linux.mjs 2023-06-25 08:55:10 +05:30
Jai A P
86948d1eeb Update build.yml 2023-06-25 08:51:57 +05:30
Jai A P
75a3439f4d Update build.yml 2023-06-25 08:00:27 +05:30
Jai A P
1b1c0688a0 Update build.yml 2023-06-25 07:54:55 +05:30
Jai A P
7b9af38701 Update build.yml 2023-06-25 00:48:33 +05:30
Jai A P
c28a087b4c Update HACKING.md 2023-06-25 00:46:11 +05:30
Jai A P
61f6399926 Merge branch 'Eugeny:master' into master 2023-06-24 16:48:55 +05:30
Jai A P
629c17afc5 Update build.yml 2023-06-24 16:48:21 +05:30
Jai A P
f2871decda Update build.yml 2023-06-24 16:26:25 +05:30
Jai A P
130d22a00c Update build.yml 2023-06-24 16:13:04 +05:30
Jai A P
d9e659e8a9 Update build.yml 2023-06-24 15:42:29 +05:30
Jai A P
556299ce74 Update build.yml 2023-06-24 15:39:07 +05:30
Jai A P
eeca05aded Update build.yml 2023-06-24 15:37:48 +05:30
Jai A P
4f06e5392a Update build.yml 2023-06-24 15:30:10 +05:30
Jai A P
5232e08b3e Update build.yml 2023-06-24 15:29:04 +05:30
Jai A P
2fb7d120cc Update build.yml 2023-06-24 15:10:26 +05:30
Jai A P
4b9769b5f9 Update build.yml 2023-06-24 15:09:49 +05:30
Jai A P
89b48f10ea Update build.yml 2023-06-24 15:05:00 +05:30
Jai A P
e771570934 Update build.yml 2023-06-24 00:10:30 +05:30
Jai A P
b0fc7710c7 Update build.yml 2023-06-23 23:57:11 +05:30
Jai A P
f60966b689 Update build.yml 2023-06-23 23:46:22 +05:30
Jai A P
c8ef4543c3 Update build.yml 2023-06-23 23:31:03 +05:30
Jai A P
f56c1bbfd4 Update build.yml 2023-06-23 23:11:19 +05:30
Jai A P
4a23aceb2d Update vars.mjs 2023-06-23 22:02:51 +05:30
Jai A P
cbabc1c829 Update build.yml 2023-06-23 21:40:30 +05:30
Jai A P
b1ac07e16e Update build.yml 2023-06-23 21:16:12 +05:30
Jai A P
2f82fb06b1 Update build.yml 2023-06-21 23:59:14 +05:30
Jai A P
75a3e89b1f Update build.yml 2023-06-21 23:46:00 +05:30
Jai A P
d10926bf46 Update build.yml 2023-06-21 23:36:59 +05:30
Jai A P
a53feb3215 Update build.yml 2023-06-21 23:26:57 +05:30
Jai A P
018a9940d1 Update build.yml 2023-06-21 23:18:04 +05:30
Jai A P
9a3f1a68c6 Update build.yml 2023-06-21 23:05:21 +05:30
Jai A P
23fba79173 Update build.yml 2023-06-21 22:59:15 +05:30
Jai A P
549954d49f Update build.yml 2023-06-21 22:42:29 +05:30
Jai A P
816468214f Update sentry-upload.mjs 2023-06-21 22:25:31 +05:30
Jai A P
f6d406e0da Update webpack.config.main.mjs 2023-06-21 22:24:43 +05:30
Jai A P
6bbe3b82dd Update pty.ts 2023-06-21 22:23:12 +05:30
Jai A P
07497ac869 Update package.json 2023-06-21 22:22:38 +05:30
Jai A P
3dc85936d9 Update build.yml 2023-06-21 21:50:54 +05:30
Jai A P
b5a6606895 Update build.yml 2023-06-19 14:12:46 +05:30
Jai A P
ef195c406b Update build.yml 2023-06-19 14:03:50 +05:30
Jai A P
5d2e4582f1 Update build.yml 2023-06-19 13:57:58 +05:30
Jai A P
682f1a9b9e Update build.yml 2023-06-19 13:53:22 +05:30
Jai A P
f373cd958c Update build.yml 2023-06-19 13:46:26 +05:30
Jai A P
40c5659315 Update build.yml 2023-06-19 13:39:48 +05:30
Jai A P
a8b84d158f Update build.yml 2023-06-19 13:34:31 +05:30
Jai A P
4d9486e6c1 Update build.yml 2023-06-19 13:19:21 +05:30
158 changed files with 6549 additions and 13322 deletions

View File

@@ -1184,60 +1184,6 @@
"contributions": [
"code"
]
},
{
"login": "qyecst",
"name": "qyecst",
"avatar_url": "https://avatars.githubusercontent.com/u/13901864?v=4",
"profile": "https://github.com/qyecst",
"contributions": [
"code"
]
},
{
"login": "DehanLUO",
"name": "Han",
"avatar_url": "https://avatars.githubusercontent.com/u/53093688?v=4",
"profile": "https://github.com/DehanLUO",
"contributions": [
"code"
]
},
{
"login": "wljince007",
"name": "wljince007",
"avatar_url": "https://avatars.githubusercontent.com/u/88243938?v=4",
"profile": "https://github.com/wljince007",
"contributions": [
"code"
]
},
{
"login": "FeroTheFox",
"name": "fero",
"avatar_url": "https://avatars.githubusercontent.com/u/52982404?v=4",
"profile": "https://github.com/FeroTheFox",
"contributions": [
"code"
]
},
{
"login": "siebsie23",
"name": "Sibren",
"avatar_url": "https://avatars.githubusercontent.com/u/25083973?v=4",
"profile": "https://siebsie23.nl/",
"contributions": [
"code"
]
},
{
"login": "nwalser",
"name": "Nathaniel Walser",
"avatar_url": "https://avatars.githubusercontent.com/u/33339996?v=4",
"profile": "https://www.nathaniel-walser.com",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
@@ -1246,6 +1192,5 @@
"repoType": "github",
"repoHost": "https://github.com",
"commitConvention": "none",
"skipCi": true,
"commitType": "docs"
"skipCi": true
}

1
.env
View File

@@ -1 +0,0 @@
# TABBY_CONFIG_DIRECTORY="PATH_TO_DIRECTORY"

View File

@@ -1,13 +1,7 @@
settings:
import/parsers:
'@typescript-eslint/parser': ['.ts']
import/resolver:
typescript:
project:
- tsconfig.json
- tabby-*/tsconfig.json
typescript: true
node: true
env:
browser: true
es6: true
@@ -34,7 +28,7 @@ overrides:
- plugin:import/typescript
plugins:
- '@typescript-eslint'
- import
- 'import'
rules:
'@typescript-eslint/semi':
- error
@@ -136,7 +130,6 @@ overrides:
'@typescript-eslint/naming-convention': off
'@typescript-eslint/lines-between-class-members':
- error
- always
- exceptAfterSingleLine: true
'@typescript-eslint/dot-notation': off
'@typescript-eslint/no-implicit-any-catch': off
@@ -159,6 +152,3 @@ overrides:
'@typescript-eslint/consistent-generic-constructors': off
'keyword-spacing': off
'@typescript-eslint/keyword-spacing': off
'@typescript-eslint/class-methods-use-this': off
'@typescript-eslint/lines-around-comment': off
'@typescript-eslint/no-redundant-type-constituents': off # broken

View File

@@ -11,7 +11,7 @@ jobs:
fetch-depth: 0
- name: Installing Node
uses: actions/setup-node@v3.7.0
uses: actions/setup-node@v3.6.0
with:
node-version: 16
@@ -47,7 +47,7 @@ jobs:
fetch-depth: 0
- name: Installing Node
uses: actions/setup-node@v3.7.0
uses: actions/setup-node@v3.6.0
with:
node-version: 16
@@ -86,7 +86,6 @@ jobs:
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
USE_HARD_LINKS: false
@@ -110,16 +109,16 @@ jobs:
- name: Package artifacts
run: |
mkdir artifact-dmg
mv dist/*.dmg artifact-dmg/
mkdir artifact-pkg
mv dist/*.pkg artifact-pkg/
mkdir artifact-zip
mv dist/*.zip artifact-zip/
- uses: actions/upload-artifact@master
name: Upload DMG
name: Upload PKG
with:
name: macOS .dmg (${{matrix.arch}})
path: artifact-dmg
name: macOS .pkg (${{matrix.arch}})
path: artifact-pkg
- uses: actions/upload-artifact@master
name: Upload ZIP
@@ -132,21 +131,7 @@ jobs:
needs: Lint
strategy:
matrix:
include:
- build-arch: x64
arch: amd64
- build-arch: arm64
arch: arm64
triplet: aarch64-linux-gnu-
- build-arch: arm
arch: armhf
triplet: arm-linux-gnueabihf-
env:
CC: ${{matrix.triplet}}gcc
CXX: ${{matrix.triplet}}g++
ARCH: ${{matrix.build-arch}}
npm_config_arch: ${{matrix.build-arch}}
npm_config_target_arch: ${{matrix.build-arch}}
build-arch: [ x64, arm64, armv7l ]
steps:
- name: Checkout
@@ -154,66 +139,35 @@ jobs:
with:
fetch-depth: 0
- name: Install Node
uses: actions/setup-node@v3.7.0
with:
node-version: 18
- name: Set up multiarch/qemu-user-static
run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
if: matrix.build-arch != 'x64'
- name: Install deps (amd64)
- name: Install Node (x64)
uses: actions/setup-node@v3.6.0
with:
node-version: 16
if: matrix.build-arch == 'x64'
- name: Install deps (x64)
run: |
sudo apt-get update
sudo apt-get install libarchive-tools zsh
- name: Install npm_modules (amd64)
run: |
npm i -g yarn
yarn --network-timeout 1000000
if: matrix.build-arch == 'x64'
- name: Setup Crossbuild (${{matrix.arch}})
run: |
sudo apt-get update -y && sudo apt-get install schroot sbuild debootstrap -y
sudo debootstrap --include=git,curl,gnupg,ca-certificates,crossbuild-essential-${{matrix.arch}},python-dev,python3-dev,libarchive-tools,cmake --variant=buildd --exclude=snapd --components=main,restricted,universe,multiverse --extractor=dpkg-deb bionic /build-chroot/
echo 'deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu bionic main restricted universe multiverse' | sudo tee /build-chroot/etc/apt/sources.list >/dev/null
echo 'deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports bionic main restricted universe multiverse' | sudo tee -a /build-chroot/etc/apt/sources.list >/dev/null
curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor | sudo tee /build-chroot/etc/apt/trusted.gpg.d/nodesource.gpg >/dev/null
echo 'deb http://deb.nodesource.com/node_16.x bionic main' | sudo tee /build-chroot/etc/apt/sources.list.d/nodesource.list >/dev/null
echo "[build-chroot]
description=Ubuntu 18.04 Build chroot
type=directory
directory=/build-chroot
root-groups=root,sudo
profile=buildd
personality=linux
union-type=overlay" | sudo tee /etc/schroot/chroot.d/build-chroot.pref >/dev/null
echo "/home /home none rw,bind 0 0" | sudo tee -a /etc/schroot/buildd/fstab >/dev/null
- name: Webpack (x64)
run: yarn run build
if: matrix.build-arch == 'x64'
if: matrix.build-arch != 'x64'
- name: Install node_modules & CrossBuild native modules for ${{matrix.arch}}
run: |
sudo schroot -c build-chroot -u root -- bash -c "apt-get update -y
dpkg --add-architecture ${{matrix.arch}}
apt-get install -y nodejs libfontconfig-dev:${{matrix.arch}} libsecret-1-dev:${{matrix.arch}} libnss3:${{matrix.arch}} libatk1.0-0:${{matrix.arch}} libatk-bridge2.0-0:${{matrix.arch}} libgdk-pixbuf2.0-0:${{matrix.arch}} libgtk-3-0:${{matrix.arch}} libgbm1:${{matrix.arch}}
export CC=${{matrix.triplet}}gcc CXX=${{matrix.triplet}}g++ LD=${{matrix.triplet}}ld
if [[ ${{matrix.arch}} == 'arm64' ]]; then
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/aarch64-linux-gnu/pkgconfig/
elif [[ ${{matrix.arch}} == 'armhf' ]]; then
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/arm-linux-gnueabihf/pkgconfig/
fi
export ARCH=${{matrix.build-arch}} npm_config_arch=${{matrix.build-arch}} npm_config_target_arch=${{matrix.build-arch}}
npm i -g yarn
yarn --network-timeout 1000000 --arch=${{matrix.build-arch}} --target_arch=${{matrix.build-arch}}"
if: matrix.build-arch != 'x64'
- name: Webpack (${{matrix.arch}})
run: yarn run build --arch=${{matrix.build-arch}} --target_arch=${{matrix.build-arch}}
- name: Prepackage plugins (${{matrix.arch}})
- name: Prepackage plugins (x64)
run: scripts/prepackage-plugins.mjs
if: ${{matrix.build-arch == 'x64'}}
- name: Build packages (${{matrix.arch}})
- name: Build packages (x64)
run: scripts/build-linux.mjs
if: ${{matrix.build-arch == 'x64'}}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
@@ -224,54 +178,54 @@ jobs:
run: zsh -c 'tar czf tabby-web.tar.gz (tabby-*|web)/dist'
if: matrix.build-arch == 'x64'
# - name: Install deps and Build (arm64)
# uses: docker://multiarch/ubuntu-core:arm64-bionic
# with:
# args: >
# bash -c
# "apt update && apt install curl lsb-release gnupg -y &&
# curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&
# apt install make build-essential git ruby libarchive-tools nodejs rpm libsecret-1-dev libfontconfig1-dev -y &&
# git config --global --add safe.directory /github/workspace &&
# gem install public_suffix -v 4.0.7 &&
# gem install fpm --no-document &&
# npm i -g yarn &&
# cd /github/workspace &&
# yarn --network-timeout 1000000 &&
# yarn run build &&
# scripts/prepackage-plugins.mjs &&
# USE_SYSTEM_FPM=true scripts/build-linux.mjs"
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
# USE_HARD_LINKS: false
# if: matrix.build-arch == 'arm64' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
- name: Install deps and Build (arm64)
uses: docker://multiarch/ubuntu-core:arm64-bionic
with:
args: >
bash -c
"apt update && apt install curl lsb-release gnupg -y &&
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&
apt install make build-essential git ruby libarchive-tools nodejs rpm libsecret-1-dev libfontconfig1-dev -y &&
git config --global --add safe.directory /github/workspace &&
gem install public_suffix -v 4.0.7 &&
gem install fpm --no-document &&
npm i -g yarn &&
cd /github/workspace &&
yarn --network-timeout 1000000 &&
yarn run build &&
scripts/prepackage-plugins.mjs &&
USE_SYSTEM_FPM=true scripts/build-linux.mjs"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
USE_HARD_LINKS: false
if: matrix.build-arch == 'arm64' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
# - name: Install deps and Build (armv7l)
# uses: docker://multiarch/ubuntu-core:armhf-bionic
# with:
# args: >
# bash -c
# "apt update && apt install curl lsb-release gnupg -y &&
# curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&
# apt install make build-essential git ruby libarchive-tools nodejs rpm libsecret-1-dev libfontconfig1-dev -y &&
# git config --global --add safe.directory /github/workspace &&
# gem install public_suffix -v 4.0.7 &&
# gem install fpm --no-document &&
# npm i -g yarn &&
# cd /github/workspace &&
# sed -i '/ \"electron\":/c\ \"electron\": \"17.0.0\",' package.json &&
# yarn --network-timeout 1000000 &&
# yarn run build &&
# scripts/prepackage-plugins.mjs &&
# USE_SYSTEM_FPM=true scripts/build-linux.mjs"
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
# USE_HARD_LINKS: false
# if: matrix.build-arch == 'arm' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
- name: Install deps and Build (armv7l)
uses: docker://multiarch/ubuntu-core:armhf-bionic
with:
args: >
bash -c
"apt update && apt install curl lsb-release gnupg -y &&
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&
apt install make build-essential git ruby libarchive-tools nodejs rpm libsecret-1-dev libfontconfig1-dev -y &&
git config --global --add safe.directory /github/workspace &&
gem install public_suffix -v 4.0.7 &&
gem install fpm --no-document &&
npm i -g yarn &&
cd /github/workspace &&
sed -i '/ \"electron\":/c\ \"electron\": \"17.0.0\",' package.json &&
yarn --network-timeout 1000000 &&
yarn run build &&
scripts/prepackage-plugins.mjs &&
USE_SYSTEM_FPM=true scripts/build-linux.mjs"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
USE_HARD_LINKS: false
if: matrix.build-arch == 'armv7l' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
- name: Upload symbols (amd64 only)
- name: Upload symbols
run: |
sudo npm install -g @sentry/cli --unsafe-perm
./scripts/sentry-upload.mjs
@@ -291,37 +245,31 @@ jobs:
dir: 'dist'
- uses: actions/upload-artifact@master
name: Upload AppImage (${{matrix.arch}})
name: Upload DEB
with:
name: Linux AppImage (${{matrix.arch}})
path: dist/*.AppImage
- uses: actions/upload-artifact@master
name: Upload DEB (${{matrix.arch}})
with:
name: Linux DEB (${{matrix.arch}})
name: Linux DEB (${{matrix.build-arch}})
path: dist/*.deb
- uses: actions/upload-artifact@master
name: Upload RPM (${{matrix.arch}})
name: Upload RPM
with:
name: Linux RPM (${{matrix.arch}})
name: Linux RPM (${{matrix.build-arch}})
path: dist/*.rpm
- uses: actions/upload-artifact@master
name: Upload Pacman Package (${{matrix.arch}})
name: Upload Pacman Package
with:
name: Linux Pacman (${{matrix.arch}})
name: Linux Pacman (${{matrix.build-arch}})
path: dist/*.pacman
- uses: actions/upload-artifact@master
name: Upload Linux tarball (${{matrix.arch}})
name: Upload Linux tarball
with:
name: Linux tarball (${{matrix.arch}})
name: Linux tarball (${{matrix.build-arch}})
path: dist/*.tar.gz
- uses: actions/upload-artifact@master
name: Upload web tarball (amd64 only)
name: Upload web tarball
with:
name: Web tarball
path: tabby-web.tar.gz
@@ -345,7 +293,7 @@ jobs:
fetch-depth: 0
- name: Installing Node
uses: actions/setup-node@v3.7.0
uses: actions/setup-node@v3.6.0
with:
node-version: 16

View File

@@ -12,7 +12,7 @@ jobs:
fetch-depth: 0
- name: Installing Node
uses: actions/setup-node@v3.7.0
uses: actions/setup-node@v3.6.0
with:
node-version: 16

View File

@@ -17,6 +17,8 @@ First, from within the `tabby` directory install the dependencies via yarn:
yarn
```
**Note: For compiling for Linux armv7l, you need to downgrade electron to 17.0.0 in package.json present in root directory of tabby source**
```
# Linux (Debian/Ubuntu here as an example)
sudo apt install libfontconfig-dev libsecret-1-dev libarchive-tools libnss3 libatk1.0-0 libatk-bridge2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libgbm1 cmake

View File

@@ -119,7 +119,6 @@ Plugins und Themen können direkt aus der Ansicht "Einstellungen" in Tabby insta
* [clippy](https://github.com/Eugeny/tabby-clippy) - ein Beispiel-Plugin, das einen die ganze Zeit nervt
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - ermöglicht das Erstellen eigener Workspace-Profile auf Basis der angegebenen Konfiguration
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - öffnet den Standard-Systembrowser mit einem Text, der aus dem Tabby Tab ausgewählt wurde
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
@@ -322,15 +321,6 @@ Dank geht an diese wunderbaren Menschen ([emoji key](https://allcontributors.org
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://stackoverflow.com/users/286204/ranhiru-cooray"><img src="https://avatars.githubusercontent.com/u/2367456?v=4?s=100" width="100px;" alt="Jude Cooray"/><br /><sub><b>Jude Cooray</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Ranhiru" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -120,7 +120,6 @@ Los plugins y los temas se pueden instalar directamente desde la vista de Config
* [clippy](https://github.com/Eugeny/tabby-clippy) - un ejemplo de plugin que te molesta todo el tiempo
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - permite crear perfiles de espacio de trabajo personalizados basados en la configuración dada
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - abre el navegador del sistema por defecto con un texto seleccionado en la pestaña de Tabby's
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
# Temas
@@ -324,14 +323,6 @@ Gracias a estas maravillosas personas ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -120,7 +120,6 @@ Tema dan Plugin bisa langsung di install dari Pengaturan di dalam Tabby.
* [clippy](https://github.com/Eugeny/tabby-clippy) - suatu contoh plugin yang akan mengganggu anda setiap saat
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - memperbolehkan membuat kustom profil workspace dari konfigurasi yang diberikan
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - membuka browser default dengan text yang dipilih dari Tab Tabby
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
@@ -321,14 +320,6 @@ Terima kasih kepada mereka yang telah membantu ([emoji key](https://allcontribut
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -117,7 +117,6 @@ Plugins and themes can be installed directly from the Settings view inside Tabby
* [clippy](https://github.com/Eugeny/tabby-clippy) - an example plugin which annoys you all the time
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - allows creating custom workspace profiles based on the given config
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - opens default system browser with a text selected from the Tabby's tab
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
# Temi
@@ -317,15 +316,6 @@ Grazie a queste persone meravigliose ([emoji key](https://allcontributors.org/do
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://stackoverflow.com/users/286204/ranhiru-cooray"><img src="https://avatars.githubusercontent.com/u/2367456?v=4?s=100" width="100px;" alt="Jude Cooray"/><br /><sub><b>Jude Cooray</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Ranhiru" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -127,7 +127,6 @@ Windows上では、`Tabby.exe`がある場所と同じ場所に`data`フォル
* [clippy](https://github.com/Eugeny/tabby-clippy) - プラグインの作例として、いつも厄介なあいつが出てくるプラグイン
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 指定された設定からカスタマイズされたワークスペースを作成することができます
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - Tabby内の端末で選択したテキストを既定ブラウザで開くことができます。
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
@@ -332,14 +331,6 @@ Windows上では、`Tabby.exe`がある場所と同じ場所に`data`フォル
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -111,7 +111,6 @@
* [clippy](https://github.com/Eugeny/tabby-clippy) - 항상 당신을 귀찮게 하는 예제 플러그인
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 주어진 구성을 기반으로 사용자 정의 작업 공간 프로필을 생성할 수 있습니다
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - Tabby의 탭에서 선택한 텍스트로 기본 시스템 브라우저를 엽니다
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
# 테마
@@ -311,15 +310,6 @@ Pull requests and plugins are welcome!
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://stackoverflow.com/users/286204/ranhiru-cooray"><img src="https://avatars.githubusercontent.com/u/2367456?v=4?s=100" width="100px;" alt="Jude Cooray"/><br /><sub><b>Jude Cooray</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Ranhiru" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -34,7 +34,7 @@ This README is also available in: <a href="./README.es-ES.md">:es: Spanish</a>
----
[**Tabby**](https://tabby.sh) (formerly **Terminus**) is a highly configurable terminal emulator, SSH and serial client for Windows 10, macOS and Linux
[**Tabby**](https://tabby.sh) (formerly **Terminus**) is a highly configurable terminal emulator, SSH and serial client for Windows, macOS and Linux
* Integrated SSH and Telnet client and connection manager
* Integrated serial terminal
@@ -128,7 +128,6 @@ Plugins and themes can be installed directly from the Settings view inside Tabby
* [clippy](https://github.com/Eugeny/tabby-clippy) - an example plugin which annoys you all the time
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - allows creating custom workspace profiles based on the given config
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - opens default system browser with a text selected from the Tabby's tab
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
@@ -139,7 +138,6 @@ Plugins and themes can be installed directly from the Settings view inside Tabby
* [gruvbox](https://github.com/porkloin/terminus-theme-gruvbox)
* [windows10](https://www.npmjs.com/package/terminus-theme-windows10)
* [altair](https://github.com/yxuko/terminus-altair)
* [catppuccin](https://github.com/catppuccin/tabby) - Soothing pastel theme for Tabby
# Sponsors <!-- omit in toc -->
@@ -334,15 +332,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://stackoverflow.com/users/286204/ranhiru-cooray"><img src="https://avatars.githubusercontent.com/u/2367456?v=4?s=100" width="100px;" alt="Jude Cooray"/><br /><sub><b>Jude Cooray</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Ranhiru" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -120,7 +120,6 @@ Plugins e temas podem ser instalados durante a execução na pagina de configura
* [clippy](https://github.com/Eugeny/tabby-clippy) - um plugin de exemplo que te incomoda o tempo todo
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - permite criar perfis de espaço de trabalho personalizados com base na configuração fornecida
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - abre o navegador padrão do sistema com um texto selecionado na guia do Tabby
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
@@ -325,14 +324,6 @@ Obrigado vai para essas pessoas maravilhosas ([emoji key](https://allcontributor
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -117,7 +117,6 @@
* [clippy](https://github.com/Eugeny/tabby-clippy) — плагин-пример, который постоянно будет вас бесить;
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) — позволяет создавать пользовательские провили рабочего окружеиня на основе конфига;
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) — открывает браузер по умолчанию с текстом, выделенном во вкладке Tabby.
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - open sftp tab for ssh connection like SecureCRT
<a name="themes"></a>
# Темы
@@ -317,15 +316,6 @@ Pull-запросы и плагины приветствуются!
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://stackoverflow.com/users/286204/ranhiru-cooray"><img src="https://avatars.githubusercontent.com/u/2367456?v=4?s=100" width="100px;" alt="Jude Cooray"/><br /><sub><b>Jude Cooray</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Ranhiru" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -116,7 +116,6 @@
* [clippy](https://github.com/Eugeny/tabby-clippy) - 一个可以一直烦你的示例插件
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 允许根据给定的配置创建自定义工作区配置文件
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - 从 Tabby 标签页带有选中的文本来打开系统默认浏览器
* [sftp-tab](https://github.com/wljince007/tabby-sftp-tab) - 为ssh连接打开类似SecureCRT的sftp标签页
<a name="themes"></a>
# 主题
@@ -316,15 +315,6 @@
<td align="center" valign="top" width="14.28%"><a href="http://kapocsi.ca"><img src="https://avatars.githubusercontent.com/u/84490604?v=4?s=100" width="100px;" alt="Thomas Kapocsi"/><br /><sub><b>Thomas Kapocsi</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Kapocsi" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dylhack.dev/"><img src="https://avatars.githubusercontent.com/u/27179786?v=4?s=100" width="100px;" alt="Dylan Hackworth"/><br /><sub><b>Dylan Hackworth</b></sub></a><br /><a href="#financial-dylhack" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/echo304"><img src="https://avatars.githubusercontent.com/u/16456651?v=4?s=100" width="100px;" alt="Sangboak Lee"/><br /><sub><b>Sangboak Lee</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=echo304" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/qyecst"><img src="https://avatars.githubusercontent.com/u/13901864?v=4?s=100" width="100px;" alt="qyecst"/><br /><sub><b>qyecst</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=qyecst" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DehanLUO"><img src="https://avatars.githubusercontent.com/u/53093688?v=4?s=100" width="100px;" alt="Han"/><br /><sub><b>Han</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=DehanLUO" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wljince007"><img src="https://avatars.githubusercontent.com/u/88243938?v=4?s=100" width="100px;" alt="wljince007"/><br /><sub><b>wljince007</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=wljince007" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FeroTheFox"><img src="https://avatars.githubusercontent.com/u/52982404?v=4?s=100" width="100px;" alt="fero"/><br /><sub><b>fero</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=FeroTheFox" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://siebsie23.nl/"><img src="https://avatars.githubusercontent.com/u/25083973?v=4?s=100" width="100px;" alt="Sibren"/><br /><sub><b>Sibren</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=siebsie23" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.nathaniel-walser.com"><img src="https://avatars.githubusercontent.com/u/33339996?v=4?s=100" width="100px;" alt="Nathaniel Walser"/><br /><sub><b>Nathaniel Walser</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=nwalser" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://stackoverflow.com/users/286204/ranhiru-cooray"><img src="https://avatars.githubusercontent.com/u/2367456?v=4?s=100" width="100px;" alt="Jude Cooray"/><br /><sub><b>Jude Cooray</b></sub></a><br /><a href="https://github.com/Eugeny/tabby/commits?author=Ranhiru" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@@ -183,7 +183,7 @@ export class Application {
}
enableTray (): void {
if (!!this.tray || process.platform === 'linux') {
if (this.tray || process.platform === 'linux') {
return
}
if (process.platform === 'darwin') {

View File

@@ -1,14 +1,13 @@
import * as fs from 'fs'
import * as path from 'path'
import * as yaml from 'js-yaml'
import { app } from 'electron'
import { writeFile } from 'atomically'
export const configPath = path.join(process.env.TABBY_CONFIG_DIRECTORY!, 'config.yaml')
const legacyConfigPath = path.join(process.env.TABBY_CONFIG_DIRECTORY!, '../terminus', 'config.yaml')
export function migrateConfig (): void {
const configPath = path.join(app.getPath('userData'), 'config.yaml')
const legacyConfigPath = path.join(app.getPath('userData'), '../terminus', 'config.yaml')
if (fs.existsSync(legacyConfigPath) && (
!fs.existsSync(configPath) ||
fs.statSync(configPath).mtime < fs.statSync(legacyConfigPath).mtime
@@ -20,6 +19,7 @@ export function migrateConfig (): void {
export function loadConfig (): any {
migrateConfig()
const configPath = path.join(app.getPath('userData'), 'config.yaml')
if (fs.existsSync(configPath)) {
return yaml.load(fs.readFileSync(configPath, 'utf8'))
} else {
@@ -27,6 +27,8 @@ export function loadConfig (): any {
}
}
const configPath = path.join(app.getPath('userData'), 'config.yaml')
export async function saveConfig (content: string): Promise<void> {
await writeFile(configPath, content, { encoding: 'utf8' })
await writeFile(configPath + '.backup', content, { encoding: 'utf8' })

View File

@@ -1,21 +1,17 @@
import { app, ipcMain, Menu, dialog } from 'electron'
// set defaults of environment variables
import 'dotenv/config'
process.env.TABBY_PLUGINS ??= ''
process.env.TABBY_CONFIG_DIRECTORY ??= app.getPath('userData')
import 'v8-compile-cache'
import './portable'
import 'source-map-support/register'
import './sentry'
import './lru'
import { app, ipcMain, Menu, dialog } from 'electron'
import { parseArgs } from './cli'
import { Application } from './app'
import electronDebug = require('electron-debug')
import { loadConfig } from './config'
if (!process.env.TABBY_PLUGINS) {
process.env.TABBY_PLUGINS = ''
}
const argv = parseArgs(process.argv, process.cwd())

View File

@@ -1,4 +1,4 @@
import * as nodePTY from 'node-pty'
import * as nodePTY from '@tabby-gang/node-pty'
import { v4 as uuidv4 } from 'uuid'
import { ipcMain } from 'electron'
import { Application } from './app'

View File

@@ -92,11 +92,8 @@ export class Window {
if (this.configStore.appearance?.frame === 'native') {
bwOptions.frame = true
} else {
bwOptions.titleBarStyle = 'hidden'
if (process.platform === 'win32') {
bwOptions.titleBarOverlay = {
color: '#00000000',
}
if (process.platform === 'darwin') {
bwOptions.titleBarStyle = 'hidden'
}
}
@@ -387,22 +384,6 @@ export class Window {
this.setVibrancy(enabled, type)
})
ipcMain.on('window-set-window-controls-color', (event, theme) => {
if (!this.window || event.sender !== this.window.webContents) {
return
}
if (process.platform === 'win32') {
const symbolColor: string = theme.foreground
this.window.setTitleBarOverlay(
{
symbolColor: symbolColor,
height: 32,
},
)
}
})
ipcMain.on('window-set-title', (event, title) => {
if (!this.window || event.sender !== this.window.webContents) {
return
@@ -461,7 +442,7 @@ export class Window {
this.window.on('resize', onBoundsChange)
ipcMain.on('window-set-traffic-light-position', (_event, x, y) => {
this.window.setWindowButtonPosition({ x, y })
this.window.setTrafficLightPosition({ x, y })
})
ipcMain.on('window-set-opacity', (_event, opacity) => {

View File

@@ -16,7 +16,7 @@
},
"dependencies": {
"@electron/remote": "2.0.10",
"node-pty": "^1.0",
"@tabby-gang/node-pty": "^0.11.0-beta.203",
"any-promise": "^1.3.0",
"electron-config": "2.0.0",
"electron-debug": "^3.2.0",
@@ -38,7 +38,7 @@
"@tabby-gang/windows-blurbehind": "^3.0.0",
"macos-native-processlist": "^2.1.0",
"patch-package": "^6.5.0",
"serialport": "11.0.1",
"serialport": "11.0.0",
"serialport-binding-webserialapi": "^1.0.3",
"windows-native-registry": "^3.2.1",
"windows-process-tree": "^0.4.0"
@@ -47,7 +47,7 @@
"@ngx-translate/core": "^14.0.0",
"@types/mz": "2.7.4",
"@types/node": "20.3.1",
"atomically": "^2.0.2",
"atomically": "^1.7.0",
"filesize": "^9",
"ngx-filesize": "^3.0.2"
},

View File

@@ -47,7 +47,7 @@ const config = {
mz: 'commonjs mz',
npm: 'commonjs npm',
'node:os': 'commonjs os',
'node-pty': 'commonjs node-pty',
'@tabby-gang/node-pty': 'commonjs @tabby-gang/node-pty',
path: 'commonjs path',
util: 'commonjs util',
'source-map-support': 'commonjs source-map-support',

View File

@@ -38,13 +38,13 @@
"@serialport/bindings-interface" "^1.2.1"
debug "^4.3.3"
"@serialport/bindings-cpp@11.0.3":
version "11.0.3"
resolved "https://registry.yarnpkg.com/@serialport/bindings-cpp/-/bindings-cpp-11.0.3.tgz#ab4d4826ef657e326b6c99d6b8a113d834378a93"
integrity sha512-xgNDJ7pHHZCJMoDsEH+D8q5CV+V3RGN4/jLEG9SQ7q6kh+o03axV0l/upPHZ0HW4tTXpGgqPIGbXOTrD4RGQQA==
"@serialport/bindings-cpp@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/bindings-cpp/-/bindings-cpp-11.0.1.tgz#38afa6105ceb7888c6a2af2782822fca9130d65a"
integrity sha512-3I1mniVg3osYuIUXxU0jB5AHPsxWmErmc3JC3WfUSlfXsjWMHkHfFzbW9Scuv/z/6DLCJIDyltabRa2FoW2qsQ==
dependencies:
"@serialport/bindings-interface" "1.2.2"
"@serialport/parser-readline" "11.0.0"
"@serialport/parser-readline" "10.5.0"
debug "4.3.4"
node-addon-api "6.1.0"
node-gyp-build "4.6.0"
@@ -59,35 +59,42 @@
resolved "https://registry.yarnpkg.com/@serialport/bindings-interface/-/bindings-interface-1.2.1.tgz#1ee80b0951ef4e4fd8a5a186621feff046aa2faf"
integrity sha512-63Dyqz2gtryRDDckFusOYqLYhR3Hq/M4sEdbF9i/VsvDb6T+tNVgoAKUZ+FMrXXKnCSu+hYbk+MTc0XQANszxw==
"@serialport/parser-byte-length@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-11.0.1.tgz#26e4f3b2d66aaac0859b18a57c648d0eec78392a"
integrity sha512-UsffR5b3NHwhjJzsWv5fZMkoq3wGNyUcRTA9jlu02w+2kMlBRJPzlPVB5szVX0VWUEqkCg+3VaU2XWuYr+uAUA==
"@serialport/parser-byte-length@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-11.0.0.tgz#074e6ed6b18d7a61edc75dba22d3115e8f37dd8c"
integrity sha512-rExsdFKdzOIHOBqTwzxUF1A9nrluVIZKZOtvMq5i0Hc3euooGdmkx0VXYNRlI2rd6kJLTL2P+uIR+ZtCTRyT+w==
"@serialport/parser-cctalk@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-11.0.1.tgz#70c5ccc8fc5ebbe5c317005791155d3b2812efa6"
integrity sha512-klzVQfRcC1m0SVDV2Dy9hHfwweO2/mUMUyuXK04FRkKHy5/AdETmk9KTVVVVfpDCSysvHoyQPwiDFq8ddwX3cQ==
"@serialport/parser-cctalk@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-11.0.0.tgz#6a5e2b299e8f1ef00308980e45ecdae23825181e"
integrity sha512-eN1MvEIFwI4GedWJhte6eWF+NZtrjchZbMf0CE6NV9TRzJI1KLnFf90ZOj/mhGuANojX4sqWfJKQXwN6E8VSHQ==
"@serialport/parser-delimiter@10.5.0":
version "10.5.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-10.5.0.tgz#b0d93100cdfd0619d020a427d652495073f3b828"
integrity sha512-/uR/yT3jmrcwnl2FJU/2ySvwgo5+XpksDUR4NF/nwTS5i3CcuKS+FKi/tLzy1k8F+rCx5JzpiK+koqPqOUWArA==
"@serialport/parser-delimiter@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-11.0.0.tgz#e830c6bb49723d4446131277dc3243b502d09388"
integrity sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==
"@serialport/parser-delimiter@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-11.0.1.tgz#c0bcc24d8060c6b352cbe6003ebe95671ad32221"
integrity sha512-NAsYa3OFt2xEnj/+0BRkQP2qkRNbXBPEq6uFJEdNdzcTSF+BTRXkoIRrWBq3N6koovPqW6lnbxc/iJYe5AX/2Q==
"@serialport/parser-inter-byte-timeout@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-11.0.0.tgz#baf7223bf3d49d159c82386928c763bfecf8f70f"
integrity sha512-RLgqZC50IET6FtEIt6Oi0vdRsesSBWLNwB7ldzR9OzyXKgK0XHRzqKqbB0u5Q+tC5OScdWeiQ2AO6jooKUZtsw==
"@serialport/parser-inter-byte-timeout@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-11.0.1.tgz#ed6d939eeb3bec94579fb3628dc6dcd0c9a3dd21"
integrity sha512-PEFV9dSpW+ptH1rLhdB9KgE+rbJ/FvQiZz0mx+4jkv/Po4g3PNsEEMXfMW0aQVSFVsmitvmE0jHlhGjLv8GQEg==
"@serialport/parser-packet-length@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-packet-length/-/parser-packet-length-11.0.0.tgz#ec06934b40b45b8f5eb04ba5527e98a1062c2a20"
integrity sha512-6ZkOiaCooabpV/EM7ttSRbisbDWpGEf7Yxyr13t28LicYR43THRdjdMZcRnWxEM/jpwfskkLLXAR6wziVpKrlw==
"@serialport/parser-packet-length@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-packet-length/-/parser-packet-length-11.0.1.tgz#9d7982a6eeaf9a5bdfe642ceb287f171ab2965b7"
integrity sha512-KwPu8dsAI+eN4fnUS1vVmrOpUtBK4p9L9cHhwn5ZmfcvwvZMHp/J+IEu7xH0g5aM1/8QEoaql26BQP+sZ71NQQ==
"@serialport/parser-readline@10.5.0":
version "10.5.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-10.5.0.tgz#df23365ae7f45679b1735deae26f72ba42802862"
integrity sha512-0aXJknodcl94W9zSjvU+sLdXiyEG2rqjQmvBWZCr8wJZjWEtv3RgrnYiWq4i2OTOyC8C/oPK8ZjpBjQptRsoJQ==
dependencies:
"@serialport/parser-delimiter" "10.5.0"
"@serialport/parser-readline@11.0.0":
version "11.0.0"
@@ -96,37 +103,30 @@
dependencies:
"@serialport/parser-delimiter" "11.0.0"
"@serialport/parser-readline@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-11.0.1.tgz#e85805ae803c2dc507eefa390abec6a67ceef313"
integrity sha512-wkJ3EI733+yhbi7eBWzs/qn8+cfIBcYQjfrILPNqslAy6VlgdKw+pHoblDFmg78GN0TqGUDSWlTJ65oLEPVp5Q==
dependencies:
"@serialport/parser-delimiter" "11.0.1"
"@serialport/parser-ready@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-11.0.0.tgz#802e7189d9e5d13df70d3aa1559403b72fcfa700"
integrity sha512-lSsCPIctoc5kADCKnZDYBz1j69TsFqtnaWUicBzUAIAoUXpYKeYld8YX5NrvjViuVfIJeiqLZeGjxOWe5fqQqQ==
"@serialport/parser-ready@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-11.0.1.tgz#bba01283a121880641e43c27193e6708fef2907c"
integrity sha512-v/bvlgKhrNt+SVLSqlfXCO1HEinfRRMGnzqbpdVCgu2SiWIEenCLjs51JisKVYQoQFcXdP/EHZnzm7NPXHDlAg==
"@serialport/parser-regex@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-11.0.0.tgz#bb247297851b1a789f4dde1c4ad48c39d6db7ed6"
integrity sha512-aKuc/+/KE9swahTbYpSuOsQa7LggPx7jhfobJLPVVbAic80OpfCIY+MKr6Ax4R6UtQwF90O5Yk6OEmbbvtEmiA==
"@serialport/parser-regex@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-11.0.1.tgz#7833ca6029c8c58eb39dd6fe984756cf09d769b7"
integrity sha512-Lf3k7qibYqZ0+/wX3UA8fRng3WtQ+UyLpjQhG1COs6OBSq5/I5tYXczfhlrbA0gHo1qzgzr2V2t7m6FoBSc81Q==
"@serialport/parser-slip-encoder@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-slip-encoder/-/parser-slip-encoder-11.0.0.tgz#f1c3f56e04c497ca89059c69ea79411b30e8da60"
integrity sha512-3ZI/swd2it20vmu2tzqDbkyE4dqy+kExEDY6T33YQ210HDKPVhqj7FAVGo5P++MZ3dup1of11t4P9UPBNkuJnQ==
"@serialport/parser-slip-encoder@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-slip-encoder/-/parser-slip-encoder-11.0.1.tgz#4ba0c335627e3d1203279a5f8a4c1af0c829b7fe"
integrity sha512-l4mXsAGzpmPO7+uqKJqtPDW643irfnGEWbiy34FoYvuOs8n0SmiMtgQZFAtvlTNQCRWE2tykF/WG6K/McJthDw==
"@serialport/parser-spacepacket@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/parser-spacepacket/-/parser-spacepacket-11.0.0.tgz#7737aaa1397db4bf820160dd2f7dd0c9df5f74a0"
integrity sha512-+hqRckrTEqz+/uAUZY0Tq6YIRyCl4oQOH1MeVzKiFiGNjZP7hDJCDoY7LTr9CeJhxvcT0ItTbtjGBqGumV8fxg==
"@serialport/parser-spacepacket@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/parser-spacepacket/-/parser-spacepacket-11.0.1.tgz#9e1c372f45433afb9a5dbec7b5a298c710b0455b"
integrity sha512-Lq7fXoOsLOMo4XEt9HB31zV5LhrteXlsOy2o6r39TfRwU6x8Nou9jQMA9vW0a6yPra5zwsHIaNrA6tDOGj2Ozg==
"@serialport/stream@11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-11.0.1.tgz#ed40c66d517cfebf7185cd9c37ba0a08e76f88b2"
integrity sha512-6pjyKRg8MQuvhGfg36+PF7K5eGNQcEswCSiAg1UPilqqFS8X1QnaiSCn5UFp/hCN+pAtlFjkOi0ztvtmSI7n4g==
"@serialport/stream@11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-11.0.0.tgz#9887db096b51fabe1919a591b920b06f7580e8ee"
integrity sha512-Zty7B8C1H2XRnay2mVmW1ygEHXRHXQDcaC5wAVvOZMbQSc7ye03rMlPvviDS+pGxU2t2A2bMo34CUrRduSBong==
dependencies:
"@serialport/bindings-interface" "1.2.2"
debug "4.3.4"
@@ -138,6 +138,13 @@
dependencies:
debug "^4.3.2"
"@tabby-gang/node-pty@^0.11.0-beta.203":
version "0.11.0-beta.204"
resolved "https://registry.yarnpkg.com/@tabby-gang/node-pty/-/node-pty-0.11.0-beta.204.tgz#80d4393c7a233d3298f47a4755467a246b0099f9"
integrity sha512-sNT5Z2MEkEIhToAdVAdZ/lfeQ9UgFE3h2ENlOux+WHBrl1k0BiUEIOd/jh/K3mNAGEfcZ44gNQQ50g5KXTQEmA==
dependencies:
nan "^2.16.0"
"@tabby-gang/windows-blurbehind@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@tabby-gang/windows-blurbehind/-/windows-blurbehind-3.0.0.tgz#48d409c2eb14a12c867b70de5ee4d6769ef45e8f"
@@ -327,13 +334,10 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
atomically@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/atomically/-/atomically-2.0.2.tgz#e5a6e8021441405b7a1c36d4587e25f7a13545f2"
integrity sha512-Xfmb4q5QV7uqTlVdMSTtO5eF4DCHfNOdaPyKlbFShkzeNP+3lj3yjjcbdjSmEY4+pDBKJ9g26aP+ImTe88UHoQ==
dependencies:
stubborn-fs "^1.2.5"
when-exit "^2.0.0"
atomically@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
aws-sign2@~0.7.0:
version "0.7.0"
@@ -2260,7 +2264,7 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nan@^2.17.0, "nan@github:jkleinsc/nan#remove_accessor_signature":
nan@^2.16.0, nan@^2.17.0, "nan@github:jkleinsc/nan#remove_accessor_signature":
version "2.16.0"
resolved "https://codeload.github.com/jkleinsc/nan/tar.gz/6a2f95a6a2209d8aa7542fb18099fd808a802059"
@@ -2348,13 +2352,6 @@ node-gyp@^5.0.2, node-gyp@^5.1.0:
tar "^4.4.12"
which "^1.3.1"
node-pty@^1.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-1.0.0.tgz#7daafc0aca1c4ca3de15c61330373af4af5861fd"
integrity sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA==
dependencies:
nan "^2.17.0"
nopt@^4.0.1, nopt@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
@@ -3302,24 +3299,24 @@ serialport-binding-webserialapi@^1.0.3:
"@serialport/binding-abstract" "^9.0.2"
"@serialport/stream" "^9.0.2"
serialport@11.0.1:
version "11.0.1"
resolved "https://registry.yarnpkg.com/serialport/-/serialport-11.0.1.tgz#9c7aad877d38124a938a50f89eaef22c44825eae"
integrity sha512-j/ntDuewAkqL6g5wKjwV2RTyLBL9cpob8aRd3yLAViYApTsJoYqRleyuzst0OboNTBjBsoxQ4YKYhuYHi1XViQ==
serialport@11.0.0:
version "11.0.0"
resolved "https://registry.yarnpkg.com/serialport/-/serialport-11.0.0.tgz#a4114fc60e91b23f133ec459345b7be637b1e8ef"
integrity sha512-bxs3XejQcOHWpzPAaXMhxVRlbem6fjNUrux3ToqrGvFR6BcjOYhqE5CsHOuutv37kmhmnuHrn+/hN+1BpTmaFg==
dependencies:
"@serialport/binding-mock" "10.2.2"
"@serialport/bindings-cpp" "11.0.3"
"@serialport/parser-byte-length" "11.0.1"
"@serialport/parser-cctalk" "11.0.1"
"@serialport/parser-delimiter" "11.0.1"
"@serialport/parser-inter-byte-timeout" "11.0.1"
"@serialport/parser-packet-length" "11.0.1"
"@serialport/parser-readline" "11.0.1"
"@serialport/parser-ready" "11.0.1"
"@serialport/parser-regex" "11.0.1"
"@serialport/parser-slip-encoder" "11.0.1"
"@serialport/parser-spacepacket" "11.0.1"
"@serialport/stream" "11.0.1"
"@serialport/bindings-cpp" "11.0.1"
"@serialport/parser-byte-length" "11.0.0"
"@serialport/parser-cctalk" "11.0.0"
"@serialport/parser-delimiter" "11.0.0"
"@serialport/parser-inter-byte-timeout" "11.0.0"
"@serialport/parser-packet-length" "11.0.0"
"@serialport/parser-readline" "11.0.0"
"@serialport/parser-ready" "11.0.0"
"@serialport/parser-regex" "11.0.0"
"@serialport/parser-slip-encoder" "11.0.0"
"@serialport/parser-spacepacket" "11.0.0"
"@serialport/stream" "11.0.0"
debug "4.3.4"
set-blocking@^2.0.0, set-blocking@~2.0.0:
@@ -3619,11 +3616,6 @@ strip-json-comments@~2.0.1:
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
stubborn-fs@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/stubborn-fs/-/stubborn-fs-1.2.5.tgz#e5e244223166921ddf66ed5e062b6b3bf285bfd2"
integrity sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -3916,11 +3908,6 @@ wcwidth@^1.0.0:
dependencies:
defaults "^1.0.3"
when-exit@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/when-exit/-/when-exit-2.1.0.tgz#0f7b5d7d5f00ea2c4b131b546c444cca2c4ffba7"
integrity sha512-H85ulNwUBU1e6PGxkWUDgxnbohSXD++ah6Xw1VHAN7CtypcbZaC4aYjQ+C2PMVaDkURDuOinNAT+Lnz3utWXxQ==
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz"

View File

@@ -0,0 +1,16 @@
const fs = require('fs')
const signHook = require('./afterSignHook.cjs')
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,
})
}

View File

@@ -0,0 +1,35 @@
// See: https://medium.com/@TwitterArchiveEraser/notarize-electron-apps-7a5f988406db
const fs = require('fs')
const path = require('path')
const notarizer = require('@electron/notarize')
module.exports = async function (params) {
// notarize the app on Mac OS only.
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
return
}
console.log('afterSign hook triggered', params)
let appId = 'org.tabby'
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}`)
}
console.log(`Notarizing ${appId} found at ${appPath}`)
try {
await notarizer.notarize({
appBundleId: appId,
appPath: appPath,
appleId: process.env.APPSTORE_USERNAME,
appleIdPassword: process.env.APPSTORE_PASSWORD,
})
} catch (error) {
console.error(error)
}
console.log(`Done notarizing ${appId}`)
}

View File

@@ -3,6 +3,8 @@ appId: org.tabby
productName: Tabby
compression: normal
npmRebuild: false
afterSign: "./build/mac/afterSignHook.cjs"
afterAllArtifactBuild: "./build/mac/afterBuildHook.cjs"
files:
- '**/*'
- dist

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -26,8 +26,8 @@
"@types/js-yaml": "^4.0.5",
"@types/node": "20.3.1",
"@types/webpack-env": "^1.18.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.54.1",
"apply-loader": "2.0.0",
"axios": "^1.4.0",
"babel-loader": "^9.1.2",
@@ -39,16 +39,16 @@
"cross-env": "7.0.3",
"css-loader": "^6.7.3",
"deep-equal": "2.0.5",
"electron": "^25.3.0",
"electron": "22.3.1",
"electron-builder": "^24.0.0-alpha.1",
"electron-download": "^4.1.1",
"electron-installer-snap": "^5.1.0",
"electron-rebuild": "^3.2.9",
"eslint": "^8.48.0",
"eslint-import-resolver-typescript": "^3.6.0",
"eslint-plugin-import": "^2.28.1",
"eslint": "^8.38.0",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.27.5",
"file-loader": "^6.2.0",
"gettext-extractor": "^3.8.0",
"gettext-extractor": "^3.5.4",
"graceful-fs": "^4.2.10",
"html-loader": "4.2.0",
"json-loader": "^0.5.7",
@@ -76,7 +76,7 @@
"source-code-pro": "^2.38.0",
"source-map-loader": "^4.0.1",
"source-sans-pro": "3.6.0",
"ssh2": "^1.14.0",
"ssh2": "Eugeny/ssh2#9de907d62907d6d45debdcc0ed8dda5b7b19dc7c",
"style-loader": "^3.3.1",
"svg-inline-loader": "^0.8.2",
"thenby": "^1.3.4",
@@ -95,7 +95,7 @@
},
"resolutions": {
"*/pug": "^3",
"lzma-native": "^8.0.6",
"lzma-native": "^8.0.0",
"*/node-abi": "^3.33.0",
"**/graceful-fs": "^4.2.4",
"nan": "2.17.0"
@@ -115,8 +115,5 @@
"i18n:push": "crowdin push"
},
"type": "module",
"private": true,
"dependencies": {
"dotenv": "^16.3.1"
}
"private": true
}

View File

@@ -1,15 +1,15 @@
diff --git a/node_modules/app-builder-lib/out/appInfo.js b/node_modules/app-builder-lib/out/appInfo.js
index 49f6dca..0ea11f2 100644
index 363f32c..a0434a9 100644
--- a/node_modules/app-builder-lib/out/appInfo.js
+++ b/node_modules/app-builder-lib/out/appInfo.js
@@ -112,9 +112,7 @@ class AppInfo {
@@ -100,9 +100,7 @@ class AppInfo {
return this.info.metadata.name;
}
get linuxPackageName() {
- const name = this.name;
- // https://github.com/electron-userland/electron-builder/issues/2963
- return name.startsWith("@") ? this.sanitizedProductName : name;
+ return 'tabby-terminal';
+ return 'tabby-terminal'
}
get sanitizedName() {
return (0, filename_1.sanitizeFileName)(this.name);
return filename_1.sanitizeFileName(this.name);

View File

@@ -9,7 +9,7 @@ process.env.ARCH = (process.env.ARCH || process.arch) === 'arm' ? 'armv7l' : pro
builder({
dir: true,
linux: ['deb', 'tar.gz', 'rpm', 'pacman', 'appimage'],
linux: ['deb', 'tar.gz', 'rpm', 'pacman'],
armv7l: process.env.ARCH === 'armv7l',
arm64: process.env.ARCH === 'arm64',
config: {

View File

@@ -13,12 +13,9 @@ if (process.env.GITHUB_HEAD_REF) {
process.env.CSC_IDENTITY_AUTO_DISCOVERY = 'false'
}
process.env.APPLE_ID ??= process.env.APPSTORE_USERNAME
process.env.APPLE_APP_SPECIFIC_PASSWORD ??= process.env.APPSTORE_PASSWORD
builder({
dir: true,
mac: ['dmg', 'zip'],
mac: ['pkg', 'zip'],
x64: process.env.ARCH === 'x86_64',
arm64: process.env.ARCH === 'arm64',
config: {
@@ -27,10 +24,6 @@ builder({
},
mac: {
identity: !process.env.CI || process.env.CSC_LINK ? undefined : null,
notarize: process.env.APPLE_TEAM_ID ? {
appBundleId: 'org.tabby',
teamId: process.env.APPLE_TEAM_ID,
} : false,
},
npmRebuild: process.env.ARCH !== 'arm64',
publish: process.env.KEYGEN_TOKEN ? [

View File

@@ -9,7 +9,7 @@ sh.exec(`${sentryCli} releases new ${vars.version}`)
if (process.platform === 'darwin') {
for (const path of [
'app/node_modules/@serialport/bindings/build/Release/bindings.node',
'app/node_modules/node-pty/build/Release/pty.node',
'app/node_modules/@tabby-gang/node-pty/build/Release/pty.node',
'app/node_modules/fontmanager-redux/build/Release/fontmanager.node',
'app/node_modules/macos-native-processlist/build/Release/native.node',
]) {

View File

@@ -3,8 +3,6 @@ import * as fs from 'fs'
import * as semver from 'semver'
import * as childProcess from 'child_process'
process.env.ARCH = ((process.env.ARCH || process.arch) === 'arm') ? 'armv7l' : process.env.ARCH || process.arch
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
@@ -60,21 +58,21 @@ export const keygenConfig = {
win32: {
x64: 'f481b9d6-d5da-4970-b926-f515373e986f',
arm64: '950999b9-371c-419b-b291-938c5e4d364c',
}[process.env.ARCH],
}[process.env.ARCH ?? process.arch],
darwin: {
arm64: '98fbadee-c707-4cd6-9d99-56683595a846',
x86_64: 'f5a48841-d5b8-4b7b-aaa7-cf5bffd36461',
x64: 'f5a48841-d5b8-4b7b-aaa7-cf5bffd36461',
}[process.env.ARCH],
}[process.env.ARCH ?? process.arch],
linux: {
x64: '7bf45071-3031-4a26-9f2e-72604308313e',
arm64: '39e3c736-d4d4-4fbf-a201-324b7bab0d17',
armv7l: '50ae0a82-7f47-4fa4-b0a8-b0d575ce9409',
armhf: '7df5aa12-04ab-4075-a0fe-93b0bbea9643',
}[process.env.ARCH],
}[process.env.ARCH ?? process.arch],
}[process.platform],
}
if (!keygenConfig.product) {
throw new Error(`Unrecognized platform ${process.platform}/${process.env.ARCH}`)
throw new Error(`Unrecognized platform ${process.platform}/${process.env.ARCH ?? process.arch}`)
}

View File

@@ -16,7 +16,7 @@ export { BootstrapData, PluginInfo, BOOTSTRAP_DATA } from './mainProcess'
export { HostWindowService } from './hostWindow'
export { HostAppService, Platform } from './hostApp'
export { FileProvider } from './fileProvider'
export { ProfileProvider, ConnectableProfileProvider, QuickConnectProfileProvider, Profile, ConnectableProfile, PartialProfile, ProfileSettingsComponent, ProfileGroup, PartialProfileGroup } from './profileProvider'
export { ProfileProvider, Profile, PartialProfile, ProfileSettingsComponent } from './profileProvider'
export { PromptModalComponent } from '../components/promptModal.component'
export * from './commands'

View File

@@ -1,5 +1,5 @@
export interface MenuItemOptions {
type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'
type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio')
label?: string
sublabel?: string
enabled?: boolean

View File

@@ -86,18 +86,14 @@ export interface FileUploadOptions {
multiple: boolean
}
export type PlatformTheme = 'light'|'dark'
export abstract class PlatformService {
supportsWindowControls = false
get fileTransferStarted$ (): Observable<FileTransfer> { return this.fileTransferStarted }
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
get themeChanged$ (): Observable<PlatformTheme> { return this.themeChanged }
protected fileTransferStarted = new Subject<FileTransfer>()
protected displayMetricsChanged = new Subject<void>()
protected themeChanged = new Subject<PlatformTheme>()
abstract readClipboard (): string
abstract setClipboard (content: ClipboardContent): void
@@ -173,10 +169,6 @@ export abstract class PlatformService {
throw new Error('Not implemented')
}
getTheme (): PlatformTheme {
return 'dark'
}
abstract getOSRelease (): string
abstract getAppVersion (): string
abstract openExternal (url: string): void

View File

@@ -21,10 +21,6 @@ export interface Profile {
isTemplate: boolean
}
export interface ConnectableProfile extends Profile {
clearServiceMessagesOnConnect: boolean
}
export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
[K in keyof T]?: T[K]
}, 'options'>, 'type'>, 'name'> & {
@@ -35,21 +31,6 @@ export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
}
}
export interface ProfileGroup {
id: string
name: string
profiles: PartialProfile<Profile>[]
defaults: any
editable: boolean
}
export type PartialProfileGroup<T extends ProfileGroup> = Omit<Omit<{
[K in keyof T]?: T[K]
}, 'id'>, 'name'> & {
id: string
name: string
}
export interface ProfileSettingsComponent<P extends Profile> {
profile: P
save?: () => void
@@ -58,6 +39,7 @@ export interface ProfileSettingsComponent<P extends Profile> {
export abstract class ProfileProvider<P extends Profile> {
id: string
name: string
supportsQuickConnect = false
settingsComponent?: new (...args: any[]) => ProfileSettingsComponent<P>
configDefaults = {}
@@ -71,15 +53,13 @@ export abstract class ProfileProvider<P extends Profile> {
abstract getDescription (profile: PartialProfile<P>): string
quickConnect (query: string): PartialProfile<P>|null {
return null
}
intoQuickConnectString (profile: P): string|null {
return null
}
deleteProfile (profile: P): void { }
}
export abstract class ConnectableProfileProvider<P extends ConnectableProfile> extends ProfileProvider<P> {}
export abstract class QuickConnectProfileProvider<P extends ConnectableProfile> extends ConnectableProfileProvider<P> {
abstract quickConnect (query: string): PartialProfile<P>|null
abstract intoQuickConnectString (profile: P): string|null
}

View File

@@ -18,7 +18,7 @@ export class CoreCommandProvider extends CommandProvider {
}
async activate () {
const profile = await this.profilesService.showProfileSelector().catch(() => null)
const profile = await this.profilesService.showProfileSelector()
if (profile) {
this.profilesService.launchProfile(profile)
}

View File

@@ -1,20 +1,16 @@
title-bar(
*ngIf='ready && !hostWindow.isFullscreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
(dblclick)='hostWindow.toggleMaximize()',
[hideControls]='hostApp.platform !== Platform.Linux && !hostWindow.isFullscreen',
[class.inset]='hostApp.platform == Platform.macOS && !hostWindow.isFullscreen'
)
.content(
*ngIf='ready',
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"',
[class.tabs-on-left]='hasVerticalTabs() && config.store.appearance.tabsLocation == "left"',
[class.tabs-titlebar-enabled]='config.store.appearance.frame == "full"',
[class.tabs-on-right]='hasVerticalTabs() && config.store.appearance.tabsLocation == "right"',
[class.tabs-on-side]='hasVerticalTabs()',
)
.tab-bar(
*ngIf='!hostWindow.isFullscreen || config.store.appearance.tabsInFullscreen',
[class.tab-bar-no-controls-overlay]='hostApp.platform == Platform.macOS',
(dblclick)='hostWindow.toggleMaximize()'
)
.inset.background(*ngIf='hostApp.platform == Platform.macOS \
@@ -35,7 +31,8 @@ title-bar(
[@animateTab]='{value: "in", params: {size: targetTabSize}}',
[@.disabled]='hasVerticalTabs() || !config.store.accessibility.animations',
(click)='app.selectTab(tab)',
[class.fully-draggable]='hostApp.platform != Platform.macOS'
[class.fully-draggable]='hostApp.platform != Platform.macOS',
[class.drag-region]='hostApp.platform == Platform.macOS && !(app.tabDragActive$|async)',
)
.btn-group.background
@@ -64,7 +61,7 @@ title-bar(
(transfersChange)='onTransfersChange()'
)
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin"')
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
.btn-group.background
.d-flex(
@@ -84,12 +81,9 @@ title-bar(
window-controls.background(
*ngIf='config.store.appearance.frame == "thin" \
&& (hostApp.platform == Platform.Linux)',
&& (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
)
div.window-controls-spacer(
*ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows) && (config.store.appearance.tabsLocation == "top")',
)
.content
start-page.content-tab.content-tab-active(*ngIf='ready && app.tabs.length == 0')

View File

@@ -35,16 +35,17 @@ $tab-border-radius: 4px;
flex-direction: column;
}
&.tabs-on-right {
&.tabs-on-side {
flex-direction: row-reverse;
&.tabs-on-top {
flex-direction: row;
}
}
&.tabs-on-left {
flex-direction: row;
}
}
.content.tabs-on-left > .tab-bar, .content.tabs-on-right > .tab-bar {
.content.tabs-on-side > .tab-bar {
height: 100%;
width: var(--side-tab-width);
overflow-y: auto;
@@ -75,18 +76,6 @@ $tab-border-radius: 4px;
}
}
.content.tabs-on-left > .tab-bar.tab-bar-no-controls-overlay, .content.tabs-titlebar-enabled {
.tabs {
padding-top: 0 !important;
}
}
.content.tabs-on-right > .tab-bar {
.tabs {
// Account for WCO on Windows.
padding-top: 36px;
}
}
.tab-bar {
flex: none;
@@ -136,17 +125,10 @@ $tab-border-radius: 4px;
}
&.persistent {
// min-width: 72px; // 2 x 36 px height, ie 2 squares
// Given WCO on Windows, the min-width of the window buttons is about 138px.
min-width: 138px;
min-width: 72px; // 2 x 36 px height, ie 2 squares
}
}
&>.window-controls-spacer {
min-width: 138px;
height: 100%;
}
& > .inset {
width: calc(70px + 15px * var(--spaciness));
height: var(--tabs-height);

View File

@@ -75,7 +75,6 @@ export abstract class BaseTabComponent extends BaseComponent {
private titleChange = new Subject<string>()
private focused = new Subject<void>()
private blurred = new Subject<void>()
private visibility = new Subject<boolean>()
private progress = new Subject<number|null>()
private activity = new Subject<boolean>()
private destroyed = new Subject<void>()
@@ -84,8 +83,6 @@ export abstract class BaseTabComponent extends BaseComponent {
get focused$ (): Observable<void> { return this.focused }
get blurred$ (): Observable<void> { return this.blurred }
/* @hidden */
get visibility$ (): Observable<boolean> { return this.visibility }
get titleChange$ (): Observable<string> { return this.titleChange.pipe(distinctUntilChanged()) }
get progress$ (): Observable<number|null> { return this.progress.pipe(distinctUntilChanged()) }
get activity$ (): Observable<boolean> { return this.activity }
@@ -180,11 +177,6 @@ export abstract class BaseTabComponent extends BaseComponent {
this.blurred.next()
}
/* @hidden */
emitVisibility (visibility: boolean): void {
this.visibility.next(visibility)
}
insertIntoContainer (container: ViewContainerRef): EmbeddedViewRef<any> {
this.viewContainerEmbeddedRef = container.insert(this.hostView) as EmbeddedViewRef<any>
this.viewContainer = container

View File

@@ -18,58 +18,45 @@ export class SelectorModalComponent<T> {
@Input() selectedIndex = 0
hasGroups = false
@ViewChildren('item') itemChildren: QueryList<ElementRef>
private preventEdit: boolean
constructor (public modalInstance: NgbActiveModal) {
this.preventEdit = false
}
constructor (
public modalInstance: NgbActiveModal,
) { }
ngOnInit (): void {
this.onFilterChange()
this.hasGroups = this.options.some(x => x.group)
}
@HostListener('keydown', ['$event']) onKeyDown (event: KeyboardEvent): void {
if (event.key === 'Escape') {
@HostListener('keydown', ['$event']) onKeyUp (event: KeyboardEvent): void {
if (event.key === 'PageUp' || event.key === 'ArrowUp' && event.metaKey) {
this.selectedIndex -= 10
event.preventDefault()
} else if (event.key === 'PageDown' || event.key === 'ArrowDown' && event.metaKey) {
this.selectedIndex += 10
event.preventDefault()
} else if (event.key === 'ArrowUp') {
this.selectedIndex--
event.preventDefault()
} else if (event.key === 'ArrowDown') {
this.selectedIndex++
event.preventDefault()
} else if (event.key === 'Enter') {
this.selectOption(this.filteredOptions[this.selectedIndex])
} else if (event.key === 'Escape') {
this.close()
} else if (this.filteredOptions.length > 0) {
if (event.key === 'PageUp' || event.key === 'ArrowUp' && event.metaKey) {
this.selectedIndex -= Math.min(10, Math.max(1, this.selectedIndex))
event.preventDefault()
} else if (event.key === 'PageDown' || event.key === 'ArrowDown' && event.metaKey) {
this.selectedIndex += Math.min(10, Math.max(1, this.filteredOptions.length - this.selectedIndex - 1))
event.preventDefault()
} else if (event.key === 'ArrowUp') {
this.selectedIndex--
event.preventDefault()
} else if (event.key === 'ArrowDown') {
this.selectedIndex++
event.preventDefault()
} else if (event.key === 'Enter') {
this.selectOption(this.filteredOptions[this.selectedIndex])
} else if (event.key === 'Backspace' && !this.preventEdit) {
if (this.canEditSelected()) {
event.preventDefault()
this.filter = this.filteredOptions[this.selectedIndex].freeInputEquivalent!
this.onFilterChange()
} else {
this.preventEdit = true
}
}
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
})
}
}
@HostListener('keyup', ['$event']) onKeyUp (event: KeyboardEvent): void {
if (event.key === 'Backspace' && this.preventEdit) {
this.preventEdit = false
if (event.key === 'Backspace' && this.canEditSelected()) {
event.preventDefault()
this.filter = this.filteredOptions[this.selectedIndex].freeInputEquivalent!
this.onFilterChange()
}
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
})
}
onFilterChange (): void {
@@ -89,11 +76,10 @@ export class SelectorModalComponent<T> {
{ sort: true },
).search(f)
this.options.filter(x => x.freeInputPattern).sort(firstBy<SelectorOption<T>, number>(x => x.weight ?? 0)).forEach(freeOption => {
if (!this.filteredOptions.includes(freeOption)) {
this.filteredOptions.push(freeOption)
}
})
const freeOption = this.options.find(x => x.freeInputPattern)
if (freeOption && !this.filteredOptions.includes(freeOption)) {
this.filteredOptions.push(freeOption)
}
}
this.selectedIndex = Math.max(0, this.selectedIndex)
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)

View File

@@ -275,7 +275,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
}
})
this.blurred$.subscribe(() => this.getAllTabs().forEach(x => x.emitBlurred()))
this.visibility$.subscribe(visibility => this.getAllTabs().forEach(x => x.emitVisibility(visibility)))
this.tabAdded$.subscribe(() => this.updateTitle())
this.tabRemoved$.subscribe(() => this.updateTitle())

View File

@@ -1,2 +1,2 @@
.title((dblclick)='hostWindow.toggleMaximize()') Tabby
window-controls(*ngIf="!hideControls")
window-controls

View File

@@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core'
import { Component } from '@angular/core'
import { HostWindowService } from '../api'
/** @hidden */
@@ -8,7 +8,5 @@ import { HostWindowService } from '../api'
styleUrls: ['./titleBar.component.scss'],
})
export class TitleBarComponent {
@Input() hideControls: boolean
constructor (public hostWindow: HostWindowService) { }
}

View File

@@ -1,10 +1,10 @@
.container.mt-3.mb-3
.mb-3
.container.mt-5.mb-5
.mb-4
.tabby-logo
h1.tabby-title Tabby
sup α
.text-center.mb-3(translate) Thank you for downloading Tabby!
.text-center.mb-5(translate) Thank you for downloading Tabby!
.form-line
.header
@@ -16,54 +16,13 @@
*ngFor='let lang of allLanguages'
) {{lang.name}}
.form-line
.header
.title(translate) Switch color scheme
.btn-group(role='group')
input.btn-check(
type='radio',
name='colorSchemeMode',
[(ngModel)]='config.store.appearance.colorSchemeMode',
(ngModelChange)='config.save()',
id='colorSchemeModeAuto',
[value]='"auto"'
)
label.btn.btn-secondary(
for='colorSchemeModeAuto'
)
span(translate) From system
input.btn-check(
type='radio',
name='colorSchemeMode',
[(ngModel)]='config.store.appearance.colorSchemeMode',
(ngModelChange)='config.save()',
id='colorSchemeModeDark',
[value]='"dark"'
)
label.btn.btn-secondary(
for='colorSchemeModeDark'
)
span(translate) Always dark
input.btn-check(
type='radio',
name='colorSchemeMode',
[(ngModel)]='config.store.appearance.colorSchemeMode',
(ngModelChange)='config.save()',
id='colorSchemeModeLight',
[value]='"light"'
)
label.btn.btn-secondary(
for='colorSchemeModeLight'
)
span(translate) Always light
.form-line
.header
.title(translate) Enable analytics
.description(translate) Help track the number of Tabby installs across the world!
toggle([(ngModel)]='config.store.enableAnalytics')
.form-line
.header
.title(translate) Enable global hotkey (Ctrl-Space)

View File

@@ -6,8 +6,3 @@
max-height: 100%;
overflow-y: auto;
}
.tabby-logo {
width: 60px;
height: 60px;
}

View File

@@ -9,6 +9,5 @@ export class CoreConfigProvider extends ConfigProvider {
[Platform.Linux]: require('./configDefaults.linux.yaml').default,
[Platform.Web]: require('./configDefaults.web.yaml').default,
}
defaults = require('./configDefaults.yaml').default
}

View File

@@ -96,3 +96,5 @@ hotkeys:
- '⌘-Shift-E'
command-selector:
- '⌘-Shift-P'
appearance:
vibrancy: true

View File

@@ -11,7 +11,7 @@ appearance:
tabsLocation: top
tabsInFullscreen: false
cycleTabs: true
theme: Follow the color scheme
theme: Standard
frame: thin
css: '/* * { color: blue !important; } */'
opacity: 1.0
@@ -19,7 +19,6 @@ appearance:
vibrancyType: 'blur'
lastTabClosesWindow: false
spaciness: 1
colorSchemeMode: 'dark'
terminal:
showBuiltinProfiles: true
showRecentProfiles: 3
@@ -32,7 +31,6 @@ hotkeys:
profile-selectors:
__nonStructural: true
profiles: []
groups: []
profileDefaults:
__nonStructural: true
ssh:
@@ -56,4 +54,3 @@ hacks:
disableVibrancyWhileDragging: false
enableFluentBackground: false
language: null
defaultQuickConnectProvider: "ssh"

View File

@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'
import { TranslateService } from '@ngx-translate/core'
import { ProfilesService } from './services/profiles.service'
import { HotkeyDescription, HotkeyProvider } from './api/hotkeyProvider'
import { PartialProfile, Profile } from './api'
/** @hidden */
@Injectable()
@@ -267,7 +268,7 @@ export class AppHotkeyProvider extends HotkeyProvider {
return [
...this.hotkeys,
...profiles.map(profile => ({
id: `profile.${ProfilesService.getProfileHotkeyName(profile)}`,
id: `profile.${AppHotkeyProvider.getProfileHotkeyName(profile)}`,
name: this.translate.instant('New tab: {profile}', { profile: profile.name }),
})),
...this.profilesService.getProviders().map(provider => ({
@@ -277,4 +278,7 @@ export class AppHotkeyProvider extends HotkeyProvider {
]
}
static getProfileHotkeyName (profile: PartialProfile<Profile>): string {
return (profile.id ?? profile.name).replace(/\./g, '-')
}
}

View File

@@ -37,7 +37,7 @@ import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive'
import { DropZoneDirective } from './directives/dropZone.directive'
import { CdkAutoDropGroup } from './directives/cdkAutoDropGroup.directive'
import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, QuickConnectProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api'
import { Theme, CLIHandler, TabContextMenuItemProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider, PlatformService, FileProvider, ProfilesService, ProfileProvider, SelectorOption, Profile, SelectorService, CommandProvider } from './api'
import { AppService } from './services/app.service'
import { ConfigService } from './services/config.service'
@@ -177,7 +177,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
if (hotkey.startsWith('profile.')) {
const id = hotkey.substring(hotkey.indexOf('.') + 1)
const profiles = await profilesService.getProfiles()
const profile = profiles.find(x => ProfilesService.getProfileHotkeyName(x) === id)
const profile = profiles.find(x => AppHotkeyProvider.getProfileHotkeyName(x) === id)
if (profile) {
profilesService.openNewTabForProfile(profile)
}
@@ -188,10 +188,10 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
if (!provider) {
return
}
this.showSelector(provider).catch(() => null)
this.showSelector(provider)
}
if (hotkey === 'command-selector') {
commands.showSelector().catch(() => null)
commands.showSelector()
}
if (hotkey === 'profile-selector') {
@@ -214,12 +214,11 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
callback: () => this.profilesService.openNewTabForProfile(p),
}))
if (provider instanceof QuickConnectProfileProvider) {
if (provider.supportsQuickConnect) {
options.push({
name: this.translate.instant('Quick connect'),
freeInputPattern: this.translate.instant('Connect to "%s"...'),
icon: 'fas fa-arrow-right',
description: `(${provider.name.toUpperCase()})`,
callback: query => {
const p = provider.quickConnect(query)
if (p) {

View File

@@ -230,13 +230,11 @@ export class AppService {
if (this._activeTab) {
this._activeTab.clearActivity()
this._activeTab.emitBlurred()
this._activeTab.emitVisibility(false)
}
this._activeTab = tab
this.activeTabChange.next(tab)
setImmediate(() => {
this._activeTab?.emitFocused()
this._activeTab?.emitVisibility(true)
})
this.hostWindow.setTitle(this._activeTab?.title)
}

View File

@@ -101,7 +101,7 @@ export class CommandService {
context.tab = tab.getFocusedTab() ?? undefined
}
const commands = await this.getCommands(context)
return this.selector.show(
await this.selector.show(
this.translate.instant('Commands'),
commands.map(c => ({
name: c.label,

View File

@@ -10,15 +10,11 @@ import { PlatformService } from '../api/platform'
import { HostAppService } from '../api/hostApp'
import { Vault, VaultService } from './vault.service'
import { serializeFunction } from '../utils'
import { PartialProfileGroup, ProfileGroup } from '../api/profileProvider'
const deepmerge = require('deepmerge')
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const configMerge = (a, b) => deepmerge(a, b, { arrayMerge: (_d, s) => s }) // eslint-disable-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const configMergeByDefault = (a, b) => deepmerge(a, b) // eslint-disable-line @typescript-eslint/no-var-requires
const LATEST_VERSION = 1
function isStructuralMember (v) {
@@ -166,7 +162,7 @@ export class ConfigService {
defaults = configMerge(provider.defaults, defaults)
}
return defaults
}).reduce(configMergeByDefault)
}).reduce(configMerge)
}
getDefaults (): Record<string, any> {
@@ -217,9 +213,7 @@ export class ConfigService {
* Reads config YAML as string
*/
readRaw (): string {
// Scrub undefined values
const cleanStore = JSON.parse(JSON.stringify(this._store))
return yaml.dump(cleanStore)
return yaml.dump(this._store)
}
/**
@@ -357,55 +351,6 @@ export class ConfigService {
delete window.localStorage.lastSerialConnection
config.version = 3
}
if (config.version < 4) {
for (const p of config.profiles ?? []) {
if (!p.id) {
p.id = `${p.type}:custom:${uuidv4()}`
}
}
config.version = 4
}
if (config.version < 5) {
const groups: PartialProfileGroup<ProfileGroup>[] = []
for (const p of config.profiles ?? []) {
if (!(p.group ?? '').trim()) {
continue
}
let group = groups.find(x => x.name === p.group)
if (!group) {
group = {
id: `${uuidv4()}`,
name: `${p.group}`,
}
groups.push(group)
}
p.group = group.id
}
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
for (const g of groups) {
if (profileGroupCollapsed[g.name]) {
const collapsed = profileGroupCollapsed[g.name]
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profileGroupCollapsed[g.name]
profileGroupCollapsed[g.id] = collapsed
}
}
window.localStorage.profileGroupCollapsed = JSON.stringify(profileGroupCollapsed)
config.groups = groups
config.version = 5
}
if (config.version < 6) {
if (config.ssh?.clearServiceMessagesOnConnect === false) {
config.profileDefaults ??= {}
config.profileDefaults.ssh ??= {}
config.profileDefaults.ssh.clearServiceMessagesOnConnect = false
delete config.ssh?.clearServiceMessagesOnConnect
}
config.version = 6
}
}
private async maybeDecryptConfig (store) {

View File

@@ -13,9 +13,8 @@ export class FileProvidersService {
) { }
async selectAndStoreFile (description: string): Promise<string> {
return this.selectProvider().then(p => {
return p.selectAndStoreFile(description)
})
const p = await this.selectProvider()
return p.selectAndStoreFile(description)
}
async retrieveFile (key: string): Promise<Buffer> {

View File

@@ -7,7 +7,6 @@ import localeENUS from '@angular/common/locales/en'
import localeENGB from '@angular/common/locales/en-GB'
import localeAF from '@angular/common/locales/af'
import localeBG from '@angular/common/locales/bg'
import localeCS from '@angular/common/locales/cs'
import localeDA from '@angular/common/locales/da'
import localeDE from '@angular/common/locales/de'
import localeES from '@angular/common/locales/es'
@@ -32,7 +31,6 @@ registerLocaleData(localeENUS)
registerLocaleData(localeENGB)
registerLocaleData(localeAF)
registerLocaleData(localeBG)
registerLocaleData(localeCS)
registerLocaleData(localeDA)
registerLocaleData(localeDE)
registerLocaleData(localeES)
@@ -84,10 +82,6 @@ export class LocaleService {
code: 'id-ID',
name: 'Bahasa Indonesia',
},
{
code: 'cs-CZ',
name: 'Čeština',
},
{
code: 'da-DK',
name: 'Dansk',

View File

@@ -2,15 +2,12 @@ import { Injectable, Inject } from '@angular/core'
import { TranslateService } from '@ngx-translate/core'
import { NewTabParameters } from './tabs.service'
import { BaseTabComponent } from '../components/baseTab.component'
import { QuickConnectProfileProvider, PartialProfile, PartialProfileGroup, Profile, ProfileGroup, ProfileProvider } from '../api/profileProvider'
import { PartialProfile, Profile, ProfileProvider } from '../api/profileProvider'
import { SelectorOption } from '../api/selector'
import { AppService } from './app.service'
import { configMerge, ConfigProxy, ConfigService } from './config.service'
import { NotificationsService } from './notifications.service'
import { SelectorService } from './selector.service'
import deepClone from 'clone-deep'
import { v4 as uuidv4 } from 'uuid'
import slugify from 'slugify'
@Injectable({ providedIn: 'root' })
export class ProfilesService {
@@ -39,127 +36,6 @@ export class ProfilesService {
@Inject(ProfileProvider) private profileProviders: ProfileProvider<Profile>[],
) { }
/*
* Methods used to interract with ProfileProvider
*/
getProviders (): ProfileProvider<Profile>[] {
return [...this.profileProviders]
}
providerForProfile <T extends Profile> (profile: PartialProfile<T>): ProfileProvider<T>|null {
const provider = this.profileProviders.find(x => x.id === profile.type) ?? null
return provider as unknown as ProfileProvider<T>|null
}
getDescription <P extends Profile> (profile: PartialProfile<P>): string|null {
profile = this.getConfigProxyForProfile(profile)
return this.providerForProfile(profile)?.getDescription(profile) ?? null
}
/*
* Methods used to interract with Profile
*/
/*
* Return ConfigProxy for a given Profile
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
* arg: skipGroupDefaults -> do not merge parent group provider defaults in ConfigProxy
*/
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, options?: { skipGlobalDefaults?: boolean, skipGroupDefaults?: boolean }): T {
const defaults = this.getProfileDefaults(profile, options).reduce(configMerge, {})
return new ConfigProxy(profile, defaults) as unknown as T
}
/**
* Return an Array of Profiles
* arg: includeBuiltin (default: true) -> include BuiltinProfiles
* arg: clone (default: false) -> return deepclone Array
*/
async getProfiles (options?: { includeBuiltin?: boolean, clone?: boolean }): Promise<PartialProfile<Profile>[]> {
let list = this.config.store.profiles ?? []
if (options?.includeBuiltin ?? true) {
const lists = await Promise.all(this.config.enabledServices(this.profileProviders).map(x => x.getBuiltinProfiles()))
list = [
...this.config.store.profiles ?? [],
...lists.reduce((a, b) => a.concat(b), []),
]
}
const sortKey = p => `${this.resolveProfileGroupName(p.group ?? '')} / ${p.name}`
list.sort((a, b) => sortKey(a).localeCompare(sortKey(b)))
list.sort((a, b) => (a.isBuiltin ? 1 : 0) - (b.isBuiltin ? 1 : 0))
return options?.clone ? deepClone(list) : list
}
/**
* Insert a new Profile in config
* arg: genId (default: true) -> generate uuid in before pushing Profile into config
*/
async newProfile (profile: PartialProfile<Profile>, options?: { genId?: boolean }): Promise<void> {
if (options?.genId ?? true) {
profile.id = `${profile.type}:custom:${slugify(profile.name)}:${uuidv4()}`
}
const cProfile = this.config.store.profiles.find(p => p.id === profile.id)
if (cProfile) {
throw new Error(`Cannot insert new Profile, duplicated Id: ${profile.id}`)
}
this.config.store.profiles.push(profile)
}
/**
* Write a Profile in config
*/
async writeProfile (profile: PartialProfile<Profile>): Promise<void> {
const cProfile = this.config.store.profiles.find(p => p.id === profile.id)
if (cProfile) {
// Fully replace the config
for (const k in cProfile) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete cProfile[k]
}
Object.assign(cProfile, profile)
}
}
/**
* Delete a Profile from config
*/
async deleteProfile (profile: PartialProfile<Profile>): Promise<void> {
this.providerForProfile(profile)?.deleteProfile(this.getConfigProxyForProfile(profile))
this.config.store.profiles = this.config.store.profiles.filter(p => p.id !== profile.id)
const profileHotkeyName = ProfilesService.getProfileHotkeyName(profile)
if (this.config.store.hotkeys.profile.hasOwnProperty(profileHotkeyName)) {
const profileHotkeys = deepClone(this.config.store.hotkeys.profile)
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profileHotkeys[profileHotkeyName]
this.config.store.hotkeys.profile = profileHotkeys
}
}
/**
* Delete all Profiles from config using option filter
* arg: filter (p: PartialProfile<Profile>) => boolean -> predicate used to decide which profiles have to be deleted
*/
async bulkDeleteProfiles (filter: (p: PartialProfile<Profile>) => boolean): Promise<void> {
for (const profile of this.config.store.profiles.filter(filter)) {
this.providerForProfile(profile)?.deleteProfile(this.getConfigProxyForProfile(profile))
const profileHotkeyName = ProfilesService.getProfileHotkeyName(profile)
if (this.config.store.hotkeys.profile.hasOwnProperty(profileHotkeyName)) {
const profileHotkeys = deepClone(this.config.store.hotkeys.profile)
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete profileHotkeys[profileHotkeyName]
this.config.store.hotkeys.profile = profileHotkeys
}
}
this.config.store.profiles = this.config.store.profiles.filter(x => !filter(x))
}
async openNewTabForProfile <P extends Profile> (profile: PartialProfile<P>): Promise<BaseTabComponent|null> {
const params = await this.newTabParametersForProfile(profile)
if (params) {
@@ -187,40 +63,52 @@ export class ProfilesService {
return params
}
async launchProfile (profile: PartialProfile<Profile>): Promise<void> {
await this.openNewTabForProfile(profile)
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
if (this.config.store.terminal.showRecentProfiles > 0) {
recentProfiles = recentProfiles.filter(x => x.group !== profile.group || x.name !== profile.name)
recentProfiles.unshift(profile)
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
} else {
recentProfiles = []
}
window.localStorage['recentProfiles'] = JSON.stringify(recentProfiles)
getProviders (): ProfileProvider<Profile>[] {
return [...this.profileProviders]
}
static getProfileHotkeyName (profile: PartialProfile<Profile>): string {
return (profile.id ?? profile.name).replace(/\./g, '-')
async getProfiles (): Promise<PartialProfile<Profile>[]> {
const lists = await Promise.all(this.config.enabledServices(this.profileProviders).map(x => x.getBuiltinProfiles()))
let list = lists.reduce((a, b) => a.concat(b), [])
list = [
...this.config.store.profiles ?? [],
...list,
]
const sortKey = p => `${p.group ?? ''} / ${p.name}`
list.sort((a, b) => sortKey(a).localeCompare(sortKey(b)))
list.sort((a, b) => (a.isBuiltin ? 1 : 0) - (b.isBuiltin ? 1 : 0))
return list
}
/*
* Methods used to interract with Profile Selector
*/
providerForProfile <T extends Profile> (profile: PartialProfile<T>): ProfileProvider<T>|null {
const provider = this.profileProviders.find(x => x.id === profile.type) ?? null
return provider as unknown as ProfileProvider<T>|null
}
getDescription <P extends Profile> (profile: PartialProfile<P>): string|null {
profile = this.getConfigProxyForProfile(profile)
return this.providerForProfile(profile)?.getDescription(profile) ?? null
}
selectorOptionForProfile <P extends Profile, T> (profile: PartialProfile<P>): SelectorOption<T> {
const fullProfile = this.getConfigProxyForProfile(profile)
const provider = this.providerForProfile(fullProfile)
const freeInputEquivalent = provider instanceof QuickConnectProfileProvider ? provider.intoQuickConnectString(fullProfile) ?? undefined : undefined
const freeInputEquivalent = provider?.intoQuickConnectString(fullProfile) ?? undefined
return {
...profile,
group: this.resolveProfileGroupName(profile.group ?? ''),
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
group: profile.group || '',
freeInputEquivalent,
description: provider?.getDescription(fullProfile),
}
}
getRecentProfiles (): PartialProfile<Profile>[] {
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
return recentProfiles
}
showProfileSelector (): Promise<PartialProfile<Profile>|null> {
if (this.selector.active) {
return Promise.resolve(null)
@@ -230,12 +118,12 @@ export class ProfilesService {
try {
const recentProfiles = this.getRecentProfiles()
let options: SelectorOption<void>[] = recentProfiles.map((p, i) => ({
let options: SelectorOption<void>[] = recentProfiles.map(p => ({
...this.selectorOptionForProfile(p),
group: this.translate.instant('Recent'),
icon: 'fas fa-history',
color: p.color,
weight: i - (recentProfiles.length + 1),
weight: -2,
callback: async () => {
if (p.id) {
p = (await this.getProfiles()).find(x => x.id === p.id) ?? p
@@ -289,38 +177,27 @@ export class ProfilesService {
})
} catch { }
this.getProviders().forEach(provider => {
if (provider instanceof QuickConnectProfileProvider) {
options.push({
name: this.translate.instant('Quick connect'),
freeInputPattern: this.translate.instant('Connect to "%s"...'),
description: `(${provider.name.toUpperCase()})`,
icon: 'fas fa-arrow-right',
weight: provider.id !== this.config.store.defaultQuickConnectProvider ? 1 : 0,
callback: query => {
const profile = provider.quickConnect(query)
resolve(profile)
},
})
}
})
await this.selector.show(this.translate.instant('Select profile or enter an address'), options).catch(() => reject())
if (this.getProviders().some(x => x.supportsQuickConnect)) {
options.push({
name: this.translate.instant('Quick connect'),
freeInputPattern: this.translate.instant('Connect to "%s"...'),
icon: 'fas fa-arrow-right',
callback: query => {
const profile = this.quickConnect(query)
resolve(profile)
},
})
}
await this.selector.show(this.translate.instant('Select profile or enter an address'), options)
} catch (err) {
reject(err)
}
})
}
getRecentProfiles (): PartialProfile<Profile>[] {
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
return recentProfiles
}
async quickConnect (query: string): Promise<PartialProfile<Profile>|null> {
for (const provider of this.getProviders()) {
if (provider instanceof QuickConnectProfileProvider) {
if (provider.supportsQuickConnect) {
const profile = provider.quickConnect(query)
if (profile) {
return profile
@@ -331,178 +208,27 @@ export class ProfilesService {
return null
}
/*
* Methods used to interract with Profile/ProfileGroup/Global defaults
*/
/**
* Return global defaults for a given profile provider
* Always return something, empty object if no defaults found
*/
getProviderDefaults (provider: ProfileProvider<Profile>): any {
const defaults = this.config.store.profileDefaults
return defaults[provider.id] ?? {}
}
/**
* Set global defaults for a given profile provider
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
setProviderDefaults (provider: ProfileProvider<Profile>, pdefaults: any): void {
this.config.store.profileDefaults[provider.id] = pdefaults
}
/**
* Return defaults for a given profile
* Always return something, empty object if no defaults found
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
* arg: skipGroupDefaults -> do not merge parent group provider defaults in ConfigProxy
*/
getProfileDefaults (profile: PartialProfile<Profile>, options?: { skipGlobalDefaults?: boolean, skipGroupDefaults?: boolean }): any[] {
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, skipUserDefaults = false): T {
const provider = this.providerForProfile(profile)
return [
const defaults = [
this.profileDefaults,
provider?.configDefaults ?? {},
provider && !options?.skipGlobalDefaults ? this.getProviderDefaults(provider) : {},
provider && !options?.skipGlobalDefaults && !options?.skipGroupDefaults ? this.getProviderProfileGroupDefaults(profile.group ?? '', provider) : {},
]
!provider || skipUserDefaults ? {} : this.config.store.profileDefaults[provider.id] ?? {},
].reduce(configMerge, {})
return new ConfigProxy(profile, defaults) as unknown as T
}
/*
* Methods used to interract with ProfileGroup
*/
async launchProfile (profile: PartialProfile<Profile>): Promise<void> {
await this.openNewTabForProfile(profile)
/**
* Synchronously return an Array of the existing ProfileGroups
* Does not return builtin groups
*/
getSyncProfileGroups (): PartialProfileGroup<ProfileGroup>[] {
return deepClone(this.config.store.groups ?? [])
}
/**
* Return an Array of the existing ProfileGroups
* arg: includeProfiles (default: false) -> if false, does not fill up the profiles field of ProfileGroup
* arg: includeNonUserGroup (default: false) -> if false, does not add built-in and ungrouped groups
*/
async getProfileGroups (options?: { includeProfiles?: boolean, includeNonUserGroup?: boolean }): Promise<PartialProfileGroup<ProfileGroup>[]> {
let profiles: PartialProfile<Profile>[] = []
if (options?.includeProfiles) {
profiles = await this.getProfiles({ includeBuiltin: options.includeNonUserGroup, clone: true })
}
let groups: PartialProfileGroup<ProfileGroup>[] = this.getSyncProfileGroups()
groups = groups.map(x => {
x.editable = true
if (options?.includeProfiles) {
x.profiles = profiles.filter(p => p.group === x.id)
profiles = profiles.filter(p => p.group !== x.id)
}
return x
})
if (options?.includeNonUserGroup) {
const builtInGroups: PartialProfileGroup<ProfileGroup>[] = []
builtInGroups.push({
id: 'built-in',
name: this.translate.instant('Built-in'),
editable: false,
profiles: [],
})
const ungrouped: PartialProfileGroup<ProfileGroup> = {
id: 'ungrouped',
name: this.translate.instant('Ungrouped'),
editable: false,
}
if (options.includeProfiles) {
for (const profile of profiles.filter(p => p.isBuiltin)) {
let group: PartialProfileGroup<ProfileGroup> | undefined = builtInGroups.find(g => g.id === slugify(profile.group ?? 'built-in'))
if (!group) {
group = {
id: `${slugify(profile.group!)}`,
name: `${profile.group!}`,
editable: false,
profiles: [],
}
builtInGroups.push(group)
}
group.profiles!.push(profile)
}
ungrouped.profiles = profiles.filter(p => !p.isBuiltin)
}
groups = groups.concat(builtInGroups)
groups.push(ungrouped)
}
return groups
}
/**
* Insert a new ProfileGroup in config
* arg: genId (default: true) -> generate uuid in before pushing Profile into config
*/
async newProfileGroup (group: PartialProfileGroup<ProfileGroup>, options?: { genId?: boolean }): Promise<void> {
if (options?.genId ?? true) {
group.id = `${uuidv4()}`
}
const cProfileGroup = this.config.store.groups.find(p => p.id === group.id)
if (cProfileGroup) {
throw new Error(`Cannot insert new ProfileGroup, duplicated Id: ${group.id}`)
}
this.config.store.groups.push(group)
}
/**
* Write a ProfileGroup in config
*/
async writeProfileGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> {
delete group.profiles
delete group.editable
const cGroup = this.config.store.groups.find(g => g.id === group.id)
if (cGroup) {
Object.assign(cGroup, group)
}
}
/**
* Delete a ProfileGroup from config
*/
async deleteProfileGroup (group: PartialProfileGroup<ProfileGroup>, options?: { deleteProfiles?: boolean }): Promise<void> {
this.config.store.groups = this.config.store.groups.filter(g => g.id !== group.id)
if (options?.deleteProfiles) {
await this.bulkDeleteProfiles((p) => p.group === group.id)
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
if (this.config.store.terminal.showRecentProfiles > 0) {
recentProfiles = recentProfiles.filter(x => x.group !== profile.group || x.name !== profile.name)
recentProfiles.unshift(profile)
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
} else {
for (const profile of this.config.store.profiles.filter(x => x.group === group.id)) {
delete profile.group
}
recentProfiles = []
}
window.localStorage['recentProfiles'] = JSON.stringify(recentProfiles)
}
/**
* Resolve and return ProfileGroup Name from ProfileGroup ID
*/
resolveProfileGroupName (groupId: string): string {
return this.config.store.groups.find(g => g.id === groupId)?.name ?? groupId
}
/**
* Return defaults for a given group ID and provider
* Always return something, empty object if no defaults found
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
*/
getProviderProfileGroupDefaults (groupId: string, provider: ProfileProvider<Profile>): any {
return this.getSyncProfileGroups().find(g => g.id === groupId)?.defaults?.[provider.id] ?? {}
}
}

View File

@@ -3,7 +3,6 @@ import { Subject, Observable } from 'rxjs'
import * as Color from 'color'
import { ConfigService } from '../services/config.service'
import { Theme } from '../api/theme'
import { PlatformService, PlatformTheme } from '../api/platform'
import { NewTheme } from '../theme'
@Injectable({ providedIn: 'root' })
@@ -18,7 +17,6 @@ export class ThemesService {
private constructor (
private config: ConfigService,
private standardTheme: NewTheme,
private platform: PlatformService,
@Inject(Theme) private themes: Theme[],
) {
this.rootElementStyleBackup = document.documentElement.style.cssText
@@ -26,10 +24,6 @@ export class ThemesService {
config.ready$.toPromise().then(() => {
this.applyCurrentTheme()
this.applyThemeVariables()
platform.themeChanged$.subscribe(() => {
this.applyCurrentTheme()
this.applyThemeVariables()
})
config.changed$.subscribe(() => {
this.applyCurrentTheme()
this.applyThemeVariables()
@@ -42,7 +36,7 @@ export class ThemesService {
document.documentElement.style.cssText = this.rootElementStyleBackup
}
const theme = this._getActiveColorScheme()
const theme = this.config.store.terminal.colorScheme
const isDark = Color(theme.background).luminosity() < Color(theme.foreground).luminosity()
function more (some, factor) {
@@ -112,10 +106,8 @@ export class ThemesService {
const themeColors = {
primary: theme.colors[accentIndex],
secondary: isDark
? less(theme.background, 0.5).string()
: less(theme.background, 0.125).string(),
tertiary: more(theme.background, 0.75).string(),
secondary: less(theme.background, 0.5).string(),
tertiary: theme.colors[8],
warning: theme.colors[3],
danger: theme.colors[1],
success: theme.colors[2],
@@ -192,22 +184,6 @@ export class ThemesService {
return this.findTheme(this.config.store.appearance.theme) ?? this.standardTheme
}
/// @hidden
_getActiveColorScheme (): any {
let theme: PlatformTheme = 'dark'
if (this.config.store.appearance.colorSchemeMode === 'light') {
theme = 'light'
} else if (this.config.store.appearance.colorSchemeMode === 'auto') {
theme = this.platform.getTheme()
}
if (theme === 'light') {
return this.config.store.terminal.lightColorScheme
} else {
return this.config.store.terminal.colorScheme
}
}
applyTheme (theme: Theme): void {
if (!this.styleElement) {
this.styleElement = document.createElement('style')

View File

@@ -285,7 +285,7 @@ export class VaultFileProvider extends FileProvider {
icon: 'fas fa-file',
result: f,
})),
]).catch(() => null)
])
if (result) {
return `${this.prefix}${result.key.id}`
}

View File

@@ -149,7 +149,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
click: async () => {
const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('Profile name')
const name = (await modal.result.catch(() => null))?.value
const name = (await modal.result)?.value
if (!name) {
return
}
@@ -262,7 +262,7 @@ export class ProfilesContextMenu extends TabContextMenuItemProvider {
}
async switchTabProfile (tab: BaseTabComponent) {
const profile = await this.profilesService.showProfileSelector().catch(() => null)
const profile = await this.profilesService.showProfileSelector()
if (!profile) {
return
}

View File

@@ -110,7 +110,7 @@ body {
}
.nav {
--bs-nav-link-color: var(--theme-fg-more);
--bs-nav-link-color: var(--theme-fg);
--bs-nav-link-hover-color: var(--theme-fg-less);
--bs-nav-link-disabled-color: var(--bs-gray);
}
@@ -119,8 +119,8 @@ body {
--bs-nav-tabs-border-width: 2px;
--bs-nav-tabs-border-radius: 0;
--bs-nav-tabs-link-hover-border-color: var(--bs-body-bg);
--bs-nav-tabs-border-color: var(--theme-fg);
--bs-nav-tabs-link-active-color: var(--theme-fg);
--bs-nav-tabs-border-color: var(--theme-fg-less-2);
--bs-nav-tabs-link-active-color: var(--theme-fg-less-2);
--bs-nav-tabs-link-active-bg: transparent;
--bs-nav-tabs-link-active-border-color: transparent;

View File

@@ -22,6 +22,5 @@ export class ElectronConfigProvider extends ConfigProvider {
},
},
}
defaults = {}
}

View File

@@ -99,7 +99,6 @@ export default class ElectronModule {
})
this.registerGlobalHotkey()
this.updateVibrancy()
this.updateWindowControlsColor()
})
config.changed$.subscribe(() => {
@@ -132,8 +131,6 @@ export default class ElectronModule {
config.changed$.subscribe(() => this.updateVibrancy())
config.changed$.subscribe(() => this.updateWindowControlsColor())
config.ready$.toPromise().then(() => {
dockMenu.update()
})
@@ -172,15 +169,6 @@ export default class ElectronModule {
this.hostWindow.setOpacity(this.config.store.appearance.opacity)
}
private updateWindowControlsColor () {
// if windows and not using native frame, WCO does not exist, return.
if (this.hostApp.platform === Platform.Windows && this.config.store.appearance.frame === 'native') {
return
}
this.electron.ipcRenderer.send('window-set-window-controls-color', this.config.store.terminal.colorScheme)
}
}
export { ElectronHostWindow, ElectronHostAppService, ElectronService }

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'
import { App, IpcRenderer, Shell, Dialog, Clipboard, GlobalShortcut, Screen, AutoUpdater, TouchBar, BrowserWindow, Menu, MenuItem, PowerSaveBlocker, NativeTheme } from 'electron'
import { App, IpcRenderer, Shell, Dialog, Clipboard, GlobalShortcut, Screen, AutoUpdater, TouchBar, BrowserWindow, Menu, MenuItem, PowerSaveBlocker } from 'electron'
import * as remote from '@electron/remote'
export interface MessageBoxResponse {
@@ -20,7 +20,6 @@ export class ElectronService {
process: any
autoUpdater: AutoUpdater
powerSaveBlocker: PowerSaveBlocker
nativeTheme: NativeTheme
TouchBar: typeof TouchBar
BrowserWindow: typeof BrowserWindow
Menu: typeof Menu
@@ -44,7 +43,5 @@ export class ElectronService {
this.BrowserWindow = remote.BrowserWindow
this.Menu = remote.Menu
this.MenuItem = remote.MenuItem
this.MenuItem = remote.MenuItem
this.nativeTheme = remote.nativeTheme
}
}

View File

@@ -10,8 +10,6 @@ import { ElectronService } from '../services/electron.service'
import { ElectronHostWindow } from './hostWindow.service'
import { ShellIntegrationService } from './shellIntegration.service'
import { ElectronHostAppService } from './hostApp.service'
import { PlatformTheme } from '../../../tabby-core/src/api/platform'
import { configPath } from '../../../app/lib/config'
const fontManager = require('fontmanager-redux') // eslint-disable-line
/* eslint-disable block-scoped-var */
@@ -37,15 +35,11 @@ export class ElectronPlatformService extends PlatformService {
private translate: TranslateService,
) {
super()
this.configPath = configPath
this.configPath = path.join(electron.app.getPath('userData'), 'config.yaml')
electron.ipcRenderer.on('host:display-metrics-changed', () => {
this.zone.run(() => this.displayMetricsChanged.next())
})
electron.nativeTheme.on('updated', () => {
this.zone.run(() => this.themeChanged.next(this.getTheme()))
})
}
readClipboard (): string {
@@ -249,14 +243,6 @@ export class ElectronPlatformService extends PlatformService {
},
)).filePaths[0]
}
getTheme (): PlatformTheme {
if (this.electron.nativeTheme.shouldUseDarkColors) {
return 'dark'
} else {
return 'light'
}
}
}
class ElectronFileUpload extends FileUpload {

View File

@@ -33,7 +33,6 @@ export class ShellIntegrationService {
command: 'paste "%V"',
},
]
private constructor (
private electron: ElectronService,
private hostApp: HostAppService,

View File

@@ -21,7 +21,7 @@ import { RecoveryProvider } from './recoveryProvider'
import { ShellSettingsTabProvider } from './settings'
import { TerminalConfigProvider } from './config'
import { LocalTerminalHotkeyProvider } from './hotkeys'
import { NewTabContextMenu } from './tabContextMenu'
import { NewTabContextMenu, SaveAsProfileContextMenu } from './tabContextMenu'
import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from './cli'
import { LocalProfilesService } from './profiles'
@@ -47,6 +47,7 @@ import { LocalProfilesService } from './profiles'
{ provide: ProfileProvider, useClass: LocalProfilesService, multi: true },
{ provide: TabContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
{ provide: TabContextMenuItemProvider, useClass: SaveAsProfileContextMenu, multi: true },
{ provide: CLIHandler, useClass: TerminalCLIHandler, multi: true },
{ provide: CLIHandler, useClass: OpenPathCLIHandler, multi: true },

View File

@@ -1,9 +1,59 @@
import { Inject, Injectable, Optional } from '@angular/core'
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, MenuItemOptions, ProfilesService, TranslateService } from 'tabby-core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, NotificationsService, MenuItemOptions, ProfilesService, PromptModalComponent, TranslateService } from 'tabby-core'
import { TerminalTabComponent } from './components/terminalTab.component'
import { TerminalService } from './services/terminal.service'
import { LocalProfile, UACService } from './api'
/** @hidden */
@Injectable()
export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
constructor (
private config: ConfigService,
private ngbModal: NgbModal,
private notifications: NotificationsService,
private translate: TranslateService,
) {
super()
}
async getItems (tab: BaseTabComponent): Promise<MenuItemOptions[]> {
if (!(tab instanceof TerminalTabComponent)) {
return []
}
const terminalTab = tab
const items: MenuItemOptions[] = [
{
label: this.translate.instant('Save as profile'),
click: async () => {
const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('New profile name')
const name = (await modal.result)?.value
if (!name) {
return
}
const profile = {
options: {
...terminalTab.profile.options,
cwd: await terminalTab.session?.getWorkingDirectory() ?? terminalTab.profile.options.cwd,
},
name,
type: 'local',
}
this.config.store.profiles = [
...this.config.store.profiles,
profile,
]
this.config.save()
this.notifications.info(this.translate.instant('Saved'))
},
},
]
return items
}
}
/** @hidden */
@Injectable()
export class NewTabContextMenu extends TabContextMenuItemProvider {

View File

@@ -70,7 +70,6 @@ export class PluginManagerService {
map(plugins => {
const mapping: Record<string, PluginInfo[]> = {}
for (const p of plugins) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
mapping[p.name] ??= []
mapping[p.name].push(p)
}

View File

@@ -3,10 +3,10 @@ import { SerialPortStream } from '@serialport/stream'
import { LogService, NotificationsService } from 'tabby-core'
import { Subject, Observable } from 'rxjs'
import { Injector, NgZone } from '@angular/core'
import { BaseSession, ConnectableTerminalProfile, InputProcessingOptions, InputProcessor, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal'
import { BaseSession, BaseTerminalProfile, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal'
import { SerialService } from './services/serial.service'
export interface SerialProfile extends ConnectableTerminalProfile {
export interface SerialProfile extends BaseTerminalProfile {
options: SerialProfileOptions
}
@@ -21,7 +21,6 @@ export interface SerialProfileOptions extends StreamProcessingOptions, LoginScri
xoff?: boolean
xany?: boolean
slowSend?: boolean
input: InputProcessingOptions,
}
export const BAUD_RATES = [
@@ -66,7 +65,6 @@ export class SerialSession extends BaseSession {
}
this.middleware.push(new UTF8SplitterMiddleware())
this.middleware.push(new InputProcessor(profile.options.input))
this.setLoginScriptsOptions(profile.options)
}

View File

@@ -87,19 +87,9 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
.description(translate) Sends data one byte at a time
toggle([(ngModel)]='profile.options.slowSend')
li(ngbNavItem)
a(ngbNavLink, translate) Colors
ng-template(ngbNavContent)
color-scheme-selector([(model)]='profile.terminalColorScheme')
li(ngbNavItem)
a(ngbNavLink, translate) Login scripts
ng-template(ngbNavContent)
login-scripts-settings([options]='profile.options')
li(ngbNavItem)
a(ngbNavLink, translate) Input
ng-template(ngbNavContent)
input-processing-settings([options]='profile.options.input')
div([ngbNavOutlet]='nav')

View File

@@ -2,14 +2,14 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
import slugify from 'slugify'
import deepClone from 'clone-deep'
import { Injectable } from '@angular/core'
import { NewTabParameters, SelectorService, HostAppService, Platform, TranslateService, ConnectableProfileProvider } from 'tabby-core'
import { ProfileProvider, NewTabParameters, SelectorService, HostAppService, Platform, TranslateService } from 'tabby-core'
import { SerialProfileSettingsComponent } from './components/serialProfileSettings.component'
import { SerialTabComponent } from './components/serialTab.component'
import { SerialService } from './services/serial.service'
import { BAUD_RATES, SerialProfile } from './api'
@Injectable({ providedIn: 'root' })
export class SerialProfilesService extends ConnectableProfileProvider<SerialProfile> {
export class SerialProfilesService extends ProfileProvider<SerialProfile> {
id = 'serial'
name = _('Serial')
settingsComponent = SerialProfileSettingsComponent
@@ -30,9 +30,7 @@ export class SerialProfilesService extends ConnectableProfileProvider<SerialProf
outputNewlines: null,
scripts: [],
slowSend: false,
input: { backspace: 'backspace' },
},
clearServiceMessagesOnConnect: false,
}
constructor (

View File

@@ -18,8 +18,8 @@
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
"@types/marked": "^5.0.1",
"marked": "^5.1.2",
"@types/marked": "^4.0.8",
"marked": "^4.2.12",
"ngx-infinite-scroll": "^16"
},
"peerDependencies": {

View File

@@ -59,7 +59,7 @@ export class ConfigSyncSettingsTabComponent extends BaseComponent {
const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('Name for the new config')
modal.componentInstance.value = name
name = (await modal.result.catch(() => null))?.value
name = (await modal.result)?.value
if (!name) {
return
}

View File

@@ -1,32 +0,0 @@
.modal-header
h3.m-0 {{group.name}}
.modal-body
.row
.col-12.col-lg-4
.mb-3
label(translate) Name
input.form-control(
type='text',
autofocus,
[(ngModel)]='group.name',
)
.col-12.col-lg-8
.form-line.content-box
.header
.title(translate) Default profile group settings
.description(translate) These apply to all profiles of a given type in this group
.list-group.mt-3.mb-3.content-box
a.list-group-item.list-group-item-action.d-flex.align-items-center(
(click)='editDefaults(provider)',
*ngFor='let provider of providers'
) {{provider.name|translate}}
.me-auto
button.btn.btn-link.hover-reveal.ms-1((click)='$event.stopPropagation(); deleteDefaults(provider)')
i.fas.fa-trash-arrow-up
.modal-footer
button.btn.btn-primary((click)='save()', translate) Save
button.btn.btn-danger((click)='cancel()', translate) Cancel

View File

@@ -1,54 +0,0 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigProxy, ProfileGroup, Profile, ProfileProvider, PlatformService, TranslateService } from 'tabby-core'
/** @hidden */
@Component({
templateUrl: './editProfileGroupModal.component.pug',
})
export class EditProfileGroupModalComponent<G extends ProfileGroup> {
@Input() group: G & ConfigProxy
@Input() providers: ProfileProvider<Profile>[]
constructor (
private modalInstance: NgbActiveModal,
private platform: PlatformService,
private translate: TranslateService,
) {}
save () {
this.modalInstance.close({ group: this.group })
}
cancel () {
this.modalInstance.dismiss()
}
editDefaults (provider: ProfileProvider<Profile>) {
this.modalInstance.close({ group: this.group, provider })
}
async deleteDefaults (provider: ProfileProvider<Profile>): Promise<void> {
if ((await this.platform.showMessageBox(
{
type: 'warning',
message: this.translate.instant('Restore settings to inherited defaults ?'),
buttons: [
this.translate.instant('Delete'),
this.translate.instant('Keep'),
],
defaultId: 1,
cancelId: 1,
},
)).response === 0) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete this.group.defaults?.[provider.id]
}
}
}
export interface EditProfileGroupModalComponentResult<G extends ProfileGroup> {
group: G
provider?: ProfileProvider<Profile>
}

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