mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-02 07:26:58 +00:00
Compare commits
1 Commits
v1.0.201
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5006b60b13 |
@@ -1184,60 +1184,6 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"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,
|
"contributorsPerLine": 7,
|
||||||
@@ -1246,6 +1192,5 @@
|
|||||||
"repoType": "github",
|
"repoType": "github",
|
||||||
"repoHost": "https://github.com",
|
"repoHost": "https://github.com",
|
||||||
"commitConvention": "none",
|
"commitConvention": "none",
|
||||||
"skipCi": true,
|
"skipCi": true
|
||||||
"commitType": "docs"
|
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,7 @@
|
|||||||
settings:
|
settings:
|
||||||
import/parsers:
|
|
||||||
'@typescript-eslint/parser': ['.ts']
|
|
||||||
import/resolver:
|
import/resolver:
|
||||||
typescript:
|
typescript: true
|
||||||
project:
|
|
||||||
- tsconfig.json
|
|
||||||
- tabby-*/tsconfig.json
|
|
||||||
node: true
|
node: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
browser: true
|
browser: true
|
||||||
es6: true
|
es6: true
|
||||||
@@ -34,7 +28,7 @@ overrides:
|
|||||||
- plugin:import/typescript
|
- plugin:import/typescript
|
||||||
plugins:
|
plugins:
|
||||||
- '@typescript-eslint'
|
- '@typescript-eslint'
|
||||||
- import
|
- 'import'
|
||||||
rules:
|
rules:
|
||||||
'@typescript-eslint/semi':
|
'@typescript-eslint/semi':
|
||||||
- error
|
- error
|
||||||
@@ -136,7 +130,6 @@ overrides:
|
|||||||
'@typescript-eslint/naming-convention': off
|
'@typescript-eslint/naming-convention': off
|
||||||
'@typescript-eslint/lines-between-class-members':
|
'@typescript-eslint/lines-between-class-members':
|
||||||
- error
|
- error
|
||||||
- always
|
|
||||||
- exceptAfterSingleLine: true
|
- exceptAfterSingleLine: true
|
||||||
'@typescript-eslint/dot-notation': off
|
'@typescript-eslint/dot-notation': off
|
||||||
'@typescript-eslint/no-implicit-any-catch': off
|
'@typescript-eslint/no-implicit-any-catch': off
|
||||||
@@ -159,6 +152,3 @@ overrides:
|
|||||||
'@typescript-eslint/consistent-generic-constructors': off
|
'@typescript-eslint/consistent-generic-constructors': off
|
||||||
'keyword-spacing': off
|
'keyword-spacing': off
|
||||||
'@typescript-eslint/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
|
|
||||||
|
214
.github/workflows/build.yml
vendored
214
.github/workflows/build.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Installing Node
|
- name: Installing Node
|
||||||
uses: actions/setup-node@v3.7.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Installing Node
|
- name: Installing Node
|
||||||
uses: actions/setup-node@v3.7.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
|
|
||||||
@@ -86,7 +86,6 @@ jobs:
|
|||||||
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
||||||
CSC_LINK: ${{ secrets.CSC_LINK }}
|
CSC_LINK: ${{ secrets.CSC_LINK }}
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
|
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
|
||||||
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
|
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
|
||||||
USE_HARD_LINKS: false
|
USE_HARD_LINKS: false
|
||||||
@@ -110,16 +109,16 @@ jobs:
|
|||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifact-dmg
|
mkdir artifact-pkg
|
||||||
mv dist/*.dmg artifact-dmg/
|
mv dist/*.pkg artifact-pkg/
|
||||||
mkdir artifact-zip
|
mkdir artifact-zip
|
||||||
mv dist/*.zip artifact-zip/
|
mv dist/*.zip artifact-zip/
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload DMG
|
name: Upload PKG
|
||||||
with:
|
with:
|
||||||
name: macOS .dmg (${{matrix.arch}})
|
name: macOS .pkg (${{matrix.arch}})
|
||||||
path: artifact-dmg
|
path: artifact-pkg
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload ZIP
|
name: Upload ZIP
|
||||||
@@ -132,21 +131,7 @@ jobs:
|
|||||||
needs: Lint
|
needs: Lint
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
build-arch: [ x64, arm64, armv7l ]
|
||||||
- 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}}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -154,66 +139,35 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install Node
|
- name: Set up multiarch/qemu-user-static
|
||||||
uses: actions/setup-node@v3.7.0
|
run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||||
with:
|
if: matrix.build-arch != 'x64'
|
||||||
node-version: 18
|
|
||||||
|
|
||||||
- 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: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install libarchive-tools zsh
|
sudo apt-get install libarchive-tools zsh
|
||||||
|
|
||||||
- name: Install npm_modules (amd64)
|
|
||||||
run: |
|
|
||||||
npm i -g yarn
|
npm i -g yarn
|
||||||
yarn --network-timeout 1000000
|
yarn --network-timeout 1000000
|
||||||
if: matrix.build-arch == 'x64'
|
if: matrix.build-arch == 'x64'
|
||||||
|
|
||||||
- name: Setup Crossbuild (${{matrix.arch}})
|
- name: Webpack (x64)
|
||||||
run: |
|
run: yarn run build
|
||||||
sudo apt-get update -y && sudo apt-get install schroot sbuild debootstrap -y
|
if: matrix.build-arch == 'x64'
|
||||||
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
|
|
||||||
|
|
||||||
if: matrix.build-arch != 'x64'
|
- name: Prepackage plugins (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}})
|
|
||||||
run: scripts/prepackage-plugins.mjs
|
run: scripts/prepackage-plugins.mjs
|
||||||
|
if: ${{matrix.build-arch == 'x64'}}
|
||||||
|
|
||||||
- name: Build packages (${{matrix.arch}})
|
- name: Build packages (x64)
|
||||||
run: scripts/build-linux.mjs
|
run: scripts/build-linux.mjs
|
||||||
|
if: ${{matrix.build-arch == 'x64'}}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
||||||
@@ -224,54 +178,54 @@ jobs:
|
|||||||
run: zsh -c 'tar czf tabby-web.tar.gz (tabby-*|web)/dist'
|
run: zsh -c 'tar czf tabby-web.tar.gz (tabby-*|web)/dist'
|
||||||
if: matrix.build-arch == 'x64'
|
if: matrix.build-arch == 'x64'
|
||||||
|
|
||||||
# - name: Install deps and Build (arm64)
|
- name: Install deps and Build (arm64)
|
||||||
# uses: docker://multiarch/ubuntu-core:arm64-bionic
|
uses: docker://multiarch/ubuntu-core:arm64-bionic
|
||||||
# with:
|
with:
|
||||||
# args: >
|
args: >
|
||||||
# bash -c
|
bash -c
|
||||||
# "apt update && apt install curl lsb-release gnupg -y &&
|
"apt update && apt install curl lsb-release gnupg -y &&
|
||||||
# curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&
|
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 &&
|
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 &&
|
git config --global --add safe.directory /github/workspace &&
|
||||||
# gem install public_suffix -v 4.0.7 &&
|
gem install public_suffix -v 4.0.7 &&
|
||||||
# gem install fpm --no-document &&
|
gem install fpm --no-document &&
|
||||||
# npm i -g yarn &&
|
npm i -g yarn &&
|
||||||
# cd /github/workspace &&
|
cd /github/workspace &&
|
||||||
# yarn --network-timeout 1000000 &&
|
yarn --network-timeout 1000000 &&
|
||||||
# yarn run build &&
|
yarn run build &&
|
||||||
# scripts/prepackage-plugins.mjs &&
|
scripts/prepackage-plugins.mjs &&
|
||||||
# USE_SYSTEM_FPM=true scripts/build-linux.mjs"
|
USE_SYSTEM_FPM=true scripts/build-linux.mjs"
|
||||||
# env:
|
env:
|
||||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
||||||
# USE_HARD_LINKS: false
|
USE_HARD_LINKS: false
|
||||||
# if: matrix.build-arch == 'arm64' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
|
if: matrix.build-arch == 'arm64' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
|
||||||
|
|
||||||
# - name: Install deps and Build (armv7l)
|
- name: Install deps and Build (armv7l)
|
||||||
# uses: docker://multiarch/ubuntu-core:armhf-bionic
|
uses: docker://multiarch/ubuntu-core:armhf-bionic
|
||||||
# with:
|
with:
|
||||||
# args: >
|
args: >
|
||||||
# bash -c
|
bash -c
|
||||||
# "apt update && apt install curl lsb-release gnupg -y &&
|
"apt update && apt install curl lsb-release gnupg -y &&
|
||||||
# curl -fsSL https://deb.nodesource.com/setup_16.x | bash - &&
|
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 &&
|
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 &&
|
git config --global --add safe.directory /github/workspace &&
|
||||||
# gem install public_suffix -v 4.0.7 &&
|
gem install public_suffix -v 4.0.7 &&
|
||||||
# gem install fpm --no-document &&
|
gem install fpm --no-document &&
|
||||||
# npm i -g yarn &&
|
npm i -g yarn &&
|
||||||
# cd /github/workspace &&
|
cd /github/workspace &&
|
||||||
# sed -i '/ \"electron\":/c\ \"electron\": \"17.0.0\",' package.json &&
|
sed -i '/ \"electron\":/c\ \"electron\": \"17.0.0\",' package.json &&
|
||||||
# yarn --network-timeout 1000000 &&
|
yarn --network-timeout 1000000 &&
|
||||||
# yarn run build &&
|
yarn run build &&
|
||||||
# scripts/prepackage-plugins.mjs &&
|
scripts/prepackage-plugins.mjs &&
|
||||||
# USE_SYSTEM_FPM=true scripts/build-linux.mjs"
|
USE_SYSTEM_FPM=true scripts/build-linux.mjs"
|
||||||
# env:
|
env:
|
||||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
KEYGEN_TOKEN: ${{ secrets.KEYGEN_TOKEN }}
|
||||||
# USE_HARD_LINKS: false
|
USE_HARD_LINKS: false
|
||||||
# if: matrix.build-arch == 'arm' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
|
if: matrix.build-arch == 'armv7l' && github.repository == 'Eugeny/tabby' && startsWith(github.ref, 'refs/tags')
|
||||||
|
|
||||||
- name: Upload symbols (amd64 only)
|
- name: Upload symbols
|
||||||
run: |
|
run: |
|
||||||
sudo npm install -g @sentry/cli --unsafe-perm
|
sudo npm install -g @sentry/cli --unsafe-perm
|
||||||
./scripts/sentry-upload.mjs
|
./scripts/sentry-upload.mjs
|
||||||
@@ -291,37 +245,31 @@ jobs:
|
|||||||
dir: 'dist'
|
dir: 'dist'
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload AppImage (${{matrix.arch}})
|
name: Upload DEB
|
||||||
with:
|
with:
|
||||||
name: Linux AppImage (${{matrix.arch}})
|
name: Linux DEB (${{matrix.build-arch}})
|
||||||
path: dist/*.AppImage
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
|
||||||
name: Upload DEB (${{matrix.arch}})
|
|
||||||
with:
|
|
||||||
name: Linux DEB (${{matrix.arch}})
|
|
||||||
path: dist/*.deb
|
path: dist/*.deb
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload RPM (${{matrix.arch}})
|
name: Upload RPM
|
||||||
with:
|
with:
|
||||||
name: Linux RPM (${{matrix.arch}})
|
name: Linux RPM (${{matrix.build-arch}})
|
||||||
path: dist/*.rpm
|
path: dist/*.rpm
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload Pacman Package (${{matrix.arch}})
|
name: Upload Pacman Package
|
||||||
with:
|
with:
|
||||||
name: Linux Pacman (${{matrix.arch}})
|
name: Linux Pacman (${{matrix.build-arch}})
|
||||||
path: dist/*.pacman
|
path: dist/*.pacman
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload Linux tarball (${{matrix.arch}})
|
name: Upload Linux tarball
|
||||||
with:
|
with:
|
||||||
name: Linux tarball (${{matrix.arch}})
|
name: Linux tarball (${{matrix.build-arch}})
|
||||||
path: dist/*.tar.gz
|
path: dist/*.tar.gz
|
||||||
|
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
name: Upload web tarball (amd64 only)
|
name: Upload web tarball
|
||||||
with:
|
with:
|
||||||
name: Web tarball
|
name: Web tarball
|
||||||
path: tabby-web.tar.gz
|
path: tabby-web.tar.gz
|
||||||
@@ -345,7 +293,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Installing Node
|
- name: Installing Node
|
||||||
uses: actions/setup-node@v3.7.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
|
|
||||||
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Installing Node
|
- name: Installing Node
|
||||||
uses: actions/setup-node@v3.7.0
|
uses: actions/setup-node@v3.6.0
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
|
|
||||||
|
@@ -17,6 +17,8 @@ First, from within the `tabby` directory install the dependencies via yarn:
|
|||||||
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)
|
# 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
|
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
|
||||||
|
@@ -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
|
* [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
|
* [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
|
* [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>
|
<a name="themes"></a>
|
||||||
|
|
||||||
@@ -322,14 +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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -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
|
* [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
|
* [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
|
* [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>
|
<a name="themes"></a>
|
||||||
|
|
||||||
# Temas
|
# 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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -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
|
* [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
|
* [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
|
* [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>
|
<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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -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
|
* [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
|
* [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
|
* [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>
|
<a name="themes"></a>
|
||||||
# Temi
|
# Temi
|
||||||
@@ -317,14 +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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -127,7 +127,6 @@ Windows上では、`Tabby.exe`がある場所と同じ場所に`data`フォル
|
|||||||
* [clippy](https://github.com/Eugeny/tabby-clippy) - プラグインの作例として、いつも厄介なあいつが出てくるプラグイン
|
* [clippy](https://github.com/Eugeny/tabby-clippy) - プラグインの作例として、いつも厄介なあいつが出てくるプラグイン
|
||||||
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 指定された設定からカスタマイズされたワークスペースを作成することができます
|
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 指定された設定からカスタマイズされたワークスペースを作成することができます
|
||||||
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - Tabby内の端末で選択したテキストを既定ブラウザで開くことができます。
|
* [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>
|
<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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -111,7 +111,6 @@
|
|||||||
* [clippy](https://github.com/Eugeny/tabby-clippy) - 항상 당신을 귀찮게 하는 예제 플러그인
|
* [clippy](https://github.com/Eugeny/tabby-clippy) - 항상 당신을 귀찮게 하는 예제 플러그인
|
||||||
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 주어진 구성을 기반으로 사용자 정의 작업 공간 프로필을 생성할 수 있습니다
|
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 주어진 구성을 기반으로 사용자 정의 작업 공간 프로필을 생성할 수 있습니다
|
||||||
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - Tabby의 탭에서 선택한 텍스트로 기본 시스템 브라우저를 엽니다
|
* [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>
|
<a name="themes"></a>
|
||||||
# 테마
|
# 테마
|
||||||
@@ -311,14 +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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
12
README.md
12
README.md
@@ -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 SSH and Telnet client and connection manager
|
||||||
* Integrated serial terminal
|
* 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
|
* [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
|
* [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
|
* [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>
|
<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)
|
* [gruvbox](https://github.com/porkloin/terminus-theme-gruvbox)
|
||||||
* [windows10](https://www.npmjs.com/package/terminus-theme-windows10)
|
* [windows10](https://www.npmjs.com/package/terminus-theme-windows10)
|
||||||
* [altair](https://github.com/yxuko/terminus-altair)
|
* [altair](https://github.com/yxuko/terminus-altair)
|
||||||
* [catppuccin](https://github.com/catppuccin/tabby) - Soothing pastel theme for Tabby
|
|
||||||
|
|
||||||
# Sponsors <!-- omit in toc -->
|
# Sponsors <!-- omit in toc -->
|
||||||
|
|
||||||
@@ -334,14 +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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -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
|
* [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
|
* [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
|
* [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>
|
<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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -117,7 +117,6 @@
|
|||||||
* [clippy](https://github.com/Eugeny/tabby-clippy) — плагин-пример, который постоянно будет вас бесить;
|
* [clippy](https://github.com/Eugeny/tabby-clippy) — плагин-пример, который постоянно будет вас бесить;
|
||||||
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) — позволяет создавать пользовательские провили рабочего окружеиня на основе конфига;
|
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) — позволяет создавать пользовательские провили рабочего окружеиня на основе конфига;
|
||||||
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) — открывает браузер по умолчанию с текстом, выделенном во вкладке Tabby.
|
* [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>
|
<a name="themes"></a>
|
||||||
# Темы
|
# Темы
|
||||||
@@ -317,14 +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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -116,7 +116,6 @@
|
|||||||
* [clippy](https://github.com/Eugeny/tabby-clippy) - 一个可以一直烦你的示例插件
|
* [clippy](https://github.com/Eugeny/tabby-clippy) - 一个可以一直烦你的示例插件
|
||||||
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 允许根据给定的配置创建自定义工作区配置文件
|
* [workspace-manager](https://github.com/composer404/tabby-workspace-manager) - 允许根据给定的配置创建自定义工作区配置文件
|
||||||
* [search-in-browser](https://github.com/composer404/tabby-search-in-browser) - 从 Tabby 标签页带有选中的文本来打开系统默认浏览器
|
* [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>
|
<a name="themes"></a>
|
||||||
# 主题
|
# 主题
|
||||||
@@ -316,14 +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="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://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/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>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -183,7 +183,7 @@ export class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enableTray (): void {
|
enableTray (): void {
|
||||||
if (!!this.tray || process.platform === 'linux') {
|
if (this.tray || process.platform === 'linux') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as yaml from 'js-yaml'
|
import * as yaml from 'js-yaml'
|
||||||
|
import { app } from 'electron'
|
||||||
import { writeFile } from 'atomically'
|
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 {
|
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) && (
|
if (fs.existsSync(legacyConfigPath) && (
|
||||||
!fs.existsSync(configPath) ||
|
!fs.existsSync(configPath) ||
|
||||||
fs.statSync(configPath).mtime < fs.statSync(legacyConfigPath).mtime
|
fs.statSync(configPath).mtime < fs.statSync(legacyConfigPath).mtime
|
||||||
@@ -20,6 +19,7 @@ export function migrateConfig (): void {
|
|||||||
export function loadConfig (): any {
|
export function loadConfig (): any {
|
||||||
migrateConfig()
|
migrateConfig()
|
||||||
|
|
||||||
|
const configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||||
if (fs.existsSync(configPath)) {
|
if (fs.existsSync(configPath)) {
|
||||||
return yaml.load(fs.readFileSync(configPath, 'utf8'))
|
return yaml.load(fs.readFileSync(configPath, 'utf8'))
|
||||||
} else {
|
} 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> {
|
export async function saveConfig (content: string): Promise<void> {
|
||||||
await writeFile(configPath, content, { encoding: 'utf8' })
|
await writeFile(configPath, content, { encoding: 'utf8' })
|
||||||
await writeFile(configPath + '.backup', content, { encoding: 'utf8' })
|
await writeFile(configPath + '.backup', content, { encoding: 'utf8' })
|
||||||
|
@@ -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 'v8-compile-cache'
|
||||||
import './portable'
|
import './portable'
|
||||||
import 'source-map-support/register'
|
import 'source-map-support/register'
|
||||||
import './sentry'
|
import './sentry'
|
||||||
import './lru'
|
import './lru'
|
||||||
|
import { app, ipcMain, Menu, dialog } from 'electron'
|
||||||
import { parseArgs } from './cli'
|
import { parseArgs } from './cli'
|
||||||
import { Application } from './app'
|
import { Application } from './app'
|
||||||
import electronDebug = require('electron-debug')
|
import electronDebug = require('electron-debug')
|
||||||
import { loadConfig } from './config'
|
import { loadConfig } from './config'
|
||||||
|
|
||||||
|
if (!process.env.TABBY_PLUGINS) {
|
||||||
|
process.env.TABBY_PLUGINS = ''
|
||||||
|
}
|
||||||
|
|
||||||
const argv = parseArgs(process.argv, process.cwd())
|
const argv = parseArgs(process.argv, process.cwd())
|
||||||
|
|
||||||
|
@@ -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 { v4 as uuidv4 } from 'uuid'
|
||||||
import { ipcMain } from 'electron'
|
import { ipcMain } from 'electron'
|
||||||
import { Application } from './app'
|
import { Application } from './app'
|
||||||
|
@@ -92,11 +92,8 @@ export class Window {
|
|||||||
if (this.configStore.appearance?.frame === 'native') {
|
if (this.configStore.appearance?.frame === 'native') {
|
||||||
bwOptions.frame = true
|
bwOptions.frame = true
|
||||||
} else {
|
} else {
|
||||||
bwOptions.titleBarStyle = 'hidden'
|
if (process.platform === 'darwin') {
|
||||||
if (process.platform === 'win32') {
|
bwOptions.titleBarStyle = 'hidden'
|
||||||
bwOptions.titleBarOverlay = {
|
|
||||||
color: '#00000000',
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,22 +384,6 @@ export class Window {
|
|||||||
this.setVibrancy(enabled, type)
|
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) => {
|
ipcMain.on('window-set-title', (event, title) => {
|
||||||
if (!this.window || event.sender !== this.window.webContents) {
|
if (!this.window || event.sender !== this.window.webContents) {
|
||||||
return
|
return
|
||||||
@@ -461,7 +442,7 @@ export class Window {
|
|||||||
this.window.on('resize', onBoundsChange)
|
this.window.on('resize', onBoundsChange)
|
||||||
|
|
||||||
ipcMain.on('window-set-traffic-light-position', (_event, x, y) => {
|
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) => {
|
ipcMain.on('window-set-opacity', (_event, opacity) => {
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "2.0.10",
|
"@electron/remote": "2.0.10",
|
||||||
"node-pty": "^1.0",
|
"@tabby-gang/node-pty": "^0.11.0-beta.203",
|
||||||
"any-promise": "^1.3.0",
|
"any-promise": "^1.3.0",
|
||||||
"electron-config": "2.0.0",
|
"electron-config": "2.0.0",
|
||||||
"electron-debug": "^3.2.0",
|
"electron-debug": "^3.2.0",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"@tabby-gang/windows-blurbehind": "^3.0.0",
|
"@tabby-gang/windows-blurbehind": "^3.0.0",
|
||||||
"macos-native-processlist": "^2.1.0",
|
"macos-native-processlist": "^2.1.0",
|
||||||
"patch-package": "^6.5.0",
|
"patch-package": "^6.5.0",
|
||||||
"serialport": "11.0.1",
|
"serialport": "11.0.0",
|
||||||
"serialport-binding-webserialapi": "^1.0.3",
|
"serialport-binding-webserialapi": "^1.0.3",
|
||||||
"windows-native-registry": "^3.2.1",
|
"windows-native-registry": "^3.2.1",
|
||||||
"windows-process-tree": "^0.4.0"
|
"windows-process-tree": "^0.4.0"
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"@ngx-translate/core": "^14.0.0",
|
"@ngx-translate/core": "^14.0.0",
|
||||||
"@types/mz": "2.7.4",
|
"@types/mz": "2.7.4",
|
||||||
"@types/node": "20.3.1",
|
"@types/node": "20.3.1",
|
||||||
"atomically": "^2.0.2",
|
"atomically": "^1.7.0",
|
||||||
"filesize": "^9",
|
"filesize": "^9",
|
||||||
"ngx-filesize": "^3.0.2"
|
"ngx-filesize": "^3.0.2"
|
||||||
},
|
},
|
||||||
|
@@ -47,7 +47,7 @@ const config = {
|
|||||||
mz: 'commonjs mz',
|
mz: 'commonjs mz',
|
||||||
npm: 'commonjs npm',
|
npm: 'commonjs npm',
|
||||||
'node:os': 'commonjs os',
|
'node:os': 'commonjs os',
|
||||||
'node-pty': 'commonjs node-pty',
|
'@tabby-gang/node-pty': 'commonjs @tabby-gang/node-pty',
|
||||||
path: 'commonjs path',
|
path: 'commonjs path',
|
||||||
util: 'commonjs util',
|
util: 'commonjs util',
|
||||||
'source-map-support': 'commonjs source-map-support',
|
'source-map-support': 'commonjs source-map-support',
|
||||||
|
173
app/yarn.lock
173
app/yarn.lock
@@ -38,13 +38,13 @@
|
|||||||
"@serialport/bindings-interface" "^1.2.1"
|
"@serialport/bindings-interface" "^1.2.1"
|
||||||
debug "^4.3.3"
|
debug "^4.3.3"
|
||||||
|
|
||||||
"@serialport/bindings-cpp@11.0.3":
|
"@serialport/bindings-cpp@11.0.1":
|
||||||
version "11.0.3"
|
version "11.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/bindings-cpp/-/bindings-cpp-11.0.3.tgz#ab4d4826ef657e326b6c99d6b8a113d834378a93"
|
resolved "https://registry.yarnpkg.com/@serialport/bindings-cpp/-/bindings-cpp-11.0.1.tgz#38afa6105ceb7888c6a2af2782822fca9130d65a"
|
||||||
integrity sha512-xgNDJ7pHHZCJMoDsEH+D8q5CV+V3RGN4/jLEG9SQ7q6kh+o03axV0l/upPHZ0HW4tTXpGgqPIGbXOTrD4RGQQA==
|
integrity sha512-3I1mniVg3osYuIUXxU0jB5AHPsxWmErmc3JC3WfUSlfXsjWMHkHfFzbW9Scuv/z/6DLCJIDyltabRa2FoW2qsQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@serialport/bindings-interface" "1.2.2"
|
"@serialport/bindings-interface" "1.2.2"
|
||||||
"@serialport/parser-readline" "11.0.0"
|
"@serialport/parser-readline" "10.5.0"
|
||||||
debug "4.3.4"
|
debug "4.3.4"
|
||||||
node-addon-api "6.1.0"
|
node-addon-api "6.1.0"
|
||||||
node-gyp-build "4.6.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"
|
resolved "https://registry.yarnpkg.com/@serialport/bindings-interface/-/bindings-interface-1.2.1.tgz#1ee80b0951ef4e4fd8a5a186621feff046aa2faf"
|
||||||
integrity sha512-63Dyqz2gtryRDDckFusOYqLYhR3Hq/M4sEdbF9i/VsvDb6T+tNVgoAKUZ+FMrXXKnCSu+hYbk+MTc0XQANszxw==
|
integrity sha512-63Dyqz2gtryRDDckFusOYqLYhR3Hq/M4sEdbF9i/VsvDb6T+tNVgoAKUZ+FMrXXKnCSu+hYbk+MTc0XQANszxw==
|
||||||
|
|
||||||
"@serialport/parser-byte-length@11.0.1":
|
"@serialport/parser-byte-length@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-11.0.1.tgz#26e4f3b2d66aaac0859b18a57c648d0eec78392a"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-byte-length/-/parser-byte-length-11.0.0.tgz#074e6ed6b18d7a61edc75dba22d3115e8f37dd8c"
|
||||||
integrity sha512-UsffR5b3NHwhjJzsWv5fZMkoq3wGNyUcRTA9jlu02w+2kMlBRJPzlPVB5szVX0VWUEqkCg+3VaU2XWuYr+uAUA==
|
integrity sha512-rExsdFKdzOIHOBqTwzxUF1A9nrluVIZKZOtvMq5i0Hc3euooGdmkx0VXYNRlI2rd6kJLTL2P+uIR+ZtCTRyT+w==
|
||||||
|
|
||||||
"@serialport/parser-cctalk@11.0.1":
|
"@serialport/parser-cctalk@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-11.0.1.tgz#70c5ccc8fc5ebbe5c317005791155d3b2812efa6"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-cctalk/-/parser-cctalk-11.0.0.tgz#6a5e2b299e8f1ef00308980e45ecdae23825181e"
|
||||||
integrity sha512-klzVQfRcC1m0SVDV2Dy9hHfwweO2/mUMUyuXK04FRkKHy5/AdETmk9KTVVVVfpDCSysvHoyQPwiDFq8ddwX3cQ==
|
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":
|
"@serialport/parser-delimiter@11.0.0":
|
||||||
version "11.0.0"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-11.0.0.tgz#e830c6bb49723d4446131277dc3243b502d09388"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-11.0.0.tgz#e830c6bb49723d4446131277dc3243b502d09388"
|
||||||
integrity sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==
|
integrity sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==
|
||||||
|
|
||||||
"@serialport/parser-delimiter@11.0.1":
|
"@serialport/parser-inter-byte-timeout@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-delimiter/-/parser-delimiter-11.0.1.tgz#c0bcc24d8060c6b352cbe6003ebe95671ad32221"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-11.0.0.tgz#baf7223bf3d49d159c82386928c763bfecf8f70f"
|
||||||
integrity sha512-NAsYa3OFt2xEnj/+0BRkQP2qkRNbXBPEq6uFJEdNdzcTSF+BTRXkoIRrWBq3N6koovPqW6lnbxc/iJYe5AX/2Q==
|
integrity sha512-RLgqZC50IET6FtEIt6Oi0vdRsesSBWLNwB7ldzR9OzyXKgK0XHRzqKqbB0u5Q+tC5OScdWeiQ2AO6jooKUZtsw==
|
||||||
|
|
||||||
"@serialport/parser-inter-byte-timeout@11.0.1":
|
"@serialport/parser-packet-length@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-11.0.1.tgz#ed6d939eeb3bec94579fb3628dc6dcd0c9a3dd21"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-packet-length/-/parser-packet-length-11.0.0.tgz#ec06934b40b45b8f5eb04ba5527e98a1062c2a20"
|
||||||
integrity sha512-PEFV9dSpW+ptH1rLhdB9KgE+rbJ/FvQiZz0mx+4jkv/Po4g3PNsEEMXfMW0aQVSFVsmitvmE0jHlhGjLv8GQEg==
|
integrity sha512-6ZkOiaCooabpV/EM7ttSRbisbDWpGEf7Yxyr13t28LicYR43THRdjdMZcRnWxEM/jpwfskkLLXAR6wziVpKrlw==
|
||||||
|
|
||||||
"@serialport/parser-packet-length@11.0.1":
|
"@serialport/parser-readline@10.5.0":
|
||||||
version "11.0.1"
|
version "10.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-packet-length/-/parser-packet-length-11.0.1.tgz#9d7982a6eeaf9a5bdfe642ceb287f171ab2965b7"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-10.5.0.tgz#df23365ae7f45679b1735deae26f72ba42802862"
|
||||||
integrity sha512-KwPu8dsAI+eN4fnUS1vVmrOpUtBK4p9L9cHhwn5ZmfcvwvZMHp/J+IEu7xH0g5aM1/8QEoaql26BQP+sZ71NQQ==
|
integrity sha512-0aXJknodcl94W9zSjvU+sLdXiyEG2rqjQmvBWZCr8wJZjWEtv3RgrnYiWq4i2OTOyC8C/oPK8ZjpBjQptRsoJQ==
|
||||||
|
dependencies:
|
||||||
|
"@serialport/parser-delimiter" "10.5.0"
|
||||||
|
|
||||||
"@serialport/parser-readline@11.0.0":
|
"@serialport/parser-readline@11.0.0":
|
||||||
version "11.0.0"
|
version "11.0.0"
|
||||||
@@ -96,37 +103,30 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@serialport/parser-delimiter" "11.0.0"
|
"@serialport/parser-delimiter" "11.0.0"
|
||||||
|
|
||||||
"@serialport/parser-readline@11.0.1":
|
"@serialport/parser-ready@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-readline/-/parser-readline-11.0.1.tgz#e85805ae803c2dc507eefa390abec6a67ceef313"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-11.0.0.tgz#802e7189d9e5d13df70d3aa1559403b72fcfa700"
|
||||||
integrity sha512-wkJ3EI733+yhbi7eBWzs/qn8+cfIBcYQjfrILPNqslAy6VlgdKw+pHoblDFmg78GN0TqGUDSWlTJ65oLEPVp5Q==
|
integrity sha512-lSsCPIctoc5kADCKnZDYBz1j69TsFqtnaWUicBzUAIAoUXpYKeYld8YX5NrvjViuVfIJeiqLZeGjxOWe5fqQqQ==
|
||||||
dependencies:
|
|
||||||
"@serialport/parser-delimiter" "11.0.1"
|
|
||||||
|
|
||||||
"@serialport/parser-ready@11.0.1":
|
"@serialport/parser-regex@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-ready/-/parser-ready-11.0.1.tgz#bba01283a121880641e43c27193e6708fef2907c"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-11.0.0.tgz#bb247297851b1a789f4dde1c4ad48c39d6db7ed6"
|
||||||
integrity sha512-v/bvlgKhrNt+SVLSqlfXCO1HEinfRRMGnzqbpdVCgu2SiWIEenCLjs51JisKVYQoQFcXdP/EHZnzm7NPXHDlAg==
|
integrity sha512-aKuc/+/KE9swahTbYpSuOsQa7LggPx7jhfobJLPVVbAic80OpfCIY+MKr6Ax4R6UtQwF90O5Yk6OEmbbvtEmiA==
|
||||||
|
|
||||||
"@serialport/parser-regex@11.0.1":
|
"@serialport/parser-slip-encoder@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-regex/-/parser-regex-11.0.1.tgz#7833ca6029c8c58eb39dd6fe984756cf09d769b7"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-slip-encoder/-/parser-slip-encoder-11.0.0.tgz#f1c3f56e04c497ca89059c69ea79411b30e8da60"
|
||||||
integrity sha512-Lf3k7qibYqZ0+/wX3UA8fRng3WtQ+UyLpjQhG1COs6OBSq5/I5tYXczfhlrbA0gHo1qzgzr2V2t7m6FoBSc81Q==
|
integrity sha512-3ZI/swd2it20vmu2tzqDbkyE4dqy+kExEDY6T33YQ210HDKPVhqj7FAVGo5P++MZ3dup1of11t4P9UPBNkuJnQ==
|
||||||
|
|
||||||
"@serialport/parser-slip-encoder@11.0.1":
|
"@serialport/parser-spacepacket@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-slip-encoder/-/parser-slip-encoder-11.0.1.tgz#4ba0c335627e3d1203279a5f8a4c1af0c829b7fe"
|
resolved "https://registry.yarnpkg.com/@serialport/parser-spacepacket/-/parser-spacepacket-11.0.0.tgz#7737aaa1397db4bf820160dd2f7dd0c9df5f74a0"
|
||||||
integrity sha512-l4mXsAGzpmPO7+uqKJqtPDW643irfnGEWbiy34FoYvuOs8n0SmiMtgQZFAtvlTNQCRWE2tykF/WG6K/McJthDw==
|
integrity sha512-+hqRckrTEqz+/uAUZY0Tq6YIRyCl4oQOH1MeVzKiFiGNjZP7hDJCDoY7LTr9CeJhxvcT0ItTbtjGBqGumV8fxg==
|
||||||
|
|
||||||
"@serialport/parser-spacepacket@11.0.1":
|
"@serialport/stream@11.0.0":
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@serialport/parser-spacepacket/-/parser-spacepacket-11.0.1.tgz#9e1c372f45433afb9a5dbec7b5a298c710b0455b"
|
resolved "https://registry.yarnpkg.com/@serialport/stream/-/stream-11.0.0.tgz#9887db096b51fabe1919a591b920b06f7580e8ee"
|
||||||
integrity sha512-Lq7fXoOsLOMo4XEt9HB31zV5LhrteXlsOy2o6r39TfRwU6x8Nou9jQMA9vW0a6yPra5zwsHIaNrA6tDOGj2Ozg==
|
integrity sha512-Zty7B8C1H2XRnay2mVmW1ygEHXRHXQDcaC5wAVvOZMbQSc7ye03rMlPvviDS+pGxU2t2A2bMo34CUrRduSBong==
|
||||||
|
|
||||||
"@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==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@serialport/bindings-interface" "1.2.2"
|
"@serialport/bindings-interface" "1.2.2"
|
||||||
debug "4.3.4"
|
debug "4.3.4"
|
||||||
@@ -138,6 +138,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.3.2"
|
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":
|
"@tabby-gang/windows-blurbehind@^3.0.0":
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@tabby-gang/windows-blurbehind/-/windows-blurbehind-3.0.0.tgz#48d409c2eb14a12c867b70de5ee4d6769ef45e8f"
|
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"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz"
|
||||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||||
|
|
||||||
atomically@^2.0.2:
|
atomically@^1.7.0:
|
||||||
version "2.0.2"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/atomically/-/atomically-2.0.2.tgz#e5a6e8021441405b7a1c36d4587e25f7a13545f2"
|
resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
|
||||||
integrity sha512-Xfmb4q5QV7uqTlVdMSTtO5eF4DCHfNOdaPyKlbFShkzeNP+3lj3yjjcbdjSmEY4+pDBKJ9g26aP+ImTe88UHoQ==
|
integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
|
||||||
dependencies:
|
|
||||||
stubborn-fs "^1.2.5"
|
|
||||||
when-exit "^2.0.0"
|
|
||||||
|
|
||||||
aws-sign2@~0.7.0:
|
aws-sign2@~0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
@@ -2260,7 +2264,7 @@ mz@^2.7.0:
|
|||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
thenify-all "^1.0.0"
|
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"
|
version "2.16.0"
|
||||||
resolved "https://codeload.github.com/jkleinsc/nan/tar.gz/6a2f95a6a2209d8aa7542fb18099fd808a802059"
|
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"
|
tar "^4.4.12"
|
||||||
which "^1.3.1"
|
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:
|
nopt@^4.0.1, nopt@^4.0.3:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
|
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/binding-abstract" "^9.0.2"
|
||||||
"@serialport/stream" "^9.0.2"
|
"@serialport/stream" "^9.0.2"
|
||||||
|
|
||||||
serialport@11.0.1:
|
serialport@11.0.0:
|
||||||
version "11.0.1"
|
version "11.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/serialport/-/serialport-11.0.1.tgz#9c7aad877d38124a938a50f89eaef22c44825eae"
|
resolved "https://registry.yarnpkg.com/serialport/-/serialport-11.0.0.tgz#a4114fc60e91b23f133ec459345b7be637b1e8ef"
|
||||||
integrity sha512-j/ntDuewAkqL6g5wKjwV2RTyLBL9cpob8aRd3yLAViYApTsJoYqRleyuzst0OboNTBjBsoxQ4YKYhuYHi1XViQ==
|
integrity sha512-bxs3XejQcOHWpzPAaXMhxVRlbem6fjNUrux3ToqrGvFR6BcjOYhqE5CsHOuutv37kmhmnuHrn+/hN+1BpTmaFg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@serialport/binding-mock" "10.2.2"
|
"@serialport/binding-mock" "10.2.2"
|
||||||
"@serialport/bindings-cpp" "11.0.3"
|
"@serialport/bindings-cpp" "11.0.1"
|
||||||
"@serialport/parser-byte-length" "11.0.1"
|
"@serialport/parser-byte-length" "11.0.0"
|
||||||
"@serialport/parser-cctalk" "11.0.1"
|
"@serialport/parser-cctalk" "11.0.0"
|
||||||
"@serialport/parser-delimiter" "11.0.1"
|
"@serialport/parser-delimiter" "11.0.0"
|
||||||
"@serialport/parser-inter-byte-timeout" "11.0.1"
|
"@serialport/parser-inter-byte-timeout" "11.0.0"
|
||||||
"@serialport/parser-packet-length" "11.0.1"
|
"@serialport/parser-packet-length" "11.0.0"
|
||||||
"@serialport/parser-readline" "11.0.1"
|
"@serialport/parser-readline" "11.0.0"
|
||||||
"@serialport/parser-ready" "11.0.1"
|
"@serialport/parser-ready" "11.0.0"
|
||||||
"@serialport/parser-regex" "11.0.1"
|
"@serialport/parser-regex" "11.0.0"
|
||||||
"@serialport/parser-slip-encoder" "11.0.1"
|
"@serialport/parser-slip-encoder" "11.0.0"
|
||||||
"@serialport/parser-spacepacket" "11.0.1"
|
"@serialport/parser-spacepacket" "11.0.0"
|
||||||
"@serialport/stream" "11.0.1"
|
"@serialport/stream" "11.0.0"
|
||||||
debug "4.3.4"
|
debug "4.3.4"
|
||||||
|
|
||||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
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"
|
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz"
|
||||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
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:
|
supports-color@^5.3.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||||
@@ -3916,11 +3908,6 @@ wcwidth@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defaults "^1.0.3"
|
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:
|
which-module@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz"
|
||||||
|
16
build/mac/afterBuildHook.cjs
Normal file
16
build/mac/afterBuildHook.cjs
Normal 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,
|
||||||
|
})
|
||||||
|
}
|
35
build/mac/afterSignHook.cjs
Normal file
35
build/mac/afterSignHook.cjs
Normal 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}`)
|
||||||
|
}
|
@@ -3,6 +3,8 @@ appId: org.tabby
|
|||||||
productName: Tabby
|
productName: Tabby
|
||||||
compression: normal
|
compression: normal
|
||||||
npmRebuild: false
|
npmRebuild: false
|
||||||
|
afterSign: "./build/mac/afterSignHook.cjs"
|
||||||
|
afterAllArtifactBuild: "./build/mac/afterBuildHook.cjs"
|
||||||
files:
|
files:
|
||||||
- '**/*'
|
- '**/*'
|
||||||
- dist
|
- dist
|
||||||
|
570
locale/af-ZA.po
570
locale/af-ZA.po
File diff suppressed because it is too large
Load Diff
568
locale/app.pot
568
locale/app.pot
File diff suppressed because it is too large
Load Diff
570
locale/bg-BG.po
570
locale/bg-BG.po
File diff suppressed because it is too large
Load Diff
2574
locale/cs-CZ.po
2574
locale/cs-CZ.po
File diff suppressed because it is too large
Load Diff
570
locale/da-DK.po
570
locale/da-DK.po
File diff suppressed because it is too large
Load Diff
588
locale/de-DE.po
588
locale/de-DE.po
File diff suppressed because it is too large
Load Diff
576
locale/en-GB.po
576
locale/en-GB.po
File diff suppressed because it is too large
Load Diff
596
locale/es-ES.po
596
locale/es-ES.po
File diff suppressed because it is too large
Load Diff
592
locale/fr-FR.po
592
locale/fr-FR.po
File diff suppressed because it is too large
Load Diff
600
locale/hr-HR.po
600
locale/hr-HR.po
File diff suppressed because it is too large
Load Diff
590
locale/id-ID.po
590
locale/id-ID.po
File diff suppressed because it is too large
Load Diff
588
locale/it-IT.po
588
locale/it-IT.po
File diff suppressed because it is too large
Load Diff
640
locale/ja-JP.po
640
locale/ja-JP.po
File diff suppressed because it is too large
Load Diff
620
locale/ko-KR.po
620
locale/ko-KR.po
File diff suppressed because it is too large
Load Diff
670
locale/pl-PL.po
670
locale/pl-PL.po
File diff suppressed because it is too large
Load Diff
594
locale/pt-BR.po
594
locale/pt-BR.po
File diff suppressed because it is too large
Load Diff
570
locale/pt-PT.po
570
locale/pt-PT.po
File diff suppressed because it is too large
Load Diff
592
locale/ru-RU.po
592
locale/ru-RU.po
File diff suppressed because it is too large
Load Diff
586
locale/sv-SE.po
586
locale/sv-SE.po
File diff suppressed because it is too large
Load Diff
592
locale/uk-UA.po
592
locale/uk-UA.po
File diff suppressed because it is too large
Load Diff
592
locale/zh-CN.po
592
locale/zh-CN.po
File diff suppressed because it is too large
Load Diff
594
locale/zh-TW.po
594
locale/zh-TW.po
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -26,8 +26,8 @@
|
|||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"@types/node": "20.3.1",
|
"@types/node": "20.3.1",
|
||||||
"@types/webpack-env": "^1.18.0",
|
"@types/webpack-env": "^1.18.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.4.1",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^6.4.1",
|
"@typescript-eslint/parser": "^5.54.1",
|
||||||
"apply-loader": "2.0.0",
|
"apply-loader": "2.0.0",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"babel-loader": "^9.1.2",
|
"babel-loader": "^9.1.2",
|
||||||
@@ -37,18 +37,18 @@
|
|||||||
"core-js": "^3.31.0",
|
"core-js": "^3.31.0",
|
||||||
"core-js-pure": "^3.21.1",
|
"core-js-pure": "^3.21.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.8.1",
|
||||||
"deep-equal": "2.0.5",
|
"deep-equal": "2.0.5",
|
||||||
"electron": "^25.3.0",
|
"electron": "22.3.1",
|
||||||
"electron-builder": "^24.0.0-alpha.1",
|
"electron-builder": "^24.0.0-alpha.1",
|
||||||
"electron-download": "^4.1.1",
|
"electron-download": "^4.1.1",
|
||||||
"electron-installer-snap": "^5.1.0",
|
"electron-installer-snap": "^5.1.0",
|
||||||
"electron-rebuild": "^3.2.9",
|
"electron-rebuild": "^3.2.9",
|
||||||
"eslint": "^8.48.0",
|
"eslint": "^8.38.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.0",
|
"eslint-import-resolver-typescript": "^3.5.2",
|
||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"gettext-extractor": "^3.8.0",
|
"gettext-extractor": "^3.5.4",
|
||||||
"graceful-fs": "^4.2.10",
|
"graceful-fs": "^4.2.10",
|
||||||
"html-loader": "4.2.0",
|
"html-loader": "4.2.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
"source-code-pro": "^2.38.0",
|
"source-code-pro": "^2.38.0",
|
||||||
"source-map-loader": "^4.0.1",
|
"source-map-loader": "^4.0.1",
|
||||||
"source-sans-pro": "3.6.0",
|
"source-sans-pro": "3.6.0",
|
||||||
"ssh2": "^1.14.0",
|
"ssh2": "Eugeny/ssh2#9de907d62907d6d45debdcc0ed8dda5b7b19dc7c",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"svg-inline-loader": "^0.8.2",
|
"svg-inline-loader": "^0.8.2",
|
||||||
"thenby": "^1.3.4",
|
"thenby": "^1.3.4",
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"*/pug": "^3",
|
"*/pug": "^3",
|
||||||
"lzma-native": "^8.0.6",
|
"lzma-native": "^8.0.0",
|
||||||
"*/node-abi": "^3.33.0",
|
"*/node-abi": "^3.33.0",
|
||||||
"**/graceful-fs": "^4.2.4",
|
"**/graceful-fs": "^4.2.4",
|
||||||
"nan": "2.17.0"
|
"nan": "2.17.0"
|
||||||
@@ -115,8 +115,5 @@
|
|||||||
"i18n:push": "crowdin push"
|
"i18n:push": "crowdin push"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true
|
||||||
"dependencies": {
|
|
||||||
"dotenv": "^16.3.1"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
diff --git a/node_modules/app-builder-lib/out/appInfo.js b/node_modules/app-builder-lib/out/appInfo.js
|
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
|
--- a/node_modules/app-builder-lib/out/appInfo.js
|
||||||
+++ b/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;
|
return this.info.metadata.name;
|
||||||
}
|
}
|
||||||
get linuxPackageName() {
|
get linuxPackageName() {
|
||||||
- const name = this.name;
|
- const name = this.name;
|
||||||
- // https://github.com/electron-userland/electron-builder/issues/2963
|
- // https://github.com/electron-userland/electron-builder/issues/2963
|
||||||
- return name.startsWith("@") ? this.sanitizedProductName : name;
|
- return name.startsWith("@") ? this.sanitizedProductName : name;
|
||||||
+ return 'tabby-terminal';
|
+ return 'tabby-terminal'
|
||||||
}
|
}
|
||||||
get sanitizedName() {
|
get sanitizedName() {
|
||||||
return (0, filename_1.sanitizeFileName)(this.name);
|
return filename_1.sanitizeFileName(this.name);
|
@@ -9,7 +9,7 @@ process.env.ARCH = (process.env.ARCH || process.arch) === 'arm' ? 'armv7l' : pro
|
|||||||
|
|
||||||
builder({
|
builder({
|
||||||
dir: true,
|
dir: true,
|
||||||
linux: ['deb', 'tar.gz', 'rpm', 'pacman', 'appimage'],
|
linux: ['deb', 'tar.gz', 'rpm', 'pacman'],
|
||||||
armv7l: process.env.ARCH === 'armv7l',
|
armv7l: process.env.ARCH === 'armv7l',
|
||||||
arm64: process.env.ARCH === 'arm64',
|
arm64: process.env.ARCH === 'arm64',
|
||||||
config: {
|
config: {
|
||||||
|
@@ -13,12 +13,9 @@ if (process.env.GITHUB_HEAD_REF) {
|
|||||||
process.env.CSC_IDENTITY_AUTO_DISCOVERY = 'false'
|
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({
|
builder({
|
||||||
dir: true,
|
dir: true,
|
||||||
mac: ['dmg', 'zip'],
|
mac: ['pkg', 'zip'],
|
||||||
x64: process.env.ARCH === 'x86_64',
|
x64: process.env.ARCH === 'x86_64',
|
||||||
arm64: process.env.ARCH === 'arm64',
|
arm64: process.env.ARCH === 'arm64',
|
||||||
config: {
|
config: {
|
||||||
@@ -27,10 +24,6 @@ builder({
|
|||||||
},
|
},
|
||||||
mac: {
|
mac: {
|
||||||
identity: !process.env.CI || process.env.CSC_LINK ? undefined : null,
|
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',
|
npmRebuild: process.env.ARCH !== 'arm64',
|
||||||
publish: process.env.KEYGEN_TOKEN ? [
|
publish: process.env.KEYGEN_TOKEN ? [
|
||||||
|
@@ -9,7 +9,7 @@ sh.exec(`${sentryCli} releases new ${vars.version}`)
|
|||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
for (const path of [
|
for (const path of [
|
||||||
'app/node_modules/@serialport/bindings/build/Release/bindings.node',
|
'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/fontmanager-redux/build/Release/fontmanager.node',
|
||||||
'app/node_modules/macos-native-processlist/build/Release/native.node',
|
'app/node_modules/macos-native-processlist/build/Release/native.node',
|
||||||
]) {
|
]) {
|
||||||
|
@@ -3,8 +3,6 @@ import * as fs from 'fs'
|
|||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
import * as childProcess from 'child_process'
|
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'
|
import * as url from 'url'
|
||||||
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||||
|
|
||||||
@@ -60,21 +58,21 @@ export const keygenConfig = {
|
|||||||
win32: {
|
win32: {
|
||||||
x64: 'f481b9d6-d5da-4970-b926-f515373e986f',
|
x64: 'f481b9d6-d5da-4970-b926-f515373e986f',
|
||||||
arm64: '950999b9-371c-419b-b291-938c5e4d364c',
|
arm64: '950999b9-371c-419b-b291-938c5e4d364c',
|
||||||
}[process.env.ARCH],
|
}[process.env.ARCH ?? process.arch],
|
||||||
darwin: {
|
darwin: {
|
||||||
arm64: '98fbadee-c707-4cd6-9d99-56683595a846',
|
arm64: '98fbadee-c707-4cd6-9d99-56683595a846',
|
||||||
x86_64: 'f5a48841-d5b8-4b7b-aaa7-cf5bffd36461',
|
x86_64: 'f5a48841-d5b8-4b7b-aaa7-cf5bffd36461',
|
||||||
x64: 'f5a48841-d5b8-4b7b-aaa7-cf5bffd36461',
|
x64: 'f5a48841-d5b8-4b7b-aaa7-cf5bffd36461',
|
||||||
}[process.env.ARCH],
|
}[process.env.ARCH ?? process.arch],
|
||||||
linux: {
|
linux: {
|
||||||
x64: '7bf45071-3031-4a26-9f2e-72604308313e',
|
x64: '7bf45071-3031-4a26-9f2e-72604308313e',
|
||||||
arm64: '39e3c736-d4d4-4fbf-a201-324b7bab0d17',
|
arm64: '39e3c736-d4d4-4fbf-a201-324b7bab0d17',
|
||||||
armv7l: '50ae0a82-7f47-4fa4-b0a8-b0d575ce9409',
|
armv7l: '50ae0a82-7f47-4fa4-b0a8-b0d575ce9409',
|
||||||
armhf: '7df5aa12-04ab-4075-a0fe-93b0bbea9643',
|
armhf: '7df5aa12-04ab-4075-a0fe-93b0bbea9643',
|
||||||
}[process.env.ARCH],
|
}[process.env.ARCH ?? process.arch],
|
||||||
}[process.platform],
|
}[process.platform],
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keygenConfig.product) {
|
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}`)
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ export { BootstrapData, PluginInfo, BOOTSTRAP_DATA } from './mainProcess'
|
|||||||
export { HostWindowService } from './hostWindow'
|
export { HostWindowService } from './hostWindow'
|
||||||
export { HostAppService, Platform } from './hostApp'
|
export { HostAppService, Platform } from './hostApp'
|
||||||
export { FileProvider } from './fileProvider'
|
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 { PromptModalComponent } from '../components/promptModal.component'
|
||||||
export * from './commands'
|
export * from './commands'
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
export interface MenuItemOptions {
|
export interface MenuItemOptions {
|
||||||
type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'
|
type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio')
|
||||||
label?: string
|
label?: string
|
||||||
sublabel?: string
|
sublabel?: string
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
|
@@ -86,18 +86,14 @@ export interface FileUploadOptions {
|
|||||||
multiple: boolean
|
multiple: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlatformTheme = 'light'|'dark'
|
|
||||||
|
|
||||||
export abstract class PlatformService {
|
export abstract class PlatformService {
|
||||||
supportsWindowControls = false
|
supportsWindowControls = false
|
||||||
|
|
||||||
get fileTransferStarted$ (): Observable<FileTransfer> { return this.fileTransferStarted }
|
get fileTransferStarted$ (): Observable<FileTransfer> { return this.fileTransferStarted }
|
||||||
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
|
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
|
||||||
get themeChanged$ (): Observable<PlatformTheme> { return this.themeChanged }
|
|
||||||
|
|
||||||
protected fileTransferStarted = new Subject<FileTransfer>()
|
protected fileTransferStarted = new Subject<FileTransfer>()
|
||||||
protected displayMetricsChanged = new Subject<void>()
|
protected displayMetricsChanged = new Subject<void>()
|
||||||
protected themeChanged = new Subject<PlatformTheme>()
|
|
||||||
|
|
||||||
abstract readClipboard (): string
|
abstract readClipboard (): string
|
||||||
abstract setClipboard (content: ClipboardContent): void
|
abstract setClipboard (content: ClipboardContent): void
|
||||||
@@ -173,10 +169,6 @@ export abstract class PlatformService {
|
|||||||
throw new Error('Not implemented')
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
|
|
||||||
getTheme (): PlatformTheme {
|
|
||||||
return 'dark'
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract getOSRelease (): string
|
abstract getOSRelease (): string
|
||||||
abstract getAppVersion (): string
|
abstract getAppVersion (): string
|
||||||
abstract openExternal (url: string): void
|
abstract openExternal (url: string): void
|
||||||
|
@@ -21,10 +21,6 @@ export interface Profile {
|
|||||||
isTemplate: boolean
|
isTemplate: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConnectableProfile extends Profile {
|
|
||||||
clearServiceMessagesOnConnect: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
|
export type PartialProfile<T extends Profile> = Omit<Omit<Omit<{
|
||||||
[K in keyof T]?: T[K]
|
[K in keyof T]?: T[K]
|
||||||
}, 'options'>, 'type'>, 'name'> & {
|
}, '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> {
|
export interface ProfileSettingsComponent<P extends Profile> {
|
||||||
profile: P
|
profile: P
|
||||||
save?: () => void
|
save?: () => void
|
||||||
@@ -58,6 +39,7 @@ export interface ProfileSettingsComponent<P extends Profile> {
|
|||||||
export abstract class ProfileProvider<P extends Profile> {
|
export abstract class ProfileProvider<P extends Profile> {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
|
supportsQuickConnect = false
|
||||||
settingsComponent?: new (...args: any[]) => ProfileSettingsComponent<P>
|
settingsComponent?: new (...args: any[]) => ProfileSettingsComponent<P>
|
||||||
configDefaults = {}
|
configDefaults = {}
|
||||||
|
|
||||||
@@ -71,15 +53,13 @@ export abstract class ProfileProvider<P extends Profile> {
|
|||||||
|
|
||||||
abstract getDescription (profile: PartialProfile<P>): string
|
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 { }
|
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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@@ -18,7 +18,7 @@ export class CoreCommandProvider extends CommandProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async activate () {
|
async activate () {
|
||||||
const profile = await this.profilesService.showProfileSelector().catch(() => null)
|
const profile = await this.profilesService.showProfileSelector()
|
||||||
if (profile) {
|
if (profile) {
|
||||||
this.profilesService.launchProfile(profile)
|
this.profilesService.launchProfile(profile)
|
||||||
}
|
}
|
||||||
|
@@ -1,20 +1,16 @@
|
|||||||
title-bar(
|
title-bar(
|
||||||
*ngIf='ready && !hostWindow.isFullscreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
|
*ngIf='ready && !hostWindow.isFullscreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
|
||||||
(dblclick)='hostWindow.toggleMaximize()',
|
(dblclick)='hostWindow.toggleMaximize()',
|
||||||
[hideControls]='hostApp.platform !== Platform.Linux && !hostWindow.isFullscreen',
|
|
||||||
[class.inset]='hostApp.platform == Platform.macOS && !hostWindow.isFullscreen'
|
[class.inset]='hostApp.platform == Platform.macOS && !hostWindow.isFullscreen'
|
||||||
)
|
)
|
||||||
|
|
||||||
.content(
|
.content(
|
||||||
*ngIf='ready',
|
*ngIf='ready',
|
||||||
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"',
|
[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-on-side]='hasVerticalTabs()',
|
||||||
[class.tabs-titlebar-enabled]='config.store.appearance.frame == "full"',
|
|
||||||
[class.tabs-on-right]='hasVerticalTabs() && config.store.appearance.tabsLocation == "right"',
|
|
||||||
)
|
)
|
||||||
.tab-bar(
|
.tab-bar(
|
||||||
*ngIf='!hostWindow.isFullscreen || config.store.appearance.tabsInFullscreen',
|
*ngIf='!hostWindow.isFullscreen || config.store.appearance.tabsInFullscreen',
|
||||||
[class.tab-bar-no-controls-overlay]='hostApp.platform == Platform.macOS',
|
|
||||||
(dblclick)='hostWindow.toggleMaximize()'
|
(dblclick)='hostWindow.toggleMaximize()'
|
||||||
)
|
)
|
||||||
.inset.background(*ngIf='hostApp.platform == Platform.macOS \
|
.inset.background(*ngIf='hostApp.platform == Platform.macOS \
|
||||||
@@ -35,7 +31,8 @@ title-bar(
|
|||||||
[@animateTab]='{value: "in", params: {size: targetTabSize}}',
|
[@animateTab]='{value: "in", params: {size: targetTabSize}}',
|
||||||
[@.disabled]='hasVerticalTabs() || !config.store.accessibility.animations',
|
[@.disabled]='hasVerticalTabs() || !config.store.accessibility.animations',
|
||||||
(click)='app.selectTab(tab)',
|
(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
|
.btn-group.background
|
||||||
@@ -64,7 +61,7 @@ title-bar(
|
|||||||
(transfersChange)='onTransfersChange()'
|
(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
|
.btn-group.background
|
||||||
.d-flex(
|
.d-flex(
|
||||||
@@ -84,12 +81,9 @@ title-bar(
|
|||||||
|
|
||||||
window-controls.background(
|
window-controls.background(
|
||||||
*ngIf='config.store.appearance.frame == "thin" \
|
*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
|
.content
|
||||||
start-page.content-tab.content-tab-active(*ngIf='ready && app.tabs.length == 0')
|
start-page.content-tab.content-tab-active(*ngIf='ready && app.tabs.length == 0')
|
||||||
|
|
||||||
|
@@ -35,16 +35,17 @@ $tab-border-radius: 4px;
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tabs-on-right {
|
&.tabs-on-side {
|
||||||
flex-direction: row-reverse;
|
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%;
|
height: 100%;
|
||||||
width: var(--side-tab-width);
|
width: var(--side-tab-width);
|
||||||
overflow-y: auto;
|
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 {
|
.tab-bar {
|
||||||
flex: none;
|
flex: none;
|
||||||
@@ -136,17 +125,10 @@ $tab-border-radius: 4px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.persistent {
|
&.persistent {
|
||||||
// min-width: 72px; // 2 x 36 px height, ie 2 squares
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.window-controls-spacer {
|
|
||||||
min-width: 138px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .inset {
|
& > .inset {
|
||||||
width: calc(70px + 15px * var(--spaciness));
|
width: calc(70px + 15px * var(--spaciness));
|
||||||
height: var(--tabs-height);
|
height: var(--tabs-height);
|
||||||
|
@@ -75,7 +75,6 @@ export abstract class BaseTabComponent extends BaseComponent {
|
|||||||
private titleChange = new Subject<string>()
|
private titleChange = new Subject<string>()
|
||||||
private focused = new Subject<void>()
|
private focused = new Subject<void>()
|
||||||
private blurred = new Subject<void>()
|
private blurred = new Subject<void>()
|
||||||
private visibility = new Subject<boolean>()
|
|
||||||
private progress = new Subject<number|null>()
|
private progress = new Subject<number|null>()
|
||||||
private activity = new Subject<boolean>()
|
private activity = new Subject<boolean>()
|
||||||
private destroyed = new Subject<void>()
|
private destroyed = new Subject<void>()
|
||||||
@@ -84,8 +83,6 @@ export abstract class BaseTabComponent extends BaseComponent {
|
|||||||
|
|
||||||
get focused$ (): Observable<void> { return this.focused }
|
get focused$ (): Observable<void> { return this.focused }
|
||||||
get blurred$ (): Observable<void> { return this.blurred }
|
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 titleChange$ (): Observable<string> { return this.titleChange.pipe(distinctUntilChanged()) }
|
||||||
get progress$ (): Observable<number|null> { return this.progress.pipe(distinctUntilChanged()) }
|
get progress$ (): Observable<number|null> { return this.progress.pipe(distinctUntilChanged()) }
|
||||||
get activity$ (): Observable<boolean> { return this.activity }
|
get activity$ (): Observable<boolean> { return this.activity }
|
||||||
@@ -180,11 +177,6 @@ export abstract class BaseTabComponent extends BaseComponent {
|
|||||||
this.blurred.next()
|
this.blurred.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @hidden */
|
|
||||||
emitVisibility (visibility: boolean): void {
|
|
||||||
this.visibility.next(visibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
insertIntoContainer (container: ViewContainerRef): EmbeddedViewRef<any> {
|
insertIntoContainer (container: ViewContainerRef): EmbeddedViewRef<any> {
|
||||||
this.viewContainerEmbeddedRef = container.insert(this.hostView) as EmbeddedViewRef<any>
|
this.viewContainerEmbeddedRef = container.insert(this.hostView) as EmbeddedViewRef<any>
|
||||||
this.viewContainer = container
|
this.viewContainer = container
|
||||||
|
@@ -18,58 +18,45 @@ export class SelectorModalComponent<T> {
|
|||||||
@Input() selectedIndex = 0
|
@Input() selectedIndex = 0
|
||||||
hasGroups = false
|
hasGroups = false
|
||||||
@ViewChildren('item') itemChildren: QueryList<ElementRef>
|
@ViewChildren('item') itemChildren: QueryList<ElementRef>
|
||||||
private preventEdit: boolean
|
|
||||||
|
|
||||||
constructor (public modalInstance: NgbActiveModal) {
|
constructor (
|
||||||
this.preventEdit = false
|
public modalInstance: NgbActiveModal,
|
||||||
}
|
) { }
|
||||||
|
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
this.onFilterChange()
|
this.onFilterChange()
|
||||||
this.hasGroups = this.options.some(x => x.group)
|
this.hasGroups = this.options.some(x => x.group)
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('keydown', ['$event']) onKeyDown (event: KeyboardEvent): void {
|
@HostListener('keydown', ['$event']) onKeyUp (event: KeyboardEvent): void {
|
||||||
if (event.key === 'Escape') {
|
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()
|
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',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
if (event.key === 'Backspace' && this.canEditSelected()) {
|
||||||
|
event.preventDefault()
|
||||||
@HostListener('keyup', ['$event']) onKeyUp (event: KeyboardEvent): void {
|
this.filter = this.filteredOptions[this.selectedIndex].freeInputEquivalent!
|
||||||
if (event.key === 'Backspace' && this.preventEdit) {
|
this.onFilterChange()
|
||||||
this.preventEdit = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.selectedIndex = (this.selectedIndex + this.filteredOptions.length) % this.filteredOptions.length
|
||||||
|
Array.from(this.itemChildren)[this.selectedIndex]?.nativeElement.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'nearest',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onFilterChange (): void {
|
onFilterChange (): void {
|
||||||
@@ -89,11 +76,10 @@ export class SelectorModalComponent<T> {
|
|||||||
{ sort: true },
|
{ sort: true },
|
||||||
).search(f)
|
).search(f)
|
||||||
|
|
||||||
this.options.filter(x => x.freeInputPattern).sort(firstBy<SelectorOption<T>, number>(x => x.weight ?? 0)).forEach(freeOption => {
|
const freeOption = this.options.find(x => x.freeInputPattern)
|
||||||
if (!this.filteredOptions.includes(freeOption)) {
|
if (freeOption && !this.filteredOptions.includes(freeOption)) {
|
||||||
this.filteredOptions.push(freeOption)
|
this.filteredOptions.push(freeOption)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
this.selectedIndex = Math.max(0, this.selectedIndex)
|
this.selectedIndex = Math.max(0, this.selectedIndex)
|
||||||
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
|
this.selectedIndex = Math.min(this.filteredOptions.length - 1, this.selectedIndex)
|
||||||
|
@@ -275,7 +275,6 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.blurred$.subscribe(() => this.getAllTabs().forEach(x => x.emitBlurred()))
|
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.tabAdded$.subscribe(() => this.updateTitle())
|
||||||
this.tabRemoved$.subscribe(() => this.updateTitle())
|
this.tabRemoved$.subscribe(() => this.updateTitle())
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
.title((dblclick)='hostWindow.toggleMaximize()') Tabby
|
.title((dblclick)='hostWindow.toggleMaximize()') Tabby
|
||||||
window-controls(*ngIf="!hideControls")
|
window-controls
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { HostWindowService } from '../api'
|
import { HostWindowService } from '../api'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@@ -8,7 +8,5 @@ import { HostWindowService } from '../api'
|
|||||||
styleUrls: ['./titleBar.component.scss'],
|
styleUrls: ['./titleBar.component.scss'],
|
||||||
})
|
})
|
||||||
export class TitleBarComponent {
|
export class TitleBarComponent {
|
||||||
@Input() hideControls: boolean
|
|
||||||
|
|
||||||
constructor (public hostWindow: HostWindowService) { }
|
constructor (public hostWindow: HostWindowService) { }
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
.container.mt-3.mb-3
|
.container.mt-5.mb-5
|
||||||
.mb-3
|
.mb-4
|
||||||
.tabby-logo
|
.tabby-logo
|
||||||
h1.tabby-title Tabby
|
h1.tabby-title Tabby
|
||||||
sup α
|
sup α
|
||||||
|
|
||||||
.text-center.mb-3(translate) Thank you for downloading Tabby!
|
.text-center.mb-5(translate) Thank you for downloading Tabby!
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
@@ -16,54 +16,13 @@
|
|||||||
*ngFor='let lang of allLanguages'
|
*ngFor='let lang of allLanguages'
|
||||||
) {{lang.name}}
|
) {{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
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title(translate) Enable analytics
|
.title(translate) Enable analytics
|
||||||
.description(translate) Help track the number of Tabby installs across the world!
|
.description(translate) Help track the number of Tabby installs across the world!
|
||||||
toggle([(ngModel)]='config.store.enableAnalytics')
|
toggle([(ngModel)]='config.store.enableAnalytics')
|
||||||
|
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title(translate) Enable global hotkey (Ctrl-Space)
|
.title(translate) Enable global hotkey (Ctrl-Space)
|
||||||
|
@@ -6,8 +6,3 @@
|
|||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabby-logo {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
@@ -9,6 +9,5 @@ export class CoreConfigProvider extends ConfigProvider {
|
|||||||
[Platform.Linux]: require('./configDefaults.linux.yaml').default,
|
[Platform.Linux]: require('./configDefaults.linux.yaml').default,
|
||||||
[Platform.Web]: require('./configDefaults.web.yaml').default,
|
[Platform.Web]: require('./configDefaults.web.yaml').default,
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults = require('./configDefaults.yaml').default
|
defaults = require('./configDefaults.yaml').default
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,6 @@ hotkeys:
|
|||||||
duplicate-tab: []
|
duplicate-tab: []
|
||||||
restart-tab: []
|
restart-tab: []
|
||||||
reconnect-tab: []
|
reconnect-tab: []
|
||||||
disconnect-tab: []
|
|
||||||
explode-tab:
|
explode-tab:
|
||||||
- 'Ctrl-Shift-.'
|
- 'Ctrl-Shift-.'
|
||||||
combine-tabs:
|
combine-tabs:
|
||||||
|
@@ -40,7 +40,6 @@ hotkeys:
|
|||||||
duplicate-tab: []
|
duplicate-tab: []
|
||||||
restart-tab: []
|
restart-tab: []
|
||||||
reconnect-tab: []
|
reconnect-tab: []
|
||||||
disconnect-tab: []
|
|
||||||
explode-tab:
|
explode-tab:
|
||||||
- '⌘-Shift-.'
|
- '⌘-Shift-.'
|
||||||
combine-tabs:
|
combine-tabs:
|
||||||
@@ -96,3 +95,5 @@ hotkeys:
|
|||||||
- '⌘-Shift-E'
|
- '⌘-Shift-E'
|
||||||
command-selector:
|
command-selector:
|
||||||
- '⌘-Shift-P'
|
- '⌘-Shift-P'
|
||||||
|
appearance:
|
||||||
|
vibrancy: true
|
||||||
|
@@ -24,7 +24,6 @@ hotkeys:
|
|||||||
duplicate-tab: []
|
duplicate-tab: []
|
||||||
restart-tab: []
|
restart-tab: []
|
||||||
reconnect-tab: []
|
reconnect-tab: []
|
||||||
disconnect-tab: []
|
|
||||||
explode-tab:
|
explode-tab:
|
||||||
- 'Ctrl-Shift-.'
|
- 'Ctrl-Shift-.'
|
||||||
combine-tabs:
|
combine-tabs:
|
||||||
|
@@ -11,7 +11,7 @@ appearance:
|
|||||||
tabsLocation: top
|
tabsLocation: top
|
||||||
tabsInFullscreen: false
|
tabsInFullscreen: false
|
||||||
cycleTabs: true
|
cycleTabs: true
|
||||||
theme: Follow the color scheme
|
theme: Standard
|
||||||
frame: thin
|
frame: thin
|
||||||
css: '/* * { color: blue !important; } */'
|
css: '/* * { color: blue !important; } */'
|
||||||
opacity: 1.0
|
opacity: 1.0
|
||||||
@@ -19,7 +19,6 @@ appearance:
|
|||||||
vibrancyType: 'blur'
|
vibrancyType: 'blur'
|
||||||
lastTabClosesWindow: false
|
lastTabClosesWindow: false
|
||||||
spaciness: 1
|
spaciness: 1
|
||||||
colorSchemeMode: 'dark'
|
|
||||||
terminal:
|
terminal:
|
||||||
showBuiltinProfiles: true
|
showBuiltinProfiles: true
|
||||||
showRecentProfiles: 3
|
showRecentProfiles: 3
|
||||||
@@ -32,7 +31,6 @@ hotkeys:
|
|||||||
profile-selectors:
|
profile-selectors:
|
||||||
__nonStructural: true
|
__nonStructural: true
|
||||||
profiles: []
|
profiles: []
|
||||||
groups: []
|
|
||||||
profileDefaults:
|
profileDefaults:
|
||||||
__nonStructural: true
|
__nonStructural: true
|
||||||
ssh:
|
ssh:
|
||||||
@@ -56,4 +54,3 @@ hacks:
|
|||||||
disableVibrancyWhileDragging: false
|
disableVibrancyWhileDragging: false
|
||||||
enableFluentBackground: false
|
enableFluentBackground: false
|
||||||
language: null
|
language: null
|
||||||
defaultQuickConnectProvider: "ssh"
|
|
||||||
|
@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'
|
|||||||
import { TranslateService } from '@ngx-translate/core'
|
import { TranslateService } from '@ngx-translate/core'
|
||||||
import { ProfilesService } from './services/profiles.service'
|
import { ProfilesService } from './services/profiles.service'
|
||||||
import { HotkeyDescription, HotkeyProvider } from './api/hotkeyProvider'
|
import { HotkeyDescription, HotkeyProvider } from './api/hotkeyProvider'
|
||||||
|
import { PartialProfile, Profile } from './api'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -267,7 +268,7 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
|||||||
return [
|
return [
|
||||||
...this.hotkeys,
|
...this.hotkeys,
|
||||||
...profiles.map(profile => ({
|
...profiles.map(profile => ({
|
||||||
id: `profile.${ProfilesService.getProfileHotkeyName(profile)}`,
|
id: `profile.${AppHotkeyProvider.getProfileHotkeyName(profile)}`,
|
||||||
name: this.translate.instant('New tab: {profile}', { profile: profile.name }),
|
name: this.translate.instant('New tab: {profile}', { profile: profile.name }),
|
||||||
})),
|
})),
|
||||||
...this.profilesService.getProviders().map(provider => ({
|
...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, '-')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ import { FastHtmlBindDirective } from './directives/fastHtmlBind.directive'
|
|||||||
import { DropZoneDirective } from './directives/dropZone.directive'
|
import { DropZoneDirective } from './directives/dropZone.directive'
|
||||||
import { CdkAutoDropGroup } from './directives/cdkAutoDropGroup.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 { AppService } from './services/app.service'
|
||||||
import { ConfigService } from './services/config.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.')) {
|
if (hotkey.startsWith('profile.')) {
|
||||||
const id = hotkey.substring(hotkey.indexOf('.') + 1)
|
const id = hotkey.substring(hotkey.indexOf('.') + 1)
|
||||||
const profiles = await profilesService.getProfiles()
|
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) {
|
if (profile) {
|
||||||
profilesService.openNewTabForProfile(profile)
|
profilesService.openNewTabForProfile(profile)
|
||||||
}
|
}
|
||||||
@@ -188,10 +188,10 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
|
|||||||
if (!provider) {
|
if (!provider) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.showSelector(provider).catch(() => null)
|
this.showSelector(provider)
|
||||||
}
|
}
|
||||||
if (hotkey === 'command-selector') {
|
if (hotkey === 'command-selector') {
|
||||||
commands.showSelector().catch(() => null)
|
commands.showSelector()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hotkey === 'profile-selector') {
|
if (hotkey === 'profile-selector') {
|
||||||
@@ -214,12 +214,11 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
|
|||||||
callback: () => this.profilesService.openNewTabForProfile(p),
|
callback: () => this.profilesService.openNewTabForProfile(p),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (provider instanceof QuickConnectProfileProvider) {
|
if (provider.supportsQuickConnect) {
|
||||||
options.push({
|
options.push({
|
||||||
name: this.translate.instant('Quick connect'),
|
name: this.translate.instant('Quick connect'),
|
||||||
freeInputPattern: this.translate.instant('Connect to "%s"...'),
|
freeInputPattern: this.translate.instant('Connect to "%s"...'),
|
||||||
icon: 'fas fa-arrow-right',
|
icon: 'fas fa-arrow-right',
|
||||||
description: `(${provider.name.toUpperCase()})`,
|
|
||||||
callback: query => {
|
callback: query => {
|
||||||
const p = provider.quickConnect(query)
|
const p = provider.quickConnect(query)
|
||||||
if (p) {
|
if (p) {
|
||||||
|
@@ -230,13 +230,11 @@ export class AppService {
|
|||||||
if (this._activeTab) {
|
if (this._activeTab) {
|
||||||
this._activeTab.clearActivity()
|
this._activeTab.clearActivity()
|
||||||
this._activeTab.emitBlurred()
|
this._activeTab.emitBlurred()
|
||||||
this._activeTab.emitVisibility(false)
|
|
||||||
}
|
}
|
||||||
this._activeTab = tab
|
this._activeTab = tab
|
||||||
this.activeTabChange.next(tab)
|
this.activeTabChange.next(tab)
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this._activeTab?.emitFocused()
|
this._activeTab?.emitFocused()
|
||||||
this._activeTab?.emitVisibility(true)
|
|
||||||
})
|
})
|
||||||
this.hostWindow.setTitle(this._activeTab?.title)
|
this.hostWindow.setTitle(this._activeTab?.title)
|
||||||
}
|
}
|
||||||
|
@@ -101,7 +101,7 @@ export class CommandService {
|
|||||||
context.tab = tab.getFocusedTab() ?? undefined
|
context.tab = tab.getFocusedTab() ?? undefined
|
||||||
}
|
}
|
||||||
const commands = await this.getCommands(context)
|
const commands = await this.getCommands(context)
|
||||||
return this.selector.show(
|
await this.selector.show(
|
||||||
this.translate.instant('Commands'),
|
this.translate.instant('Commands'),
|
||||||
commands.map(c => ({
|
commands.map(c => ({
|
||||||
name: c.label,
|
name: c.label,
|
||||||
|
@@ -10,15 +10,11 @@ import { PlatformService } from '../api/platform'
|
|||||||
import { HostAppService } from '../api/hostApp'
|
import { HostAppService } from '../api/hostApp'
|
||||||
import { Vault, VaultService } from './vault.service'
|
import { Vault, VaultService } from './vault.service'
|
||||||
import { serializeFunction } from '../utils'
|
import { serializeFunction } from '../utils'
|
||||||
import { PartialProfileGroup, ProfileGroup } from '../api/profileProvider'
|
|
||||||
const deepmerge = require('deepmerge')
|
const deepmerge = require('deepmerge')
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// 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
|
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
|
const LATEST_VERSION = 1
|
||||||
|
|
||||||
function isStructuralMember (v) {
|
function isStructuralMember (v) {
|
||||||
@@ -166,7 +162,7 @@ export class ConfigService {
|
|||||||
defaults = configMerge(provider.defaults, defaults)
|
defaults = configMerge(provider.defaults, defaults)
|
||||||
}
|
}
|
||||||
return defaults
|
return defaults
|
||||||
}).reduce(configMergeByDefault)
|
}).reduce(configMerge)
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaults (): Record<string, any> {
|
getDefaults (): Record<string, any> {
|
||||||
@@ -217,9 +213,7 @@ export class ConfigService {
|
|||||||
* Reads config YAML as string
|
* Reads config YAML as string
|
||||||
*/
|
*/
|
||||||
readRaw (): string {
|
readRaw (): string {
|
||||||
// Scrub undefined values
|
return yaml.dump(this._store)
|
||||||
const cleanStore = JSON.parse(JSON.stringify(this._store))
|
|
||||||
return yaml.dump(cleanStore)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -357,55 +351,6 @@ export class ConfigService {
|
|||||||
delete window.localStorage.lastSerialConnection
|
delete window.localStorage.lastSerialConnection
|
||||||
config.version = 3
|
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) {
|
private async maybeDecryptConfig (store) {
|
||||||
|
@@ -13,9 +13,8 @@ export class FileProvidersService {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
async selectAndStoreFile (description: string): Promise<string> {
|
async selectAndStoreFile (description: string): Promise<string> {
|
||||||
return this.selectProvider().then(p => {
|
const p = await this.selectProvider()
|
||||||
return p.selectAndStoreFile(description)
|
return p.selectAndStoreFile(description)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveFile (key: string): Promise<Buffer> {
|
async retrieveFile (key: string): Promise<Buffer> {
|
||||||
|
@@ -7,7 +7,6 @@ import localeENUS from '@angular/common/locales/en'
|
|||||||
import localeENGB from '@angular/common/locales/en-GB'
|
import localeENGB from '@angular/common/locales/en-GB'
|
||||||
import localeAF from '@angular/common/locales/af'
|
import localeAF from '@angular/common/locales/af'
|
||||||
import localeBG from '@angular/common/locales/bg'
|
import localeBG from '@angular/common/locales/bg'
|
||||||
import localeCS from '@angular/common/locales/cs'
|
|
||||||
import localeDA from '@angular/common/locales/da'
|
import localeDA from '@angular/common/locales/da'
|
||||||
import localeDE from '@angular/common/locales/de'
|
import localeDE from '@angular/common/locales/de'
|
||||||
import localeES from '@angular/common/locales/es'
|
import localeES from '@angular/common/locales/es'
|
||||||
@@ -32,7 +31,6 @@ registerLocaleData(localeENUS)
|
|||||||
registerLocaleData(localeENGB)
|
registerLocaleData(localeENGB)
|
||||||
registerLocaleData(localeAF)
|
registerLocaleData(localeAF)
|
||||||
registerLocaleData(localeBG)
|
registerLocaleData(localeBG)
|
||||||
registerLocaleData(localeCS)
|
|
||||||
registerLocaleData(localeDA)
|
registerLocaleData(localeDA)
|
||||||
registerLocaleData(localeDE)
|
registerLocaleData(localeDE)
|
||||||
registerLocaleData(localeES)
|
registerLocaleData(localeES)
|
||||||
@@ -84,10 +82,6 @@ export class LocaleService {
|
|||||||
code: 'id-ID',
|
code: 'id-ID',
|
||||||
name: 'Bahasa Indonesia',
|
name: 'Bahasa Indonesia',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
code: 'cs-CZ',
|
|
||||||
name: 'Čeština',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
code: 'da-DK',
|
code: 'da-DK',
|
||||||
name: 'Dansk',
|
name: 'Dansk',
|
||||||
|
@@ -2,15 +2,12 @@ import { Injectable, Inject } from '@angular/core'
|
|||||||
import { TranslateService } from '@ngx-translate/core'
|
import { TranslateService } from '@ngx-translate/core'
|
||||||
import { NewTabParameters } from './tabs.service'
|
import { NewTabParameters } from './tabs.service'
|
||||||
import { BaseTabComponent } from '../components/baseTab.component'
|
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 { SelectorOption } from '../api/selector'
|
||||||
import { AppService } from './app.service'
|
import { AppService } from './app.service'
|
||||||
import { configMerge, ConfigProxy, ConfigService } from './config.service'
|
import { configMerge, ConfigProxy, ConfigService } from './config.service'
|
||||||
import { NotificationsService } from './notifications.service'
|
import { NotificationsService } from './notifications.service'
|
||||||
import { SelectorService } from './selector.service'
|
import { SelectorService } from './selector.service'
|
||||||
import deepClone from 'clone-deep'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import slugify from 'slugify'
|
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ProfilesService {
|
export class ProfilesService {
|
||||||
@@ -39,127 +36,6 @@ export class ProfilesService {
|
|||||||
@Inject(ProfileProvider) private profileProviders: ProfileProvider<Profile>[],
|
@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> {
|
async openNewTabForProfile <P extends Profile> (profile: PartialProfile<P>): Promise<BaseTabComponent|null> {
|
||||||
const params = await this.newTabParametersForProfile(profile)
|
const params = await this.newTabParametersForProfile(profile)
|
||||||
if (params) {
|
if (params) {
|
||||||
@@ -187,40 +63,52 @@ export class ProfilesService {
|
|||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
||||||
async launchProfile (profile: PartialProfile<Profile>): Promise<void> {
|
getProviders (): ProfileProvider<Profile>[] {
|
||||||
await this.openNewTabForProfile(profile)
|
return [...this.profileProviders]
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getProfileHotkeyName (profile: PartialProfile<Profile>): string {
|
async getProfiles (): Promise<PartialProfile<Profile>[]> {
|
||||||
return (profile.id ?? profile.name).replace(/\./g, '-')
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
providerForProfile <T extends Profile> (profile: PartialProfile<T>): ProfileProvider<T>|null {
|
||||||
* Methods used to interract with Profile Selector
|
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> {
|
selectorOptionForProfile <P extends Profile, T> (profile: PartialProfile<P>): SelectorOption<T> {
|
||||||
const fullProfile = this.getConfigProxyForProfile(profile)
|
const fullProfile = this.getConfigProxyForProfile(profile)
|
||||||
const provider = this.providerForProfile(fullProfile)
|
const provider = this.providerForProfile(fullProfile)
|
||||||
const freeInputEquivalent = provider instanceof QuickConnectProfileProvider ? provider.intoQuickConnectString(fullProfile) ?? undefined : undefined
|
const freeInputEquivalent = provider?.intoQuickConnectString(fullProfile) ?? undefined
|
||||||
return {
|
return {
|
||||||
...profile,
|
...profile,
|
||||||
group: this.resolveProfileGroupName(profile.group ?? ''),
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||||
|
group: profile.group || '',
|
||||||
freeInputEquivalent,
|
freeInputEquivalent,
|
||||||
description: provider?.getDescription(fullProfile),
|
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> {
|
showProfileSelector (): Promise<PartialProfile<Profile>|null> {
|
||||||
if (this.selector.active) {
|
if (this.selector.active) {
|
||||||
return Promise.resolve(null)
|
return Promise.resolve(null)
|
||||||
@@ -230,12 +118,12 @@ export class ProfilesService {
|
|||||||
try {
|
try {
|
||||||
const recentProfiles = this.getRecentProfiles()
|
const recentProfiles = this.getRecentProfiles()
|
||||||
|
|
||||||
let options: SelectorOption<void>[] = recentProfiles.map((p, i) => ({
|
let options: SelectorOption<void>[] = recentProfiles.map(p => ({
|
||||||
...this.selectorOptionForProfile(p),
|
...this.selectorOptionForProfile(p),
|
||||||
group: this.translate.instant('Recent'),
|
group: this.translate.instant('Recent'),
|
||||||
icon: 'fas fa-history',
|
icon: 'fas fa-history',
|
||||||
color: p.color,
|
color: p.color,
|
||||||
weight: i - (recentProfiles.length + 1),
|
weight: -2,
|
||||||
callback: async () => {
|
callback: async () => {
|
||||||
if (p.id) {
|
if (p.id) {
|
||||||
p = (await this.getProfiles()).find(x => x.id === p.id) ?? p
|
p = (await this.getProfiles()).find(x => x.id === p.id) ?? p
|
||||||
@@ -289,38 +177,27 @@ export class ProfilesService {
|
|||||||
})
|
})
|
||||||
} catch { }
|
} catch { }
|
||||||
|
|
||||||
this.getProviders().forEach(provider => {
|
if (this.getProviders().some(x => x.supportsQuickConnect)) {
|
||||||
if (provider instanceof QuickConnectProfileProvider) {
|
options.push({
|
||||||
options.push({
|
name: this.translate.instant('Quick connect'),
|
||||||
name: this.translate.instant('Quick connect'),
|
freeInputPattern: this.translate.instant('Connect to "%s"...'),
|
||||||
freeInputPattern: this.translate.instant('Connect to "%s"...'),
|
icon: 'fas fa-arrow-right',
|
||||||
description: `(${provider.name.toUpperCase()})`,
|
callback: query => {
|
||||||
icon: 'fas fa-arrow-right',
|
const profile = this.quickConnect(query)
|
||||||
weight: provider.id !== this.config.store.defaultQuickConnectProvider ? 1 : 0,
|
resolve(profile)
|
||||||
callback: query => {
|
},
|
||||||
const profile = provider.quickConnect(query)
|
})
|
||||||
resolve(profile)
|
}
|
||||||
},
|
await this.selector.show(this.translate.instant('Select profile or enter an address'), options)
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.selector.show(this.translate.instant('Select profile or enter an address'), options).catch(() => reject())
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(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> {
|
async quickConnect (query: string): Promise<PartialProfile<Profile>|null> {
|
||||||
for (const provider of this.getProviders()) {
|
for (const provider of this.getProviders()) {
|
||||||
if (provider instanceof QuickConnectProfileProvider) {
|
if (provider.supportsQuickConnect) {
|
||||||
const profile = provider.quickConnect(query)
|
const profile = provider.quickConnect(query)
|
||||||
if (profile) {
|
if (profile) {
|
||||||
return profile
|
return profile
|
||||||
@@ -331,178 +208,27 @@ export class ProfilesService {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, skipUserDefaults = false): T {
|
||||||
* 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[] {
|
|
||||||
const provider = this.providerForProfile(profile)
|
const provider = this.providerForProfile(profile)
|
||||||
|
const defaults = [
|
||||||
return [
|
|
||||||
this.profileDefaults,
|
this.profileDefaults,
|
||||||
provider?.configDefaults ?? {},
|
provider?.configDefaults ?? {},
|
||||||
provider && !options?.skipGlobalDefaults ? this.getProviderDefaults(provider) : {},
|
!provider || skipUserDefaults ? {} : this.config.store.profileDefaults[provider.id] ?? {},
|
||||||
provider && !options?.skipGlobalDefaults && !options?.skipGroupDefaults ? this.getProviderProfileGroupDefaults(profile.group ?? '', provider) : {},
|
].reduce(configMerge, {})
|
||||||
]
|
return new ConfigProxy(profile, defaults) as unknown as T
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
async launchProfile (profile: PartialProfile<Profile>): Promise<void> {
|
||||||
* Methods used to interract with ProfileGroup
|
await this.openNewTabForProfile(profile)
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
let recentProfiles: PartialProfile<Profile>[] = JSON.parse(window.localStorage['recentProfiles'] ?? '[]')
|
||||||
* Synchronously return an Array of the existing ProfileGroups
|
if (this.config.store.terminal.showRecentProfiles > 0) {
|
||||||
* Does not return builtin groups
|
recentProfiles = recentProfiles.filter(x => x.group !== profile.group || x.name !== profile.name)
|
||||||
*/
|
recentProfiles.unshift(profile)
|
||||||
getSyncProfileGroups (): PartialProfileGroup<ProfileGroup>[] {
|
recentProfiles = recentProfiles.slice(0, this.config.store.terminal.showRecentProfiles)
|
||||||
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)
|
|
||||||
} else {
|
} else {
|
||||||
for (const profile of this.config.store.profiles.filter(x => x.group === group.id)) {
|
recentProfiles = []
|
||||||
delete profile.group
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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] ?? {}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ import { Subject, Observable } from 'rxjs'
|
|||||||
import * as Color from 'color'
|
import * as Color from 'color'
|
||||||
import { ConfigService } from '../services/config.service'
|
import { ConfigService } from '../services/config.service'
|
||||||
import { Theme } from '../api/theme'
|
import { Theme } from '../api/theme'
|
||||||
import { PlatformService, PlatformTheme } from '../api/platform'
|
|
||||||
import { NewTheme } from '../theme'
|
import { NewTheme } from '../theme'
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
@@ -18,7 +17,6 @@ export class ThemesService {
|
|||||||
private constructor (
|
private constructor (
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
private standardTheme: NewTheme,
|
private standardTheme: NewTheme,
|
||||||
private platform: PlatformService,
|
|
||||||
@Inject(Theme) private themes: Theme[],
|
@Inject(Theme) private themes: Theme[],
|
||||||
) {
|
) {
|
||||||
this.rootElementStyleBackup = document.documentElement.style.cssText
|
this.rootElementStyleBackup = document.documentElement.style.cssText
|
||||||
@@ -26,10 +24,6 @@ export class ThemesService {
|
|||||||
config.ready$.toPromise().then(() => {
|
config.ready$.toPromise().then(() => {
|
||||||
this.applyCurrentTheme()
|
this.applyCurrentTheme()
|
||||||
this.applyThemeVariables()
|
this.applyThemeVariables()
|
||||||
platform.themeChanged$.subscribe(() => {
|
|
||||||
this.applyCurrentTheme()
|
|
||||||
this.applyThemeVariables()
|
|
||||||
})
|
|
||||||
config.changed$.subscribe(() => {
|
config.changed$.subscribe(() => {
|
||||||
this.applyCurrentTheme()
|
this.applyCurrentTheme()
|
||||||
this.applyThemeVariables()
|
this.applyThemeVariables()
|
||||||
@@ -42,7 +36,7 @@ export class ThemesService {
|
|||||||
document.documentElement.style.cssText = this.rootElementStyleBackup
|
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()
|
const isDark = Color(theme.background).luminosity() < Color(theme.foreground).luminosity()
|
||||||
|
|
||||||
function more (some, factor) {
|
function more (some, factor) {
|
||||||
@@ -112,10 +106,8 @@ export class ThemesService {
|
|||||||
|
|
||||||
const themeColors = {
|
const themeColors = {
|
||||||
primary: theme.colors[accentIndex],
|
primary: theme.colors[accentIndex],
|
||||||
secondary: isDark
|
secondary: less(theme.background, 0.5).string(),
|
||||||
? less(theme.background, 0.5).string()
|
tertiary: theme.colors[8],
|
||||||
: less(theme.background, 0.125).string(),
|
|
||||||
tertiary: more(theme.background, 0.75).string(),
|
|
||||||
warning: theme.colors[3],
|
warning: theme.colors[3],
|
||||||
danger: theme.colors[1],
|
danger: theme.colors[1],
|
||||||
success: theme.colors[2],
|
success: theme.colors[2],
|
||||||
@@ -192,22 +184,6 @@ export class ThemesService {
|
|||||||
return this.findTheme(this.config.store.appearance.theme) ?? this.standardTheme
|
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 {
|
applyTheme (theme: Theme): void {
|
||||||
if (!this.styleElement) {
|
if (!this.styleElement) {
|
||||||
this.styleElement = document.createElement('style')
|
this.styleElement = document.createElement('style')
|
||||||
|
@@ -285,7 +285,7 @@ export class VaultFileProvider extends FileProvider {
|
|||||||
icon: 'fas fa-file',
|
icon: 'fas fa-file',
|
||||||
result: f,
|
result: f,
|
||||||
})),
|
})),
|
||||||
]).catch(() => null)
|
])
|
||||||
if (result) {
|
if (result) {
|
||||||
return `${this.prefix}${result.key.id}`
|
return `${this.prefix}${result.key.id}`
|
||||||
}
|
}
|
||||||
|
@@ -149,7 +149,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
|||||||
click: async () => {
|
click: async () => {
|
||||||
const modal = this.ngbModal.open(PromptModalComponent)
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
modal.componentInstance.prompt = this.translate.instant('Profile name')
|
modal.componentInstance.prompt = this.translate.instant('Profile name')
|
||||||
const name = (await modal.result.catch(() => null))?.value
|
const name = (await modal.result)?.value
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ export class ProfilesContextMenu extends TabContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async switchTabProfile (tab: BaseTabComponent) {
|
async switchTabProfile (tab: BaseTabComponent) {
|
||||||
const profile = await this.profilesService.showProfileSelector().catch(() => null)
|
const profile = await this.profilesService.showProfileSelector()
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -110,7 +110,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav {
|
.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-hover-color: var(--theme-fg-less);
|
||||||
--bs-nav-link-disabled-color: var(--bs-gray);
|
--bs-nav-link-disabled-color: var(--bs-gray);
|
||||||
}
|
}
|
||||||
@@ -119,8 +119,8 @@ body {
|
|||||||
--bs-nav-tabs-border-width: 2px;
|
--bs-nav-tabs-border-width: 2px;
|
||||||
--bs-nav-tabs-border-radius: 0;
|
--bs-nav-tabs-border-radius: 0;
|
||||||
--bs-nav-tabs-link-hover-border-color: var(--bs-body-bg);
|
--bs-nav-tabs-link-hover-border-color: var(--bs-body-bg);
|
||||||
--bs-nav-tabs-border-color: var(--theme-fg);
|
--bs-nav-tabs-border-color: var(--theme-fg-less-2);
|
||||||
--bs-nav-tabs-link-active-color: var(--theme-fg);
|
--bs-nav-tabs-link-active-color: var(--theme-fg-less-2);
|
||||||
|
|
||||||
--bs-nav-tabs-link-active-bg: transparent;
|
--bs-nav-tabs-link-active-bg: transparent;
|
||||||
--bs-nav-tabs-link-active-border-color: transparent;
|
--bs-nav-tabs-link-active-border-color: transparent;
|
||||||
|
@@ -22,6 +22,5 @@ export class ElectronConfigProvider extends ConfigProvider {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults = {}
|
defaults = {}
|
||||||
}
|
}
|
||||||
|
@@ -99,7 +99,6 @@ export default class ElectronModule {
|
|||||||
})
|
})
|
||||||
this.registerGlobalHotkey()
|
this.registerGlobalHotkey()
|
||||||
this.updateVibrancy()
|
this.updateVibrancy()
|
||||||
this.updateWindowControlsColor()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
config.changed$.subscribe(() => {
|
config.changed$.subscribe(() => {
|
||||||
@@ -132,8 +131,6 @@ export default class ElectronModule {
|
|||||||
|
|
||||||
config.changed$.subscribe(() => this.updateVibrancy())
|
config.changed$.subscribe(() => this.updateVibrancy())
|
||||||
|
|
||||||
config.changed$.subscribe(() => this.updateWindowControlsColor())
|
|
||||||
|
|
||||||
config.ready$.toPromise().then(() => {
|
config.ready$.toPromise().then(() => {
|
||||||
dockMenu.update()
|
dockMenu.update()
|
||||||
})
|
})
|
||||||
@@ -172,15 +169,6 @@ export default class ElectronModule {
|
|||||||
|
|
||||||
this.hostWindow.setOpacity(this.config.store.appearance.opacity)
|
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 }
|
export { ElectronHostWindow, ElectronHostAppService, ElectronService }
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core'
|
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'
|
import * as remote from '@electron/remote'
|
||||||
|
|
||||||
export interface MessageBoxResponse {
|
export interface MessageBoxResponse {
|
||||||
@@ -20,7 +20,6 @@ export class ElectronService {
|
|||||||
process: any
|
process: any
|
||||||
autoUpdater: AutoUpdater
|
autoUpdater: AutoUpdater
|
||||||
powerSaveBlocker: PowerSaveBlocker
|
powerSaveBlocker: PowerSaveBlocker
|
||||||
nativeTheme: NativeTheme
|
|
||||||
TouchBar: typeof TouchBar
|
TouchBar: typeof TouchBar
|
||||||
BrowserWindow: typeof BrowserWindow
|
BrowserWindow: typeof BrowserWindow
|
||||||
Menu: typeof Menu
|
Menu: typeof Menu
|
||||||
@@ -44,7 +43,5 @@ export class ElectronService {
|
|||||||
this.BrowserWindow = remote.BrowserWindow
|
this.BrowserWindow = remote.BrowserWindow
|
||||||
this.Menu = remote.Menu
|
this.Menu = remote.Menu
|
||||||
this.MenuItem = remote.MenuItem
|
this.MenuItem = remote.MenuItem
|
||||||
this.MenuItem = remote.MenuItem
|
|
||||||
this.nativeTheme = remote.nativeTheme
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,6 @@ import { ElectronService } from '../services/electron.service'
|
|||||||
import { ElectronHostWindow } from './hostWindow.service'
|
import { ElectronHostWindow } from './hostWindow.service'
|
||||||
import { ShellIntegrationService } from './shellIntegration.service'
|
import { ShellIntegrationService } from './shellIntegration.service'
|
||||||
import { ElectronHostAppService } from './hostApp.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
|
const fontManager = require('fontmanager-redux') // eslint-disable-line
|
||||||
|
|
||||||
/* eslint-disable block-scoped-var */
|
/* eslint-disable block-scoped-var */
|
||||||
@@ -37,15 +35,11 @@ export class ElectronPlatformService extends PlatformService {
|
|||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.configPath = configPath
|
this.configPath = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||||
|
|
||||||
electron.ipcRenderer.on('host:display-metrics-changed', () => {
|
electron.ipcRenderer.on('host:display-metrics-changed', () => {
|
||||||
this.zone.run(() => this.displayMetricsChanged.next())
|
this.zone.run(() => this.displayMetricsChanged.next())
|
||||||
})
|
})
|
||||||
|
|
||||||
electron.nativeTheme.on('updated', () => {
|
|
||||||
this.zone.run(() => this.themeChanged.next(this.getTheme()))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readClipboard (): string {
|
readClipboard (): string {
|
||||||
@@ -249,14 +243,6 @@ export class ElectronPlatformService extends PlatformService {
|
|||||||
},
|
},
|
||||||
)).filePaths[0]
|
)).filePaths[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
getTheme (): PlatformTheme {
|
|
||||||
if (this.electron.nativeTheme.shouldUseDarkColors) {
|
|
||||||
return 'dark'
|
|
||||||
} else {
|
|
||||||
return 'light'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ElectronFileUpload extends FileUpload {
|
class ElectronFileUpload extends FileUpload {
|
||||||
|
@@ -33,7 +33,6 @@ export class ShellIntegrationService {
|
|||||||
command: 'paste "%V"',
|
command: 'paste "%V"',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
private constructor (
|
private constructor (
|
||||||
private electron: ElectronService,
|
private electron: ElectronService,
|
||||||
private hostApp: HostAppService,
|
private hostApp: HostAppService,
|
||||||
|
@@ -21,7 +21,7 @@ import { RecoveryProvider } from './recoveryProvider'
|
|||||||
import { ShellSettingsTabProvider } from './settings'
|
import { ShellSettingsTabProvider } from './settings'
|
||||||
import { TerminalConfigProvider } from './config'
|
import { TerminalConfigProvider } from './config'
|
||||||
import { LocalTerminalHotkeyProvider } from './hotkeys'
|
import { LocalTerminalHotkeyProvider } from './hotkeys'
|
||||||
import { NewTabContextMenu } from './tabContextMenu'
|
import { NewTabContextMenu, SaveAsProfileContextMenu } from './tabContextMenu'
|
||||||
|
|
||||||
import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from './cli'
|
import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from './cli'
|
||||||
import { LocalProfilesService } from './profiles'
|
import { LocalProfilesService } from './profiles'
|
||||||
@@ -47,6 +47,7 @@ import { LocalProfilesService } from './profiles'
|
|||||||
{ provide: ProfileProvider, useClass: LocalProfilesService, multi: true },
|
{ provide: ProfileProvider, useClass: LocalProfilesService, multi: true },
|
||||||
|
|
||||||
{ provide: TabContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
|
{ provide: TabContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
|
||||||
|
{ provide: TabContextMenuItemProvider, useClass: SaveAsProfileContextMenu, multi: true },
|
||||||
|
|
||||||
{ provide: CLIHandler, useClass: TerminalCLIHandler, multi: true },
|
{ provide: CLIHandler, useClass: TerminalCLIHandler, multi: true },
|
||||||
{ provide: CLIHandler, useClass: OpenPathCLIHandler, multi: true },
|
{ provide: CLIHandler, useClass: OpenPathCLIHandler, multi: true },
|
||||||
|
@@ -1,9 +1,59 @@
|
|||||||
import { Inject, Injectable, Optional } from '@angular/core'
|
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 { TerminalTabComponent } from './components/terminalTab.component'
|
||||||
import { TerminalService } from './services/terminal.service'
|
import { TerminalService } from './services/terminal.service'
|
||||||
import { LocalProfile, UACService } from './api'
|
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 */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NewTabContextMenu extends TabContextMenuItemProvider {
|
export class NewTabContextMenu extends TabContextMenuItemProvider {
|
||||||
|
@@ -70,7 +70,6 @@ export class PluginManagerService {
|
|||||||
map(plugins => {
|
map(plugins => {
|
||||||
const mapping: Record<string, PluginInfo[]> = {}
|
const mapping: Record<string, PluginInfo[]> = {}
|
||||||
for (const p of plugins) {
|
for (const p of plugins) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
mapping[p.name] ??= []
|
mapping[p.name] ??= []
|
||||||
mapping[p.name].push(p)
|
mapping[p.name].push(p)
|
||||||
}
|
}
|
||||||
|
@@ -3,10 +3,10 @@ import { SerialPortStream } from '@serialport/stream'
|
|||||||
import { LogService, NotificationsService } from 'tabby-core'
|
import { LogService, NotificationsService } from 'tabby-core'
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable } from 'rxjs'
|
||||||
import { Injector, NgZone } from '@angular/core'
|
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'
|
import { SerialService } from './services/serial.service'
|
||||||
|
|
||||||
export interface SerialProfile extends ConnectableTerminalProfile {
|
export interface SerialProfile extends BaseTerminalProfile {
|
||||||
options: SerialProfileOptions
|
options: SerialProfileOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +21,6 @@ export interface SerialProfileOptions extends StreamProcessingOptions, LoginScri
|
|||||||
xoff?: boolean
|
xoff?: boolean
|
||||||
xany?: boolean
|
xany?: boolean
|
||||||
slowSend?: boolean
|
slowSend?: boolean
|
||||||
input: InputProcessingOptions,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BAUD_RATES = [
|
export const BAUD_RATES = [
|
||||||
@@ -66,7 +65,6 @@ export class SerialSession extends BaseSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.middleware.push(new UTF8SplitterMiddleware())
|
this.middleware.push(new UTF8SplitterMiddleware())
|
||||||
this.middleware.push(new InputProcessor(profile.options.input))
|
|
||||||
|
|
||||||
this.setLoginScriptsOptions(profile.options)
|
this.setLoginScriptsOptions(profile.options)
|
||||||
}
|
}
|
||||||
|
@@ -87,19 +87,9 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
|||||||
.description(translate) Sends data one byte at a time
|
.description(translate) Sends data one byte at a time
|
||||||
toggle([(ngModel)]='profile.options.slowSend')
|
toggle([(ngModel)]='profile.options.slowSend')
|
||||||
|
|
||||||
li(ngbNavItem)
|
|
||||||
a(ngbNavLink, translate) Colors
|
|
||||||
ng-template(ngbNavContent)
|
|
||||||
color-scheme-selector([(model)]='profile.terminalColorScheme')
|
|
||||||
|
|
||||||
li(ngbNavItem)
|
li(ngbNavItem)
|
||||||
a(ngbNavLink, translate) Login scripts
|
a(ngbNavLink, translate) Login scripts
|
||||||
ng-template(ngbNavContent)
|
ng-template(ngbNavContent)
|
||||||
login-scripts-settings([options]='profile.options')
|
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')
|
div([ngbNavOutlet]='nav')
|
||||||
|
@@ -2,14 +2,14 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
|||||||
import slugify from 'slugify'
|
import slugify from 'slugify'
|
||||||
import deepClone from 'clone-deep'
|
import deepClone from 'clone-deep'
|
||||||
import { Injectable } from '@angular/core'
|
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 { SerialProfileSettingsComponent } from './components/serialProfileSettings.component'
|
||||||
import { SerialTabComponent } from './components/serialTab.component'
|
import { SerialTabComponent } from './components/serialTab.component'
|
||||||
import { SerialService } from './services/serial.service'
|
import { SerialService } from './services/serial.service'
|
||||||
import { BAUD_RATES, SerialProfile } from './api'
|
import { BAUD_RATES, SerialProfile } from './api'
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class SerialProfilesService extends ConnectableProfileProvider<SerialProfile> {
|
export class SerialProfilesService extends ProfileProvider<SerialProfile> {
|
||||||
id = 'serial'
|
id = 'serial'
|
||||||
name = _('Serial')
|
name = _('Serial')
|
||||||
settingsComponent = SerialProfileSettingsComponent
|
settingsComponent = SerialProfileSettingsComponent
|
||||||
@@ -30,9 +30,7 @@ export class SerialProfilesService extends ConnectableProfileProvider<SerialProf
|
|||||||
outputNewlines: null,
|
outputNewlines: null,
|
||||||
scripts: [],
|
scripts: [],
|
||||||
slowSend: false,
|
slowSend: false,
|
||||||
input: { backspace: 'backspace' },
|
|
||||||
},
|
},
|
||||||
clearServiceMessagesOnConnect: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@@ -18,8 +18,8 @@
|
|||||||
"author": "Eugene Pankov",
|
"author": "Eugene Pankov",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/marked": "^5.0.1",
|
"@types/marked": "^4.0.8",
|
||||||
"marked": "^5.1.2",
|
"marked": "^4.2.12",
|
||||||
"ngx-infinite-scroll": "^16"
|
"ngx-infinite-scroll": "^16"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@@ -59,7 +59,7 @@ export class ConfigSyncSettingsTabComponent extends BaseComponent {
|
|||||||
const modal = this.ngbModal.open(PromptModalComponent)
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
modal.componentInstance.prompt = this.translate.instant('Name for the new config')
|
modal.componentInstance.prompt = this.translate.instant('Name for the new config')
|
||||||
modal.componentInstance.value = name
|
modal.componentInstance.value = name
|
||||||
name = (await modal.result.catch(() => null))?.value
|
name = (await modal.result)?.value
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user