Compare commits
No commits in common. "canary" and "v4.0.0-canary.4" have entirely different histories.
canary
...
v4.0.0-can
110 changed files with 3453 additions and 4785 deletions
|
|
@ -3,9 +3,7 @@
|
|||
"react",
|
||||
"prettier",
|
||||
"@typescript-eslint",
|
||||
"eslint-comments",
|
||||
"lodash",
|
||||
"import"
|
||||
"eslint-comments"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
|
|
@ -34,11 +32,7 @@
|
|||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
},
|
||||
"import/resolver": {
|
||||
"typescript": {}
|
||||
},
|
||||
"import/internal-regex": "^(electron|react)$"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"func-names": [
|
||||
|
|
@ -99,30 +93,10 @@
|
|||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
"@typescript-eslint/consistent-type-imports": [ "error", { "disallowTypeAnnotations": false } ],
|
||||
"lodash/prop-shorthand": [ "error", "always" ],
|
||||
"lodash/import-scope": [ "error", "method" ],
|
||||
"lodash/collection-return": "error",
|
||||
"lodash/collection-method-value": "error",
|
||||
"import/no-extraneous-dependencies": "error",
|
||||
"import/no-anonymous-default-export": "error",
|
||||
"import/order": [
|
||||
"@typescript-eslint/consistent-type-imports": [
|
||||
"error",
|
||||
{
|
||||
"groups": [
|
||||
"builtin",
|
||||
"internal",
|
||||
"external",
|
||||
"parent",
|
||||
"sibling",
|
||||
"index"
|
||||
],
|
||||
"newlines-between": "always",
|
||||
"alphabetize": {
|
||||
"order": "asc",
|
||||
"orderImportKind": "desc",
|
||||
"caseInsensitive": true
|
||||
}
|
||||
"disallowTypeAnnotations": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
|
|
@ -35,11 +35,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
|
|
@ -50,7 +50,7 @@ jobs:
|
|||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
|
@ -64,4 +64,4 @@ jobs:
|
|||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
|
|
|||
6
.github/workflows/e2e_comment.yml
vendored
6
.github/workflows/e2e_comment.yml
vendored
|
|
@ -14,14 +14,14 @@ jobs:
|
|||
WORKFLOW_RUN_INFO: ${{ toJSON(github.event.workflow_run) }}
|
||||
run: echo "$WORKFLOW_RUN_INFO"
|
||||
- name: Download Artifacts
|
||||
uses: dawidd6/action-download-artifact@v3.1.4
|
||||
uses: dawidd6/action-download-artifact@v2.27.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: nodejs.yml
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: e2e
|
||||
- name: Get PR number
|
||||
uses: dawidd6/action-download-artifact@v3.1.4
|
||||
uses: dawidd6/action-download-artifact@v2.27.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: nodejs.yml
|
||||
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
name: pr_num
|
||||
- name: Read the pr_num file
|
||||
id: pr_num_reader
|
||||
uses: juliangruber/read-file-action@v1.1.7
|
||||
uses: juliangruber/read-file-action@v1.1.6
|
||||
with:
|
||||
path: ./pr_num.txt
|
||||
- name: List images
|
||||
|
|
|
|||
35
.github/workflows/nodejs.yml
vendored
35
.github/workflows/nodejs.yml
vendored
|
|
@ -16,23 +16,21 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-latest
|
||||
- macos-12
|
||||
- ubuntu-20.04
|
||||
- windows-latest
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ env.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Fix node-gyp and Python
|
||||
run: python3 -m pip install packaging setuptools
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache/restore@v4
|
||||
- uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock', 'app/yarn.lock') }}
|
||||
|
|
@ -85,14 +83,8 @@ jobs:
|
|||
- name: Run E2E Tests
|
||||
if: runner.os != 'Linux'
|
||||
run: yarn run test:e2e
|
||||
- name: Run E2E Tests on Linux
|
||||
if: runner.os == 'Linux'
|
||||
uses: GabrielBB/xvfb-action@v1.6
|
||||
with:
|
||||
run: yarn run test:e2e
|
||||
env:
|
||||
SHELL: /bin/bash
|
||||
- name: Archive E2E test screenshot
|
||||
if: runner.os != 'Linux'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: e2e
|
||||
|
|
@ -108,14 +100,14 @@ jobs:
|
|||
with:
|
||||
name: pr_num
|
||||
path: ./pr_num.txt
|
||||
- uses: actions/cache/save@v4
|
||||
- uses: actions/cache/save@v3
|
||||
if: github.event_name == 'push'
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock', 'app/yarn.lock') }}
|
||||
|
||||
build-linux-arm:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
|
|
@ -128,17 +120,15 @@ jobs:
|
|||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ env.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Fix node-gyp and Python
|
||||
run: python3 -m pip install packaging setuptools
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache/restore@v4
|
||||
- uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock', 'app/yarn.lock') }}
|
||||
|
|
@ -173,7 +163,8 @@ jobs:
|
|||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update
|
||||
sudo apt install -y libglib2.0-0:i386 libexpat1:i386 libgcc-s1:i386
|
||||
sudo apt install -y libpcre2-8-0=10.34-7 --allow-downgrades
|
||||
sudo apt install -y libglib2.0-0:i386 libexpat1:i386
|
||||
npm_config_arch=armv7l yarn run v8-snapshot:arch
|
||||
- name: Build
|
||||
run: yarn run electron-builder -l deb rpm AppImage pacman --${{ matrix.name }} -c electron-builder-linux-ci.json
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import {EventEmitter} from 'events';
|
||||
|
||||
import fetch from 'electron-fetch';
|
||||
import {EventEmitter} from 'events';
|
||||
|
||||
class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
updateURL!: string;
|
||||
|
|
@ -47,6 +46,4 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
const autoUpdaterLinux = new AutoUpdater();
|
||||
|
||||
export default autoUpdaterLinux;
|
||||
export default new AutoUpdater();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import {app, Menu} from 'electron';
|
||||
import type {BrowserWindow} from 'electron';
|
||||
|
||||
import {app, Menu} from 'electron';
|
||||
import {openConfig, getConfig} from './config';
|
||||
import {updatePlugins} from './plugins';
|
||||
import {installCLI} from './utils/cli-install';
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import {app} from 'electron';
|
||||
|
||||
import chokidar from 'chokidar';
|
||||
|
||||
import type {parsedConfig, configOptions} from '../typings/config';
|
||||
|
||||
import notify from './notify';
|
||||
import {_import, getDefaultConfig} from './config/import';
|
||||
import _openConfig from './config/open';
|
||||
import {cfgPath, cfgDir} from './config/paths';
|
||||
import notify from './notify';
|
||||
import {getColorMap} from './utils/colors';
|
||||
import type {parsedConfig, configOptions} from '../lib/config';
|
||||
import {app} from 'electron';
|
||||
|
||||
const watchers: Function[] = [];
|
||||
let cfg: parsedConfig = {} as any;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import {readFileSync, mkdirpSync} from 'fs-extra';
|
||||
|
||||
import type {rawConfig} from '../../typings/config';
|
||||
import notify from '../notify';
|
||||
|
||||
import {_init} from './init';
|
||||
import {migrateHyper3Config} from './migrate';
|
||||
import {defaultCfg, cfgPath, plugs, defaultPlatformKeyPath} from './paths';
|
||||
import {_init} from './init';
|
||||
import notify from '../notify';
|
||||
import type {rawConfig} from '../../lib/config';
|
||||
import {migrateHyper3Config} from './migrate';
|
||||
|
||||
let defaultConfig: rawConfig;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import vm from 'vm';
|
||||
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
import type {parsedConfig, rawConfig, configOptions} from '../../typings/config';
|
||||
import notify from '../notify';
|
||||
import mapKeys from '../utils/map-keys';
|
||||
import type {parsedConfig, rawConfig, configOptions} from '../../lib/config';
|
||||
import _ from 'lodash';
|
||||
|
||||
const _extract = (script?: vm.Script): Record<string, any> => {
|
||||
const module: Record<string, any> = {};
|
||||
|
|
@ -21,7 +19,7 @@ const _syntaxValidation = (cfg: string) => {
|
|||
return new vm.Script(cfg, {filename: '.hyper.js'});
|
||||
} catch (_err) {
|
||||
const err = _err as {name: string};
|
||||
notify(`Error loading config: ${err.name}`, JSON.stringify(err), {error: err});
|
||||
notify(`Error loading config: ${err.name}`, `${err}`, {error: err});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -46,7 +44,7 @@ const _init = (userCfg: rawConfig, defaultCfg: rawConfig): parsedConfig => {
|
|||
if (!conf.profiles.map((p) => p.name).includes(conf.defaultProfile)) {
|
||||
conf.defaultProfile = conf.profiles[0].name;
|
||||
}
|
||||
return merge({}, defaultCfg.config, conf);
|
||||
return _.merge({}, defaultCfg.config, conf);
|
||||
} else {
|
||||
notify('Error reading configuration: `config` key is missing');
|
||||
return defaultCfg.config || ({} as configOptions);
|
||||
|
|
@ -55,8 +53,8 @@ const _init = (userCfg: rawConfig, defaultCfg: rawConfig): parsedConfig => {
|
|||
// Merging platform specific keymaps with user defined keymaps
|
||||
keymaps: mapKeys({...defaultCfg.keymaps, ...userCfg?.keymaps}),
|
||||
// Ignore undefined values in plugin and localPlugins array Issue #1862
|
||||
plugins: userCfg?.plugins?.filter(Boolean) || [],
|
||||
localPlugins: userCfg?.localPlugins?.filter(Boolean) || []
|
||||
plugins: (userCfg?.plugins && userCfg.plugins.filter(Boolean)) || [],
|
||||
localPlugins: (userCfg?.localPlugins && userCfg.localPlugins.filter(Boolean)) || []
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
import {dirname, resolve} from 'path';
|
||||
|
||||
import {builders, namedTypes} from 'ast-types';
|
||||
import type {ExpressionKind} from 'ast-types/lib/gen/kinds';
|
||||
import {copy, copySync, existsSync, readFileSync, writeFileSync} from 'fs-extra';
|
||||
import merge from 'lodash/merge';
|
||||
import {parse, prettyPrint} from 'recast';
|
||||
import {builders, namedTypes} from 'ast-types';
|
||||
import * as babelParser from 'recast/parsers/babel';
|
||||
import {copy, copySync, existsSync, readFileSync, writeFileSync} from 'fs-extra';
|
||||
import {dirname, resolve} from 'path';
|
||||
import _ from 'lodash';
|
||||
|
||||
import notify from '../notify';
|
||||
|
||||
import {_extractDefault} from './init';
|
||||
import {cfgDir, cfgPath, defaultCfg, legacyCfgPath, plugs, schemaFile, schemaPath} from './paths';
|
||||
import type {ExpressionKind} from 'ast-types/lib/gen/kinds';
|
||||
|
||||
// function to remove all json serializable entries from an array expression
|
||||
function removeElements(node: namedTypes.ArrayExpression): namedTypes.ArrayExpression {
|
||||
|
|
@ -168,7 +166,7 @@ export const migrateHyper3Config = () => {
|
|||
try {
|
||||
const legacyCfgRaw = readFileSync(legacyCfgPath, 'utf8');
|
||||
const legacyCfgData = _extractDefault(legacyCfgRaw);
|
||||
newCfgData = merge({}, defaultCfgData, legacyCfgData);
|
||||
newCfgData = _.merge({}, defaultCfgData, legacyCfgData);
|
||||
|
||||
const pluginCode = configToPlugin(legacyCfgRaw);
|
||||
if (pluginCode) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import {exec} from 'child_process';
|
||||
|
||||
import {shell} from 'electron';
|
||||
|
||||
import * as Registry from 'native-reg';
|
||||
|
||||
import {cfgPath} from './paths';
|
||||
import * as Registry from 'native-reg';
|
||||
import {exec} from 'child_process';
|
||||
|
||||
const getUserChoiceKey = () => {
|
||||
try {
|
||||
|
|
@ -60,7 +57,7 @@ const openNotepad = (file: string) =>
|
|||
});
|
||||
});
|
||||
|
||||
const openConfig = () => {
|
||||
export default () => {
|
||||
// Windows opens .js files with WScript.exe by default
|
||||
// If the user hasn't set up an editor for .js files, we fallback to notepad.
|
||||
if (process.platform === 'win32') {
|
||||
|
|
@ -76,5 +73,3 @@ const openConfig = () => {
|
|||
}
|
||||
return shell.openPath(cfgPath).then((error) => error === '');
|
||||
};
|
||||
|
||||
export default openConfig;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
// This module exports paths, names, and other metadata that is referenced
|
||||
import {statSync} from 'fs';
|
||||
import {homedir} from 'os';
|
||||
import {resolve, join} from 'path';
|
||||
|
||||
import {app} from 'electron';
|
||||
|
||||
import {statSync} from 'fs';
|
||||
import {resolve, join} from 'path';
|
||||
import isDev from 'electron-is-dev';
|
||||
|
||||
const cfgFile = 'hyper.json';
|
||||
|
|
@ -17,15 +15,15 @@ const homeDirectory = homedir();
|
|||
let cfgDir = process.env.XDG_CONFIG_HOME
|
||||
? join(process.env.XDG_CONFIG_HOME, 'Hyper')
|
||||
: process.platform === 'win32'
|
||||
? app.getPath('userData')
|
||||
: join(homeDirectory, '.config', 'Hyper');
|
||||
? app.getPath('userData')
|
||||
: join(homeDirectory, '.config', 'Hyper');
|
||||
|
||||
const legacyCfgPath = join(
|
||||
process.env.XDG_CONFIG_HOME !== undefined
|
||||
? join(process.env.XDG_CONFIG_HOME, 'hyper')
|
||||
: process.platform == 'win32'
|
||||
? app.getPath('userData')
|
||||
: homedir(),
|
||||
? app.getPath('userData')
|
||||
: homedir(),
|
||||
'.hyper.js'
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,7 @@
|
|||
},
|
||||
"bell": {
|
||||
"description": "Supported Options:\n1. 'SOUND' -> Enables the bell as a sound\n2. false: turns off the bell",
|
||||
"enum": [
|
||||
"SOUND",
|
||||
false
|
||||
]
|
||||
"type": "string"
|
||||
},
|
||||
"bellSound": {
|
||||
"description": "base64 encoded string of the sound file to use for the bell\nif null, the default bell will be used",
|
||||
|
|
@ -360,10 +357,7 @@
|
|||
},
|
||||
"bell": {
|
||||
"description": "Supported Options:\n1. 'SOUND' -> Enables the bell as a sound\n2. false: turns off the bell",
|
||||
"enum": [
|
||||
"SOUND",
|
||||
false
|
||||
]
|
||||
"type": "string"
|
||||
},
|
||||
"bellSound": {
|
||||
"description": "base64 encoded string of the sound file to use for the bell\nif null, the default bell will be used",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import type {BrowserWindow} from 'electron';
|
||||
|
||||
import Config from 'electron-store';
|
||||
import type {BrowserWindow} from 'electron';
|
||||
|
||||
export const defaults = {
|
||||
windowPosition: [50, 50] as [number, number],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
declare module 'php-escape-shell' {
|
||||
export function php_escapeshellcmd(path: string): string;
|
||||
}
|
||||
|
||||
declare module 'git-describe' {
|
||||
export function gitDescribe(...args: any[]): void;
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import type {Server} from '../app/rpc';
|
||||
import type {Server} from './rpc';
|
||||
|
||||
declare global {
|
||||
namespace Electron {
|
||||
interface App {
|
||||
config: typeof import('../app/config');
|
||||
plugins: typeof import('../app/plugins');
|
||||
config: typeof import('./config');
|
||||
plugins: typeof import('./plugins');
|
||||
getWindows: () => Set<BrowserWindow>;
|
||||
getLastFocusedWindow: () => BrowserWindow | null;
|
||||
windowCallback?: (win: BrowserWindow) => void;
|
||||
1
app/index.d.ts
vendored
Normal file
1
app/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
// Dummy file, required by tsc
|
||||
20
app/index.ts
20
app/index.ts
|
|
@ -1,4 +1,3 @@
|
|||
// eslint-disable-next-line import/order
|
||||
import {cfgPath} from './config/paths';
|
||||
|
||||
// Print diagnostic information for a few arguments instead of running Hyper.
|
||||
|
|
@ -12,30 +11,27 @@ if (['--help', '-v', '--version'].includes(process.argv[1])) {
|
|||
}
|
||||
|
||||
// Enable remote module
|
||||
// eslint-disable-next-line import/order
|
||||
import {initialize as remoteInitialize} from '@electron/remote/main';
|
||||
remoteInitialize();
|
||||
|
||||
// set up config
|
||||
// eslint-disable-next-line import/order
|
||||
import * as config from './config';
|
||||
config.setup();
|
||||
|
||||
// Native
|
||||
import {resolve} from 'path';
|
||||
|
||||
// Packages
|
||||
import {app, BrowserWindow, Menu, screen} from 'electron';
|
||||
|
||||
import isDev from 'electron-is-dev';
|
||||
import {gitDescribe} from 'git-describe';
|
||||
import parseUrl from 'parse-url';
|
||||
import isDev from 'electron-is-dev';
|
||||
import * as config from './config';
|
||||
|
||||
// set up config
|
||||
config.setup();
|
||||
|
||||
import * as AppMenu from './menus/menu';
|
||||
import * as plugins from './plugins';
|
||||
import {newWindow} from './ui/window';
|
||||
import {installCLI} from './utils/cli-install';
|
||||
import * as AppMenu from './menus/menu';
|
||||
import {newWindow} from './ui/window';
|
||||
import * as windowUtils from './utils/window-utils';
|
||||
import parseUrl from 'parse-url';
|
||||
|
||||
const windowSet = new Set<BrowserWindow>([]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
// Packages
|
||||
import {app, dialog, Menu} from 'electron';
|
||||
import type {BrowserWindow} from 'electron';
|
||||
import {app, dialog, Menu} from 'electron';
|
||||
|
||||
// Utilities
|
||||
import {execCommand} from '../commands';
|
||||
import {getConfig} from '../config';
|
||||
import {icon} from '../config/paths';
|
||||
import {getDecoratedKeymaps} from '../plugins';
|
||||
import {getRendererTypes} from '../utils/renderer-utils';
|
||||
|
||||
import darwinMenu from './menus/darwin';
|
||||
import editMenu from './menus/edit';
|
||||
import helpMenu from './menus/help';
|
||||
import shellMenu from './menus/shell';
|
||||
import toolsMenu from './menus/tools';
|
||||
import viewMenu from './menus/view';
|
||||
import shellMenu from './menus/shell';
|
||||
import editMenu from './menus/edit';
|
||||
import toolsMenu from './menus/tools';
|
||||
import windowMenu from './menus/window';
|
||||
import helpMenu from './menus/help';
|
||||
import darwinMenu from './menus/darwin';
|
||||
import {getDecoratedKeymaps} from '../plugins';
|
||||
import {execCommand} from '../commands';
|
||||
import {getRendererTypes} from '../utils/renderer-utils';
|
||||
|
||||
const appName = app.name;
|
||||
const appVersion = app.getVersion();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// This menu label is overrided by OSX to be the appName
|
||||
// The label is set to appName here so it matches actual behavior
|
||||
import {app} from 'electron';
|
||||
import type {BrowserWindow, MenuItemConstructorOptions} from 'electron';
|
||||
import {app} from 'electron';
|
||||
|
||||
const darwinMenu = (
|
||||
export default (
|
||||
commandKeys: Record<string, string>,
|
||||
execCommand: (command: string, focusedWindow?: BrowserWindow) => void,
|
||||
showAbout: () => void
|
||||
|
|
@ -55,5 +55,3 @@ const darwinMenu = (
|
|||
]
|
||||
};
|
||||
};
|
||||
|
||||
export default darwinMenu;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type {BrowserWindow, MenuItemConstructorOptions} from 'electron';
|
||||
|
||||
const editMenu = (
|
||||
export default (
|
||||
commandKeys: Record<string, string>,
|
||||
execCommand: (command: string, focusedWindow?: BrowserWindow) => void
|
||||
) => {
|
||||
|
|
@ -147,5 +147,3 @@ const editMenu = (
|
|||
submenu
|
||||
};
|
||||
};
|
||||
|
||||
export default editMenu;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import {release} from 'os';
|
||||
|
||||
import {app, shell, dialog, clipboard} from 'electron';
|
||||
import type {MenuItemConstructorOptions} from 'electron';
|
||||
|
||||
import {app, shell, dialog, clipboard} from 'electron';
|
||||
import {getConfig, getPlugins} from '../../config';
|
||||
const {arch, env, platform, versions} = process;
|
||||
import {version} from '../../package.json';
|
||||
|
||||
const {arch, env, platform, versions} = process;
|
||||
|
||||
const helpMenu = (commands: Record<string, string>, showAbout: () => void): MenuItemConstructorOptions => {
|
||||
export default (commands: Record<string, string>, showAbout: () => void): MenuItemConstructorOptions => {
|
||||
const submenu: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: `${app.name} Website`,
|
||||
|
|
@ -110,5 +107,3 @@ ${JSON.stringify(getPlugins(), null, 2)}
|
|||
submenu
|
||||
};
|
||||
};
|
||||
|
||||
export default helpMenu;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type {BrowserWindow, MenuItemConstructorOptions} from 'electron';
|
||||
|
||||
const shellMenu = (
|
||||
export default (
|
||||
commandKeys: Record<string, string>,
|
||||
execCommand: (command: string, focusedWindow?: BrowserWindow) => void,
|
||||
profiles: string[]
|
||||
|
|
@ -100,5 +100,3 @@ const shellMenu = (
|
|||
]
|
||||
};
|
||||
};
|
||||
|
||||
export default shellMenu;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type {BrowserWindow, MenuItemConstructorOptions} from 'electron';
|
||||
|
||||
const toolsMenu = (
|
||||
export default (
|
||||
commands: Record<string, string>,
|
||||
execCommand: (command: string, focusedWindow?: BrowserWindow) => void
|
||||
): MenuItemConstructorOptions => {
|
||||
|
|
@ -45,5 +45,3 @@ const toolsMenu = (
|
|||
]
|
||||
};
|
||||
};
|
||||
|
||||
export default toolsMenu;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type {BrowserWindow, MenuItemConstructorOptions} from 'electron';
|
||||
|
||||
const viewMenu = (
|
||||
export default (
|
||||
commandKeys: Record<string, string>,
|
||||
execCommand: (command: string, focusedWindow?: BrowserWindow) => void
|
||||
): MenuItemConstructorOptions => {
|
||||
|
|
@ -55,5 +55,3 @@ const viewMenu = (
|
|||
]
|
||||
};
|
||||
};
|
||||
|
||||
export default viewMenu;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type {BrowserWindow, MenuItemConstructorOptions} from 'electron';
|
||||
|
||||
const windowMenu = (
|
||||
export default (
|
||||
commandKeys: Record<string, string>,
|
||||
execCommand: (command: string, focusedWindow?: BrowserWindow) => void
|
||||
): MenuItemConstructorOptions => {
|
||||
|
|
@ -94,5 +94,3 @@ const windowMenu = (
|
|||
]
|
||||
};
|
||||
};
|
||||
|
||||
export default windowMenu;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import type {BrowserWindow} from 'electron';
|
||||
|
||||
import fetch from 'electron-fetch';
|
||||
import ms from 'ms';
|
||||
|
||||
import fetch from 'electron-fetch';
|
||||
import {version} from './package.json';
|
||||
import type {BrowserWindow} from 'electron';
|
||||
|
||||
const NEWS_URL = 'https://hyper-news.now.sh';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import {app, Notification} from 'electron';
|
||||
|
||||
import {icon} from './config/paths';
|
||||
|
||||
export default function notify(title: string, body = '', details: {error?: any} = {}) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "hyper",
|
||||
"productName": "Hyper",
|
||||
"description": "A terminal built on web technologies",
|
||||
"version": "4.0.0-canary.5",
|
||||
"version": "4.0.0-canary.4",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "ZEIT, Inc.",
|
||||
|
|
@ -13,18 +13,16 @@
|
|||
"postinstall": "npx patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/parser": "7.24.4",
|
||||
"@electron/remote": "2.1.2",
|
||||
"ast-types": "^0.16.1",
|
||||
"@babel/parser": "7.22.5",
|
||||
"@electron/remote": "2.0.10",
|
||||
"async-retry": "1.3.3",
|
||||
"chokidar": "^3.6.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"color": "4.2.3",
|
||||
"default-shell": "1.0.1",
|
||||
"electron-devtools-installer": "3.2.0",
|
||||
"electron-fetch": "1.9.1",
|
||||
"electron-is-dev": "2.0.0",
|
||||
"electron-store": "8.2.0",
|
||||
"fs-extra": "11.2.0",
|
||||
"electron-store": "8.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"git-describe": "4.1.1",
|
||||
"lodash": "4.17.21",
|
||||
"ms": "2.1.3",
|
||||
|
|
@ -33,13 +31,13 @@
|
|||
"os-locale": "5.0.0",
|
||||
"parse-url": "8.1.0",
|
||||
"queue": "6.0.2",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"recast": "0.23.6",
|
||||
"semver": "7.6.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"recast": "0.23.2",
|
||||
"semver": "7.5.3",
|
||||
"shell-env": "3.0.1",
|
||||
"sudo-prompt": "^9.2.1",
|
||||
"uuid": "9.0.1"
|
||||
"uuid": "9.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"native-reg": "1.1.1"
|
||||
|
|
|
|||
|
|
@ -1,28 +1,24 @@
|
|||
/* eslint-disable eslint-comments/disable-enable-pair */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
import {exec, execFile} from 'child_process';
|
||||
import {writeFileSync} from 'fs';
|
||||
import {resolve, basename} from 'path';
|
||||
import {promisify} from 'util';
|
||||
|
||||
import {app, dialog, ipcMain as _ipcMain} from 'electron';
|
||||
import type {BrowserWindow, App, MenuItemConstructorOptions} from 'electron';
|
||||
import React from 'react';
|
||||
|
||||
import {app, dialog, ipcMain as _ipcMain} from 'electron';
|
||||
import {resolve, basename} from 'path';
|
||||
import {writeFileSync} from 'fs';
|
||||
import Config from 'electron-store';
|
||||
import ms from 'ms';
|
||||
import React from 'react';
|
||||
import ReactDom from 'react-dom';
|
||||
|
||||
import type {IpcMainWithCommands} from '../typings/common';
|
||||
import type {configOptions} from '../typings/config';
|
||||
|
||||
import * as config from './config';
|
||||
import {plugs} from './config/paths';
|
||||
import notify from './notify';
|
||||
import {availableExtensions} from './plugins/extensions';
|
||||
import {install} from './plugins/install';
|
||||
import {plugs} from './config/paths';
|
||||
import mapKeys from './utils/map-keys';
|
||||
import type {configOptions} from '../lib/config';
|
||||
import {promisify} from 'util';
|
||||
import {exec, execFile} from 'child_process';
|
||||
import type {IpcMainWithCommands} from '../common';
|
||||
|
||||
// local storage
|
||||
const cache = new Config();
|
||||
|
|
@ -471,10 +467,3 @@ ipcMain.handle('child_process.exec', (event, command, options) => {
|
|||
ipcMain.handle('child_process.execFile', (event, file, args, options) => {
|
||||
return promisify(execFile)(file, args, options);
|
||||
});
|
||||
|
||||
ipcMain.handle('getLoadedPluginVersions', () => getLoadedPluginVersions());
|
||||
ipcMain.handle('getPaths', () => getPaths());
|
||||
ipcMain.handle('getBasePaths', () => getBasePaths());
|
||||
ipcMain.handle('getDeprecatedConfig', () => getDeprecatedConfig());
|
||||
ipcMain.handle('getDecoratedConfig', (e, profile) => getDecoratedConfig(profile));
|
||||
ipcMain.handle('getDecoratedKeymaps', () => getDecoratedKeymaps());
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import cp from 'child_process';
|
||||
|
||||
import ms from 'ms';
|
||||
import queue from 'queue';
|
||||
|
||||
import ms from 'ms';
|
||||
import {yarn, plugs} from '../config/paths';
|
||||
|
||||
export const install = (fn: (err: string | null) => void) => {
|
||||
|
|
|
|||
13
app/rpc.ts
13
app/rpc.ts
|
|
@ -1,11 +1,8 @@
|
|||
import {EventEmitter} from 'events';
|
||||
|
||||
import {ipcMain} from 'electron';
|
||||
import type {BrowserWindow, IpcMainEvent} from 'electron';
|
||||
|
||||
import {ipcMain} from 'electron';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
import type {TypedEmitter, MainEvents, RendererEvents, FilterNever} from '../typings/common';
|
||||
import type {TypedEmitter, MainEvents, RendererEvents, FilterNever} from '../common';
|
||||
|
||||
export class Server {
|
||||
emitter: TypedEmitter<MainEvents>;
|
||||
|
|
@ -31,7 +28,7 @@ export class Server {
|
|||
// to support reloading the window and re-initializing
|
||||
// the channel
|
||||
this.wc.on('did-finish-load', () => {
|
||||
this.wc.send('init', uid, win.profileName);
|
||||
this.wc.send('init', uid);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -76,8 +73,6 @@ export class Server {
|
|||
}
|
||||
}
|
||||
|
||||
const createRPC = (win: BrowserWindow) => {
|
||||
export default (win: BrowserWindow) => {
|
||||
return new Server(win);
|
||||
};
|
||||
|
||||
export default createRPC;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
import {EventEmitter} from 'events';
|
||||
import {dirname} from 'path';
|
||||
import {StringDecoder} from 'string_decoder';
|
||||
|
||||
import defaultShell from 'default-shell';
|
||||
import type {IPty, IWindowsPtyForkOptions, spawn as npSpawn} from 'node-pty';
|
||||
import osLocale from 'os-locale';
|
||||
import shellEnv from 'shell-env';
|
||||
|
||||
import * as config from './config';
|
||||
import {cliScriptPath} from './config/paths';
|
||||
import {productName, version} from './package.json';
|
||||
import {getDecoratedEnv} from './plugins';
|
||||
import {getFallBackShellConfig} from './utils/shell-fallback';
|
||||
import {productName, version} from './package.json';
|
||||
import * as config from './config';
|
||||
import type {IPty, IWindowsPtyForkOptions, spawn as npSpawn} from 'node-pty';
|
||||
import {cliScriptPath} from './config/paths';
|
||||
import {dirname} from 'path';
|
||||
import shellEnv from 'shell-env';
|
||||
import osLocale from 'os-locale';
|
||||
|
||||
const createNodePtyError = () =>
|
||||
new Error(
|
||||
|
|
@ -185,32 +182,15 @@ export default class Session extends EventEmitter {
|
|||
// this will inform users in case there are errors in the config instead of instant exit
|
||||
const runDuration = new Date().getTime() - this.initTimestamp;
|
||||
if (e.exitCode > 0 && runDuration < 1000) {
|
||||
const fallBackShellConfig = getFallBackShellConfig(shell, shellArgs, defaultShell, defaultShellArgs);
|
||||
if (fallBackShellConfig) {
|
||||
const msg = `
|
||||
const defaultShellConfig = {shell: defaultShell, shellArgs: defaultShellArgs};
|
||||
const msg = `
|
||||
shell exited in ${runDuration} ms with exit code ${e.exitCode}
|
||||
please check the shell config: ${JSON.stringify({shell, shellArgs}, undefined, 2)}
|
||||
using fallback shell config: ${JSON.stringify(fallBackShellConfig, undefined, 2)}
|
||||
fallback to default shell config: ${JSON.stringify(defaultShellConfig, undefined, 2)}
|
||||
`;
|
||||
console.warn(msg);
|
||||
this.batcher?.write(msg.replace(/\n/g, '\r\n'));
|
||||
this.init({
|
||||
uid,
|
||||
rows,
|
||||
cols,
|
||||
cwd,
|
||||
shell: fallBackShellConfig.shell,
|
||||
shellArgs: fallBackShellConfig.shellArgs,
|
||||
profile
|
||||
});
|
||||
} else {
|
||||
const msg = `
|
||||
shell exited in ${runDuration} ms with exit code ${e.exitCode}
|
||||
No fallback available, please check the shell config.
|
||||
`;
|
||||
console.warn(msg);
|
||||
this.batcher?.write(msg.replace(/\n/g, '\r\n'));
|
||||
}
|
||||
console.warn(msg);
|
||||
this.batcher?.write(msg.replace(/\n/g, '\r\n'));
|
||||
this.init({uid, rows, cols, cwd, ...defaultShellConfig, profile});
|
||||
} else {
|
||||
this.ended = true;
|
||||
this.emit('exit');
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"./package.json",
|
||||
"../typings/extend-electron.d.ts",
|
||||
"../typings/ext-modules.d.ts"
|
||||
"./package.json"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import type {MenuItemConstructorOptions, BrowserWindow} from 'electron';
|
||||
|
||||
import {execCommand} from '../commands';
|
||||
import {getProfiles} from '../config';
|
||||
import editMenu from '../menus/menus/edit';
|
||||
import shellMenu from '../menus/menus/shell';
|
||||
import {execCommand} from '../commands';
|
||||
import {getDecoratedKeymaps} from '../plugins';
|
||||
|
||||
import type {MenuItemConstructorOptions, BrowserWindow} from 'electron';
|
||||
import {getProfiles} from '../config';
|
||||
const separator: MenuItemConstructorOptions = {type: 'separator'};
|
||||
|
||||
const getCommandKeys = (keymaps: Record<string, string[]>): Record<string, string> =>
|
||||
|
|
@ -23,7 +21,7 @@ const filterCutCopy = (selection: string, menuItem: MenuItemConstructorOptions)
|
|||
return menuItem;
|
||||
};
|
||||
|
||||
const contextMenuTemplate = (
|
||||
export default (
|
||||
createWindow: (fn?: (win: BrowserWindow) => void, options?: Record<string, any>) => BrowserWindow,
|
||||
selection: string
|
||||
) => {
|
||||
|
|
@ -38,5 +36,3 @@ const contextMenuTemplate = (
|
|||
.concat(separator, _shell)
|
||||
.filter((menuItem) => !Object.prototype.hasOwnProperty.call(menuItem, 'enabled') || menuItem.enabled);
|
||||
};
|
||||
|
||||
export default contextMenuTemplate;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,26 @@
|
|||
import {existsSync} from 'fs';
|
||||
import type {BrowserWindowConstructorOptions} from 'electron';
|
||||
import {app, BrowserWindow, shell, Menu} from 'electron';
|
||||
import {isAbsolute, normalize, sep} from 'path';
|
||||
import {URL, fileURLToPath} from 'url';
|
||||
|
||||
import {app, BrowserWindow, shell, Menu} from 'electron';
|
||||
import type {BrowserWindowConstructorOptions} from 'electron';
|
||||
|
||||
import {enable as remoteEnable} from '@electron/remote/main';
|
||||
import isDev from 'electron-is-dev';
|
||||
import {getWorkingDirectoryFromPID} from 'native-process-working-directory';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
import type {sessionExtraOptions} from '../../typings/common';
|
||||
import type {configOptions} from '../../typings/config';
|
||||
import {execCommand} from '../commands';
|
||||
import {getDefaultProfile} from '../config';
|
||||
import {icon, homeDirectory} from '../config/paths';
|
||||
import fetchNotifications from '../notifications';
|
||||
import notify from '../notify';
|
||||
import {decorateSessionOptions, decorateSessionClass} from '../plugins';
|
||||
import createRPC from '../rpc';
|
||||
import Session from '../session';
|
||||
import isDev from 'electron-is-dev';
|
||||
import updater from '../updater';
|
||||
import {setRendererType, unsetRendererType} from '../utils/renderer-utils';
|
||||
import toElectronBackgroundColor from '../utils/to-electron-background-color';
|
||||
|
||||
import {icon, homeDirectory} from '../config/paths';
|
||||
import createRPC from '../rpc';
|
||||
import notify from '../notify';
|
||||
import fetchNotifications from '../notifications';
|
||||
import Session from '../session';
|
||||
import contextMenuTemplate from './contextmenu';
|
||||
import {execCommand} from '../commands';
|
||||
import {setRendererType, unsetRendererType} from '../utils/renderer-utils';
|
||||
import {decorateSessionOptions, decorateSessionClass} from '../plugins';
|
||||
import {enable as remoteEnable} from '@electron/remote/main';
|
||||
import type {configOptions} from '../../lib/config';
|
||||
import {getWorkingDirectoryFromPID} from 'native-process-working-directory';
|
||||
import {existsSync} from 'fs';
|
||||
import type {sessionExtraOptions} from '../../common';
|
||||
import {getDefaultProfile} from '../config';
|
||||
|
||||
export function newWindow(
|
||||
options_: BrowserWindowConstructorOptions,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
// Packages
|
||||
import electron, {app} from 'electron';
|
||||
import type {BrowserWindow, AutoUpdater} from 'electron';
|
||||
|
||||
import retry from 'async-retry';
|
||||
import electron, {app} from 'electron';
|
||||
import ms from 'ms';
|
||||
import retry from 'async-retry';
|
||||
|
||||
// Utilities
|
||||
import autoUpdaterLinux from './auto-updater-linux';
|
||||
import {getDefaultProfile} from './config';
|
||||
import {version} from './package.json';
|
||||
import {getDecoratedConfig} from './plugins';
|
||||
import autoUpdaterLinux from './auto-updater-linux';
|
||||
import {getDefaultProfile} from './config';
|
||||
|
||||
const {platform} = process;
|
||||
const isLinux = platform === 'linux';
|
||||
|
|
@ -72,7 +71,7 @@ async function init() {
|
|||
isInit = true;
|
||||
}
|
||||
|
||||
const updater = (win: BrowserWindow) => {
|
||||
export default (win: BrowserWindow) => {
|
||||
if (!isInit) {
|
||||
void init();
|
||||
}
|
||||
|
|
@ -116,5 +115,3 @@ const updater = (win: BrowserWindow) => {
|
|||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default updater;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
import {existsSync, readlink, symlink} from 'fs';
|
||||
import path from 'path';
|
||||
import {promisify} from 'util';
|
||||
|
||||
import {clipboard, dialog} from 'electron';
|
||||
|
||||
import {mkdirpSync} from 'fs-extra';
|
||||
import notify from '../notify';
|
||||
import {cliScriptPath, cliLinkPath} from '../config/paths';
|
||||
import * as Registry from 'native-reg';
|
||||
import type {ValueType} from 'native-reg';
|
||||
import sudoPrompt from 'sudo-prompt';
|
||||
|
||||
import {cliScriptPath, cliLinkPath} from '../config/paths';
|
||||
import notify from '../notify';
|
||||
import {clipboard, dialog} from 'electron';
|
||||
import {mkdirpSync} from 'fs-extra';
|
||||
import {promisify} from 'util';
|
||||
|
||||
const readLink = promisify(readlink);
|
||||
const symLink = promisify(symlink);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const generatePrefixedCommand = (command: string, shortcuts: string[]) => {
|
|||
return result;
|
||||
};
|
||||
|
||||
const mapKeys = (config: Record<string, string[] | string>) => {
|
||||
export default (config: Record<string, string[] | string>) => {
|
||||
return Object.keys(config).reduce((keymap: Record<string, string[]>, command: string) => {
|
||||
if (!command) {
|
||||
return keymap;
|
||||
|
|
@ -39,5 +39,3 @@ const mapKeys = (config: Record<string, string[] | string>) => {
|
|||
return keymap;
|
||||
}, {});
|
||||
};
|
||||
|
||||
export default mapKeys;
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
export const getFallBackShellConfig = (
|
||||
shell: string,
|
||||
shellArgs: string[],
|
||||
defaultShell: string,
|
||||
defaultShellArgs: string[]
|
||||
): {
|
||||
shell: string;
|
||||
shellArgs: string[];
|
||||
} | null => {
|
||||
if (shellArgs.length > 0) {
|
||||
return {
|
||||
shell,
|
||||
shellArgs: []
|
||||
};
|
||||
}
|
||||
|
||||
if (shell != defaultShell) {
|
||||
return {
|
||||
shell: defaultShell,
|
||||
shellArgs: defaultShellArgs
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
|
@ -4,7 +4,7 @@ import Color from 'color';
|
|||
// returns a background color that's in hex
|
||||
// format including the alpha channel (e.g.: `#00000050`)
|
||||
// input can be any css value (rgb, hsl, string…)
|
||||
const toElectronBackgroundColor = (bgColor: string) => {
|
||||
export default (bgColor: string) => {
|
||||
const color = Color(bgColor);
|
||||
|
||||
if (color.alpha() === 1) {
|
||||
|
|
@ -15,5 +15,3 @@ const toElectronBackgroundColor = (bgColor: string) => {
|
|||
const alphaHex = Math.round(color.alpha() * 255).toString(16);
|
||||
return `#${alphaHex}${color.hex().toString().slice(1)}`;
|
||||
};
|
||||
|
||||
export default toElectronBackgroundColor;
|
||||
|
|
|
|||
449
app/yarn.lock
449
app/yarn.lock
|
|
@ -2,15 +2,15 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/parser@7.24.4":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
|
||||
integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==
|
||||
"@babel/parser@7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea"
|
||||
integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==
|
||||
|
||||
"@electron/remote@2.1.2":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/@electron/remote/-/remote-2.1.2.tgz#52a97c8faa5b769155b649ef262f2f8c851776e6"
|
||||
integrity sha512-EPwNx+nhdrTBxyCqXt/pftoQg/ybtWDW3DUWHafejvnB1ZGGfMpv6e15D8KeempocjXe78T7WreyGGb3mlZxdA==
|
||||
"@electron/remote@2.0.10":
|
||||
version "2.0.10"
|
||||
resolved "https://registry.npmjs.org/@electron/remote/-/remote-2.0.10.tgz#133e2f607b1861ac249bd78b5abd1e961feed713"
|
||||
integrity sha512-3SFKKaQXcyWgwmibud+UqJl/XlHOgLcI3fwtB9pNelPSJAcTxocOJrF6FaxBIQaj1+R05Di6xuAswZpXAW7xhA==
|
||||
|
||||
"@types/semver@^7.3.8":
|
||||
version "7.3.8"
|
||||
|
|
@ -47,6 +47,16 @@ anymatch@~3.1.2:
|
|||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
assert@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32"
|
||||
integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==
|
||||
dependencies:
|
||||
es6-object-assign "^1.1.0"
|
||||
is-nan "^1.2.1"
|
||||
object-is "^1.0.1"
|
||||
util "^0.12.0"
|
||||
|
||||
ast-types@^0.16.1:
|
||||
version "0.16.1"
|
||||
resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz#7a9da1617c9081bc121faafe91711b4c8bb81da2"
|
||||
|
|
@ -66,24 +76,16 @@ atomically@^1.7.0:
|
|||
resolved "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
|
||||
integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
available-typed-arrays@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
|
||||
integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
|
|
@ -91,10 +93,18 @@ braces@~3.0.2:
|
|||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
chokidar@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.2"
|
||||
|
||||
chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
|
|
@ -134,11 +144,6 @@ color@4.2.3:
|
|||
color-convert "^2.0.1"
|
||||
color-string "^1.9.0"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
conf@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz#838e757be963f1a2386dfe048a98f8f69f7b55d6"
|
||||
|
|
@ -155,11 +160,6 @@ conf@^10.2.0:
|
|||
pkg-up "^3.1.0"
|
||||
semver "^7.3.5"
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
|
||||
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
|
||||
|
||||
cross-spawn@^6.0.0:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
|
|
@ -192,6 +192,14 @@ default-shell@1.0.1, default-shell@^1.0.1:
|
|||
resolved "https://registry.npmjs.org/default-shell/-/default-shell-1.0.1.tgz#752304bddc6174f49eb29cb988feea0b8813c8bc"
|
||||
integrity sha1-dSMEvdxhdPSespy5iP7qC4gTyLw=
|
||||
|
||||
define-properties@^1.1.3:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
|
||||
integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
|
||||
dependencies:
|
||||
has-property-descriptors "^1.0.0"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
dot-prop@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
|
||||
|
|
@ -199,16 +207,6 @@ dot-prop@^6.0.1:
|
|||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
electron-devtools-installer@3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmjs.org/electron-devtools-installer/-/electron-devtools-installer-3.2.0.tgz#acc48d24eb7033fe5af284a19667e73b78d406d0"
|
||||
integrity sha512-t3UczsYugm4OAbqvdImMCImIMVdFzJAHgbwHpkl5jmfu1izVgUcP/mnrPqJIpEeCK1uZGpt+yHgWEN+9EwoYhQ==
|
||||
dependencies:
|
||||
rimraf "^3.0.2"
|
||||
semver "^7.2.1"
|
||||
tslib "^2.1.0"
|
||||
unzip-crx-3 "^0.2.0"
|
||||
|
||||
electron-fetch@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.9.1.tgz#e28bfe78d467de3f2dec884b1d72b8b05322f30f"
|
||||
|
|
@ -221,10 +219,10 @@ electron-is-dev@2.0.0:
|
|||
resolved "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-2.0.0.tgz#833487a069b8dad21425c67a19847d9064ab19bd"
|
||||
integrity sha512-3X99K852Yoqu9AcW50qz3ibYBWY79/pBhlMCab8ToEWS48R0T9tyxRiQhwylE7zQdXrMnx2JKqUJyMPmt5FBqA==
|
||||
|
||||
electron-store@8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.npmjs.org/electron-store/-/electron-store-8.2.0.tgz#114e6e453e8bb746ab4ccb542424d8c881ad2ca1"
|
||||
integrity sha512-ukLL5Bevdil6oieAOXz3CMy+OgaItMiVBg701MNlG6W5RaC0AHN7rvlqTCmeb6O7jP0Qa1KKYTE0xV0xbhF4Hw==
|
||||
electron-store@8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.npmjs.org/electron-store/-/electron-store-8.1.0.tgz#46a398f2bd9aa83c4a9daaae28380e2b3b9c7597"
|
||||
integrity sha512-2clHg/juMjOH0GT9cQ6qtmIvK183B39ZXR0bUoPwKwYHJsEF3quqyDzMFUAu+0OP8ijmN2CbPRAelhNbWUbzwA==
|
||||
dependencies:
|
||||
conf "^10.2.0"
|
||||
type-fest "^2.17.0"
|
||||
|
|
@ -248,6 +246,11 @@ env-paths@^2.2.1:
|
|||
resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
|
||||
|
||||
es6-object-assign@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
|
||||
integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==
|
||||
|
||||
esprima@~4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
|
|
@ -300,25 +303,41 @@ find-up@^3.0.0:
|
|||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
fs-extra@11.2.0:
|
||||
version "11.2.0"
|
||||
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b"
|
||||
integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==
|
||||
for-each@^0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
|
||||
dependencies:
|
||||
is-callable "^1.1.3"
|
||||
|
||||
fs-extra@11.1.1:
|
||||
version "11.1.1"
|
||||
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d"
|
||||
integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
|
||||
integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
get-stream@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
|
|
@ -350,23 +369,44 @@ glob-parent@~5.1.2:
|
|||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||
|
||||
has-property-descriptors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
|
||||
integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.1"
|
||||
|
||||
has-symbols@^1.0.2, has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
|
||||
has-tostringtag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
|
||||
integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
|
||||
dependencies:
|
||||
has-symbols "^1.0.2"
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
human-signals@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
|
||||
|
|
@ -379,20 +419,7 @@ iconv-lite@^0.6.2:
|
|||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||
|
||||
immediate@~3.0.5:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@~2.0.3:
|
||||
inherits@^2.0.3, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
|
@ -402,6 +429,14 @@ invert-kv@^3.0.0:
|
|||
resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz#a93c7a3d4386a1dc8325b97da9bb1620c0282523"
|
||||
integrity sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==
|
||||
|
||||
is-arguments@^1.0.4:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
|
||||
integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-arrayish@^0.3.1:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
||||
|
|
@ -414,11 +449,23 @@ is-binary-path@~2.1.0:
|
|||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-callable@^1.1.3:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
|
||||
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-generator-function@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
|
||||
integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
|
||||
dependencies:
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-glob@^4.0.1, is-glob@~4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
|
||||
|
|
@ -426,6 +473,14 @@ is-glob@^4.0.1, is-glob@~4.0.1:
|
|||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-nan@^1.2.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
|
||||
integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
|
|
@ -446,10 +501,16 @@ is-stream@^2.0.0:
|
|||
resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
|
||||
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
|
||||
is-typed-array@^1.1.10, is-typed-array@^1.1.3:
|
||||
version "1.1.10"
|
||||
resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
|
||||
integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.5"
|
||||
call-bind "^1.0.2"
|
||||
for-each "^0.3.3"
|
||||
gopd "^1.0.1"
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
|
@ -480,16 +541,6 @@ jsonfile@^6.0.1:
|
|||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jszip@^3.1.0:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
|
||||
integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
|
||||
dependencies:
|
||||
lie "~3.3.0"
|
||||
pako "~1.0.2"
|
||||
readable-stream "~2.3.6"
|
||||
setimmediate "^1.0.5"
|
||||
|
||||
lcid@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz#9030ec479a058fc36b5e8243ebaac8b6ac582fd0"
|
||||
|
|
@ -497,13 +548,6 @@ lcid@^3.0.0:
|
|||
dependencies:
|
||||
invert-kv "^3.0.0"
|
||||
|
||||
lie@~3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
|
||||
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
|
||||
dependencies:
|
||||
immediate "~3.0.5"
|
||||
|
||||
locate-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||
|
|
@ -562,25 +606,6 @@ mimic-fn@^3.0.0:
|
|||
resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74"
|
||||
integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==
|
||||
|
||||
minimatch@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.6:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
mkdirp@^0.5.1:
|
||||
version "0.5.6"
|
||||
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
|
||||
integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
|
||||
dependencies:
|
||||
minimist "^1.2.6"
|
||||
|
||||
ms@2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
|
|
@ -646,10 +671,28 @@ npm-run-path@^4.0.0:
|
|||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-is@^1.0.1:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
|
||||
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
object-keys@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||
|
||||
once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
|
|
@ -703,11 +746,6 @@ p-try@^2.0.0:
|
|||
resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
pako@~1.0.2:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
||||
|
||||
parse-path@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz#605a2d58d0a749c8594405d8cc3a2bf76d16099b"
|
||||
|
|
@ -727,11 +765,6 @@ path-exists@^3.0.0:
|
|||
resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
|
||||
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-key@^2.0.0, path-key@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||
|
|
@ -754,11 +787,6 @@ pkg-up@^3.1.0:
|
|||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
protocols@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86"
|
||||
|
|
@ -784,33 +812,22 @@ queue@6.0.2:
|
|||
dependencies:
|
||||
inherits "~2.0.3"
|
||||
|
||||
react-dom@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
react-dom@17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
react@17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
readable-stream@~2.3.6:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
|
||||
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
|
|
@ -819,15 +836,15 @@ readdirp@~3.6.0:
|
|||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
recast@0.23.6:
|
||||
version "0.23.6"
|
||||
resolved "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz#198fba74f66143a30acc81929302d214ce4e3bfa"
|
||||
integrity sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==
|
||||
recast@0.23.2:
|
||||
version "0.23.2"
|
||||
resolved "https://registry.npmjs.org/recast/-/recast-0.23.2.tgz#d3dda3e8f0a3366860d7508c00e34a338ac52b41"
|
||||
integrity sha512-Qv6cPfVZyMOtPszK6PgW70pUgm7gPlFitAPf0Q69rlOA0zLw2XdDcNmPbVGYicFGT9O8I7TZ/0ryJD+6COvIPw==
|
||||
dependencies:
|
||||
assert "^2.0.0"
|
||||
ast-types "^0.16.1"
|
||||
esprima "~4.0.0"
|
||||
source-map "~0.6.1"
|
||||
tiny-invariant "^1.3.3"
|
||||
tslib "^2.0.1"
|
||||
|
||||
require-from-string@^2.0.2:
|
||||
|
|
@ -840,34 +857,23 @@ retry@0.13.1:
|
|||
resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||
integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3.0.0":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
scheduler@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
|
||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
semver@7.6.0, semver@^7.2.1, semver@^7.3.5:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
|
||||
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
|
||||
semver@7.5.3, semver@^7.3.5:
|
||||
version "7.5.3"
|
||||
resolved "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e"
|
||||
integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
|
|
@ -876,11 +882,6 @@ semver@^5.5.0, semver@^5.6.0:
|
|||
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
setimmediate@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
|
|
@ -936,13 +937,6 @@ source-map@~0.6.1:
|
|||
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
strip-ansi@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||
|
|
@ -965,11 +959,6 @@ sudo-prompt@^9.2.1:
|
|||
resolved "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd"
|
||||
integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==
|
||||
|
||||
tiny-invariant@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
|
||||
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
|
|
@ -977,10 +966,10 @@ to-regex-range@^5.0.1:
|
|||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tslib@^2.0.1, tslib@^2.1.0:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
|
||||
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
|
||||
tslib@^2.0.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
|
||||
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
|
||||
|
||||
type-fest@^2.17.0:
|
||||
version "2.18.0"
|
||||
|
|
@ -992,15 +981,6 @@ universalify@^2.0.0:
|
|||
resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||
|
||||
unzip-crx-3@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/unzip-crx-3/-/unzip-crx-3-0.2.0.tgz#d5324147b104a8aed9ae8639c95521f6f7cda292"
|
||||
integrity sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==
|
||||
dependencies:
|
||||
jszip "^3.1.0"
|
||||
mkdirp "^0.5.1"
|
||||
yaku "^0.16.6"
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602"
|
||||
|
|
@ -1008,15 +988,33 @@ uri-js@^4.2.2:
|
|||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
util@^0.12.0:
|
||||
version "0.12.5"
|
||||
resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc"
|
||||
integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
is-arguments "^1.0.4"
|
||||
is-generator-function "^1.0.7"
|
||||
is-typed-array "^1.1.3"
|
||||
which-typed-array "^1.1.2"
|
||||
|
||||
uuid@9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||
uuid@9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
|
||||
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
|
||||
|
||||
which-typed-array@^1.1.2:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
|
||||
integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.5"
|
||||
call-bind "^1.0.2"
|
||||
for-each "^0.3.3"
|
||||
gopd "^1.0.1"
|
||||
has-tostringtag "^1.0.0"
|
||||
is-typed-array "^1.1.10"
|
||||
|
||||
which@^1.2.9:
|
||||
version "1.3.1"
|
||||
|
|
@ -1037,11 +1035,6 @@ wrappy@1:
|
|||
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
yaku@^0.16.6:
|
||||
version "0.16.7"
|
||||
resolved "https://registry.npmjs.org/yaku/-/yaku-0.16.7.tgz#1d195c78aa9b5bf8479c895b9504fd4f0847984e"
|
||||
integrity sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
|
|
|
|||
7
bin/snapshot-libs.js
vendored
7
bin/snapshot-libs.js
vendored
|
|
@ -7,6 +7,10 @@ require('normalize-url');
|
|||
require('parse-url');
|
||||
require('php-escape-shell');
|
||||
require('plist');
|
||||
require('react-deep-force-update');
|
||||
require('react-dom');
|
||||
require('react-redux');
|
||||
require('react');
|
||||
require('redux-thunk');
|
||||
require('redux');
|
||||
require('reselect');
|
||||
|
|
@ -18,9 +22,6 @@ if (false) {
|
|||
require('args');
|
||||
require('mousetrap');
|
||||
require('open');
|
||||
require('react-dom');
|
||||
require('react-redux');
|
||||
require('react');
|
||||
require('xterm-addon-fit');
|
||||
require('xterm-addon-image');
|
||||
require('xterm-addon-search');
|
||||
|
|
|
|||
|
|
@ -2,20 +2,18 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import got from 'got';
|
||||
import registryUrlModule from 'registry-url';
|
||||
|
||||
const registryUrl = registryUrlModule();
|
||||
import path from 'path';
|
||||
|
||||
// If the user defines XDG_CONFIG_HOME they definitely want their config there,
|
||||
// otherwise use the home directory in linux/mac and userdata in windows
|
||||
const applicationDirectory = process.env.XDG_CONFIG_HOME
|
||||
? path.join(process.env.XDG_CONFIG_HOME, 'Hyper')
|
||||
: process.platform === 'win32'
|
||||
? path.join(process.env.APPDATA!, 'Hyper')
|
||||
: path.join(os.homedir(), '.config', 'Hyper');
|
||||
? path.join(process.env.APPDATA!, 'Hyper')
|
||||
: path.join(os.homedir(), '.config', 'Hyper');
|
||||
|
||||
const devConfigFileName = path.join(__dirname, `../hyper.json`);
|
||||
|
||||
|
|
|
|||
11
cli/index.ts
11
cli/index.ts
|
|
@ -1,20 +1,17 @@
|
|||
// This is a CLI tool, using console is OK
|
||||
/* eslint no-console: 0 */
|
||||
import {spawn, exec} from 'child_process';
|
||||
import type {SpawnOptions} from 'child_process';
|
||||
import {existsSync} from 'fs';
|
||||
import {spawn, exec} from 'child_process';
|
||||
import {isAbsolute, resolve} from 'path';
|
||||
import {existsSync} from 'fs';
|
||||
import {version} from '../app/package.json';
|
||||
import {promisify} from 'util';
|
||||
|
||||
import args from 'args';
|
||||
import chalk from 'chalk';
|
||||
import open from 'open';
|
||||
import _columnify from 'columnify';
|
||||
import got from 'got';
|
||||
import open from 'open';
|
||||
import ora from 'ora';
|
||||
|
||||
import {version} from '../app/package.json';
|
||||
|
||||
import * as api from './api';
|
||||
|
||||
let commandPromise: Promise<void> | undefined;
|
||||
|
|
|
|||
14
typings/common.d.ts → common.d.ts
vendored
14
typings/common.d.ts → common.d.ts
vendored
|
|
@ -1,10 +1,6 @@
|
|||
import type {ExecFileOptions, ExecOptions} from 'child_process';
|
||||
|
||||
import type {IpcMain, IpcRenderer} from 'electron';
|
||||
|
||||
import type parseUrl from 'parse-url';
|
||||
|
||||
import type {configOptions} from './config';
|
||||
import type {IpcMain, IpcRenderer} from 'electron';
|
||||
import type {ExecFileOptions, ExecOptions} from 'child_process';
|
||||
|
||||
export type Session = {
|
||||
uid: string;
|
||||
|
|
@ -119,12 +115,6 @@ export type IpcCommands = {
|
|||
stdout: string;
|
||||
stderr: string;
|
||||
};
|
||||
getLoadedPluginVersions: () => {name: string; version: string}[];
|
||||
getPaths: () => {plugins: string[]; localPlugins: string[]};
|
||||
getBasePaths: () => {path: string; localPath: string};
|
||||
getDeprecatedConfig: () => Record<string, {css: string[]}>;
|
||||
getDecoratedConfig: (profile: string) => configOptions;
|
||||
getDecoratedKeymaps: () => Record<string, string[]>;
|
||||
};
|
||||
|
||||
export interface IpcMainWithCommands extends IpcMain {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type {configOptions} from '../../typings/config';
|
||||
import {CONFIG_LOAD, CONFIG_RELOAD} from '../../typings/constants/config';
|
||||
import type {HyperActions} from '../../typings/hyper';
|
||||
import {CONFIG_LOAD, CONFIG_RELOAD} from '../constants/config';
|
||||
import type {HyperActions} from '../hyper';
|
||||
import type {configOptions} from '../config';
|
||||
|
||||
export function loadConfig(config: configOptions): HyperActions {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import {CLOSE_TAB, CHANGE_TAB} from '../../typings/constants/tabs';
|
||||
import {CLOSE_TAB, CHANGE_TAB} from '../constants/tabs';
|
||||
import {
|
||||
UI_WINDOW_MAXIMIZE,
|
||||
UI_WINDOW_UNMAXIMIZE,
|
||||
UI_OPEN_HAMBURGER_MENU,
|
||||
UI_WINDOW_MINIMIZE,
|
||||
UI_WINDOW_CLOSE
|
||||
} from '../../typings/constants/ui';
|
||||
import type {HyperDispatch} from '../../typings/hyper';
|
||||
} from '../constants/ui';
|
||||
import rpc from '../rpc';
|
||||
|
||||
import {userExitTermGroup, setActiveGroup} from './term-groups';
|
||||
import type {HyperDispatch} from '../hyper';
|
||||
|
||||
export function closeTab(uid: string) {
|
||||
return (dispatch: HyperDispatch) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {INIT} from '../../typings/constants';
|
||||
import type {HyperDispatch} from '../../typings/hyper';
|
||||
import rpc from '../rpc';
|
||||
import {INIT} from '../constants';
|
||||
import type {HyperDispatch} from '../hyper';
|
||||
|
||||
export default function init() {
|
||||
return (dispatch: HyperDispatch) => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import {NOTIFICATION_MESSAGE, NOTIFICATION_DISMISS} from '../../typings/constants/notifications';
|
||||
import type {HyperActions} from '../../typings/hyper';
|
||||
import {NOTIFICATION_MESSAGE, NOTIFICATION_DISMISS} from '../constants/notifications';
|
||||
import type {HyperActions} from '../hyper';
|
||||
|
||||
export function dismissNotification(id: string): HyperActions {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import type {Session} from '../../typings/common';
|
||||
import rpc from '../rpc';
|
||||
import {keys} from '../utils/object';
|
||||
import findBySession from '../utils/term-groups';
|
||||
import {
|
||||
SESSION_ADD,
|
||||
SESSION_RESIZE,
|
||||
|
|
@ -12,11 +14,9 @@ import {
|
|||
SESSION_USER_DATA,
|
||||
SESSION_SET_XTERM_TITLE,
|
||||
SESSION_SEARCH
|
||||
} from '../../typings/constants/sessions';
|
||||
import type {HyperState, HyperDispatch, HyperActions} from '../../typings/hyper';
|
||||
import rpc from '../rpc';
|
||||
import {keys} from '../utils/object';
|
||||
import findBySession from '../utils/term-groups';
|
||||
} from '../constants/sessions';
|
||||
import type {HyperState, HyperDispatch, HyperActions} from '../hyper';
|
||||
import type {Session} from '../../common';
|
||||
|
||||
export function addSession({uid, shell, pid, cols = null, rows = null, splitDirection, activeUid, profile}: Session) {
|
||||
return (dispatch: HyperDispatch, getState: () => HyperState) => {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
import {SESSION_REQUEST} from '../../typings/constants/sessions';
|
||||
import rpc from '../rpc';
|
||||
import {
|
||||
DIRECTION,
|
||||
TERM_GROUP_RESIZE,
|
||||
TERM_GROUP_REQUEST,
|
||||
TERM_GROUP_EXIT,
|
||||
TERM_GROUP_EXIT_ACTIVE
|
||||
} from '../../typings/constants/term-groups';
|
||||
import type {ITermState, ITermGroup, HyperState, HyperDispatch, HyperActions} from '../../typings/hyper';
|
||||
import rpc from '../rpc';
|
||||
import {getRootGroups} from '../selectors';
|
||||
} from '../constants/term-groups';
|
||||
import {SESSION_REQUEST} from '../constants/sessions';
|
||||
import findBySession from '../utils/term-groups';
|
||||
|
||||
import {getRootGroups} from '../selectors';
|
||||
import {setActiveSession, ptyExitSession, userExitSession} from './sessions';
|
||||
import type {ITermState, ITermGroup, HyperState, HyperDispatch, HyperActions} from '../hyper';
|
||||
|
||||
function requestSplit(direction: 'VERTICAL' | 'HORIZONTAL') {
|
||||
return (_activeUid: string | undefined, _profile: string | undefined) =>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import {stat} from 'fs';
|
||||
import type {Stats} from 'fs';
|
||||
|
||||
import type parseUrl from 'parse-url';
|
||||
import {php_escapeshellcmd as escapeShellCmd} from 'php-escape-shell';
|
||||
|
||||
import {isExecutable} from '../utils/file';
|
||||
import {getRootGroups} from '../selectors';
|
||||
import findBySession from '../utils/term-groups';
|
||||
import notify from '../utils/notify';
|
||||
import rpc from '../rpc';
|
||||
import {requestSession, sendSessionData, setActiveSession} from './sessions';
|
||||
import {
|
||||
UI_FONT_SIZE_SET,
|
||||
UI_FONT_SIZE_INCR,
|
||||
|
|
@ -23,16 +24,13 @@ import {
|
|||
UI_OPEN_SSH_URL,
|
||||
UI_CONTEXTMENU_OPEN,
|
||||
UI_COMMAND_EXEC
|
||||
} from '../../typings/constants/ui';
|
||||
import type {HyperState, HyperDispatch, HyperActions, ITermGroups} from '../../typings/hyper';
|
||||
import rpc from '../rpc';
|
||||
import {getRootGroups} from '../selectors';
|
||||
import {isExecutable} from '../utils/file';
|
||||
import notify from '../utils/notify';
|
||||
import findBySession from '../utils/term-groups';
|
||||
} from '../constants/ui';
|
||||
|
||||
import {requestSession, sendSessionData, setActiveSession} from './sessions';
|
||||
import {setActiveGroup} from './term-groups';
|
||||
import type parseUrl from 'parse-url';
|
||||
import type {HyperState, HyperDispatch, HyperActions, ITermGroups} from '../hyper';
|
||||
import type {Stats} from 'fs';
|
||||
import {stat} from 'fs';
|
||||
|
||||
export function openContextMenu(uid: string, selection: string) {
|
||||
return (dispatch: HyperDispatch, getState: () => HyperState) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {UPDATE_INSTALL, UPDATE_AVAILABLE} from '../../typings/constants/updater';
|
||||
import type {HyperActions} from '../../typings/hyper';
|
||||
import {UPDATE_INSTALL, UPDATE_AVAILABLE} from '../constants/updater';
|
||||
import rpc from '../rpc';
|
||||
import type {HyperActions} from '../hyper';
|
||||
|
||||
export function installUpdate(): HyperActions {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import type {HyperDispatch} from '../typings/hyper';
|
||||
|
||||
import {require as remoteRequire} from '@electron/remote';
|
||||
import type {HyperDispatch} from './hyper';
|
||||
import {closeSearch} from './actions/sessions';
|
||||
import {ipcRenderer} from './utils/ipc';
|
||||
// TODO: Should be updates to new async API https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31
|
||||
|
||||
const {getDecoratedKeymaps} = remoteRequire('./plugins') as typeof import('../app/plugins');
|
||||
|
||||
let commands: Record<string, (event: any, dispatch: HyperDispatch) => void> = {
|
||||
'editor:search-close': (e, dispatch) => {
|
||||
|
|
@ -10,8 +12,8 @@ let commands: Record<string, (event: any, dispatch: HyperDispatch) => void> = {
|
|||
}
|
||||
};
|
||||
|
||||
export const getRegisteredKeys = async () => {
|
||||
const keymaps = await ipcRenderer.invoke('getDecoratedKeymaps');
|
||||
export const getRegisteredKeys = () => {
|
||||
const keymaps = getDecoratedKeymaps();
|
||||
|
||||
return Object.keys(keymaps).reduce((result: Record<string, string>, actionName) => {
|
||||
const commandKeys = keymaps[actionName];
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
import React, {forwardRef, useState} from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import type {HeaderProps} from '../../typings/hyper';
|
||||
import {decorate, getTabsProps} from '../utils/plugins';
|
||||
|
||||
import Tabs_ from './tabs';
|
||||
import type {HeaderProps} from '../hyper';
|
||||
|
||||
const Tabs = decorate(Tabs_, 'Tabs');
|
||||
|
||||
const Header = forwardRef<HTMLElement, HeaderProps>((props, ref) => {
|
||||
const [headerMouseDownWindowX, setHeaderMouseDownWindowX] = useState<number>(0);
|
||||
const [headerMouseDownWindowY, setHeaderMouseDownWindowY] = useState<number>(0);
|
||||
export default class Header extends React.PureComponent<HeaderProps> {
|
||||
headerMouseDownWindowX!: number;
|
||||
headerMouseDownWindowY!: number;
|
||||
|
||||
const onChangeIntent = (active: string) => {
|
||||
onChangeIntent = (active: string) => {
|
||||
// we ignore clicks if they're a byproduct of a drag
|
||||
// motion to move the window
|
||||
if (window.screenX !== headerMouseDownWindowX || window.screenY !== headerMouseDownWindowY) {
|
||||
if (window.screenX !== this.headerMouseDownWindowX || window.screenY !== this.headerMouseDownWindowY) {
|
||||
return;
|
||||
}
|
||||
|
||||
props.onChangeTab(active);
|
||||
this.props.onChangeTab(active);
|
||||
};
|
||||
|
||||
const handleHeaderMouseDown = () => {
|
||||
handleHeaderMouseDown = () => {
|
||||
// the hack of all hacks, this prevents the term
|
||||
// iframe from losing focus, for example, when
|
||||
// the user drags the nav around
|
||||
|
|
@ -30,43 +30,43 @@ const Header = forwardRef<HTMLElement, HeaderProps>((props, ref) => {
|
|||
|
||||
// persist start positions of a potential drag motion
|
||||
// to differentiate dragging from clicking
|
||||
setHeaderMouseDownWindowX(window.screenX);
|
||||
setHeaderMouseDownWindowY(window.screenY);
|
||||
this.headerMouseDownWindowX = window.screenX;
|
||||
this.headerMouseDownWindowY = window.screenY;
|
||||
};
|
||||
|
||||
const handleHamburgerMenuClick = (event: React.MouseEvent) => {
|
||||
handleHamburgerMenuClick = (event: React.MouseEvent) => {
|
||||
let {right: x, bottom: y} = event.currentTarget.getBoundingClientRect();
|
||||
x -= 15; // to compensate padding
|
||||
y -= 12; // ^ same
|
||||
props.openHamburgerMenu({x, y});
|
||||
this.props.openHamburgerMenu({x, y});
|
||||
};
|
||||
|
||||
const handleMaximizeClick = () => {
|
||||
if (props.maximized) {
|
||||
props.unmaximize();
|
||||
handleMaximizeClick = () => {
|
||||
if (this.props.maximized) {
|
||||
this.props.unmaximize();
|
||||
} else {
|
||||
props.maximize();
|
||||
this.props.maximize();
|
||||
}
|
||||
};
|
||||
|
||||
const handleMinimizeClick = () => {
|
||||
props.minimize();
|
||||
handleMinimizeClick = () => {
|
||||
this.props.minimize();
|
||||
};
|
||||
|
||||
const handleCloseClick = () => {
|
||||
props.close();
|
||||
handleCloseClick = () => {
|
||||
this.props.close();
|
||||
};
|
||||
|
||||
const getWindowHeaderConfig = () => {
|
||||
const {showHamburgerMenu, showWindowControls} = props;
|
||||
getWindowHeaderConfig() {
|
||||
const {showHamburgerMenu, showWindowControls} = this.props;
|
||||
|
||||
const defaults = {
|
||||
hambMenu: !props.isMac, // show by default on windows and linux
|
||||
winCtrls: !props.isMac // show by default on Windows and Linux
|
||||
hambMenu: !this.props.isMac, // show by default on windows and linux
|
||||
winCtrls: !this.props.isMac // show by default on Windows and Linux
|
||||
};
|
||||
|
||||
// don't allow the user to change defaults on macOS
|
||||
if (props.isMac) {
|
||||
if (this.props.isMac) {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
|
|
@ -74,187 +74,186 @@ const Header = forwardRef<HTMLElement, HeaderProps>((props, ref) => {
|
|||
hambMenu: showHamburgerMenu === '' ? defaults.hambMenu : showHamburgerMenu,
|
||||
winCtrls: showWindowControls === '' ? defaults.winCtrls : showWindowControls
|
||||
};
|
||||
};
|
||||
|
||||
const {isMac} = props;
|
||||
const {borderColor} = props;
|
||||
let title = 'Hyper';
|
||||
if (props.tabs.length === 1 && props.tabs[0].title) {
|
||||
// if there's only one tab we use its title as the window title
|
||||
title = props.tabs[0].title;
|
||||
}
|
||||
const {hambMenu, winCtrls} = getWindowHeaderConfig();
|
||||
const left = winCtrls === 'left';
|
||||
const maxButtonHref = props.maximized
|
||||
? './renderer/assets/icons.svg#restore-window'
|
||||
: './renderer/assets/icons.svg#maximize-window';
|
||||
|
||||
return (
|
||||
<header
|
||||
className={`header_header ${isMac && 'header_headerRounded'}`}
|
||||
onMouseDown={handleHeaderMouseDown}
|
||||
onMouseUp={() => window.focusActiveTerm()}
|
||||
onDoubleClick={handleMaximizeClick}
|
||||
ref={ref}
|
||||
>
|
||||
{!isMac && (
|
||||
<div
|
||||
className={`header_windowHeader ${props.tabs.length > 1 ? 'header_windowHeaderWithBorder' : ''}`}
|
||||
style={{borderColor}}
|
||||
>
|
||||
{hambMenu && (
|
||||
<svg
|
||||
className={`header_shape ${left ? 'header_hamburgerMenuRight' : 'header_hamburgerMenuLeft'}`}
|
||||
onClick={handleHamburgerMenuClick}
|
||||
>
|
||||
<use xlinkHref="./renderer/assets/icons.svg#hamburger-menu" />
|
||||
</svg>
|
||||
)}
|
||||
<span className="header_appTitle">{title}</span>
|
||||
{winCtrls && (
|
||||
<div className={`header_windowControls ${left ? 'header_windowControlsLeft' : ''}`}>
|
||||
<div className={`${left ? 'header_minimizeWindowLeft' : ''}`} onClick={handleMinimizeClick}>
|
||||
<svg className="header_shape">
|
||||
<use xlinkHref="./renderer/assets/icons.svg#minimize-window" />
|
||||
</svg>
|
||||
render() {
|
||||
const {isMac} = this.props;
|
||||
const props = getTabsProps(this.props, {
|
||||
tabs: this.props.tabs,
|
||||
borderColor: this.props.borderColor,
|
||||
backgroundColor: this.props.backgroundColor,
|
||||
onClose: this.props.onCloseTab,
|
||||
onChange: this.onChangeIntent,
|
||||
fullScreen: this.props.fullScreen,
|
||||
defaultProfile: this.props.defaultProfile,
|
||||
profiles: this.props.profiles.asMutable({deep: true}),
|
||||
openNewTab: this.props.openNewTab
|
||||
});
|
||||
const {borderColor} = props;
|
||||
let title = 'Hyper';
|
||||
if (props.tabs.length === 1 && props.tabs[0].title) {
|
||||
// if there's only one tab we use its title as the window title
|
||||
title = props.tabs[0].title;
|
||||
}
|
||||
const {hambMenu, winCtrls} = this.getWindowHeaderConfig();
|
||||
const left = winCtrls === 'left';
|
||||
const maxButtonHref = this.props.maximized
|
||||
? './renderer/assets/icons.svg#restore-window'
|
||||
: './renderer/assets/icons.svg#maximize-window';
|
||||
|
||||
return (
|
||||
<header
|
||||
className={`header_header ${isMac && 'header_headerRounded'}`}
|
||||
onMouseDown={this.handleHeaderMouseDown}
|
||||
onMouseUp={() => window.focusActiveTerm()}
|
||||
onDoubleClick={this.handleMaximizeClick}
|
||||
>
|
||||
{!isMac && (
|
||||
<div
|
||||
className={`header_windowHeader ${props.tabs.length > 1 ? 'header_windowHeaderWithBorder' : ''}`}
|
||||
style={{borderColor}}
|
||||
>
|
||||
{hambMenu && (
|
||||
<svg
|
||||
className={`header_shape ${left ? 'header_hamburgerMenuRight' : 'header_hamburgerMenuLeft'}`}
|
||||
onClick={this.handleHamburgerMenuClick}
|
||||
>
|
||||
<use xlinkHref="./renderer/assets/icons.svg#hamburger-menu" />
|
||||
</svg>
|
||||
)}
|
||||
<span className="header_appTitle">{title}</span>
|
||||
{winCtrls && (
|
||||
<div className={`header_windowControls ${left ? 'header_windowControlsLeft' : ''}`}>
|
||||
<div className={`${left ? 'header_minimizeWindowLeft' : ''}`} onClick={this.handleMinimizeClick}>
|
||||
<svg className="header_shape">
|
||||
<use xlinkHref="./renderer/assets/icons.svg#minimize-window" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className={`${left ? 'header_maximizeWindowLeft' : ''}`} onClick={this.handleMaximizeClick}>
|
||||
<svg className="header_shape">
|
||||
<use xlinkHref={maxButtonHref} />
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
className={`header_closeWindow ${left ? 'header_closeWindowLeft' : ''}`}
|
||||
onClick={this.handleCloseClick}
|
||||
>
|
||||
<svg className="header_shape">
|
||||
<use xlinkHref="./renderer/assets/icons.svg#close-window" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${left ? 'header_maximizeWindowLeft' : ''}`} onClick={handleMaximizeClick}>
|
||||
<svg className="header_shape">
|
||||
<use xlinkHref={maxButtonHref} />
|
||||
</svg>
|
||||
</div>
|
||||
<div className={`header_closeWindow ${left ? 'header_closeWindowLeft' : ''}`} onClick={handleCloseClick}>
|
||||
<svg className="header_shape">
|
||||
<use xlinkHref="./renderer/assets/icons.svg#close-window" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{props.customChildrenBefore}
|
||||
<Tabs
|
||||
{...getTabsProps(props, {
|
||||
tabs: props.tabs,
|
||||
borderColor: props.borderColor,
|
||||
backgroundColor: props.backgroundColor,
|
||||
onClose: props.onCloseTab,
|
||||
onChange: onChangeIntent,
|
||||
fullScreen: props.fullScreen,
|
||||
defaultProfile: props.defaultProfile,
|
||||
profiles: props.profiles.asMutable({deep: true}),
|
||||
openNewTab: props.openNewTab
|
||||
})}
|
||||
/>
|
||||
{props.customChildren}
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{this.props.customChildrenBefore}
|
||||
<Tabs {...props} />
|
||||
{this.props.customChildren}
|
||||
|
||||
<style jsx>{`
|
||||
.header_header {
|
||||
position: fixed;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
z-index: 100;
|
||||
}
|
||||
<style jsx>{`
|
||||
.header_header {
|
||||
position: fixed;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.header_headerRounded {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.header_headerRounded {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.header_windowHeader {
|
||||
height: 34px;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.header_windowHeader {
|
||||
height: 34px;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header_windowHeaderWithBorder {
|
||||
border-color: #ccc;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
.header_windowHeaderWithBorder {
|
||||
border-color: #ccc;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.header_appTitle {
|
||||
font-size: 12px;
|
||||
}
|
||||
.header_appTitle {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.header_shape,
|
||||
.header_shape > svg {
|
||||
width: 40px;
|
||||
height: 34px;
|
||||
padding: 12px 15px 12px 15px;
|
||||
-webkit-app-region: no-drag;
|
||||
color: #fff;
|
||||
opacity: 0.5;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
.header_shape,
|
||||
.header_shape > svg {
|
||||
width: 40px;
|
||||
height: 34px;
|
||||
padding: 12px 15px 12px 15px;
|
||||
-webkit-app-region: no-drag;
|
||||
color: #fff;
|
||||
opacity: 0.5;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.header_shape:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.header_shape:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.header_shape:active {
|
||||
opacity: 0.3;
|
||||
}
|
||||
.header_shape:active {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.header_hamburgerMenuLeft {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.header_hamburgerMenuLeft {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.header_hamburgerMenuRight {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.header_hamburgerMenuRight {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.header_windowControls {
|
||||
display: flex;
|
||||
width: 120px;
|
||||
height: 34px;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.header_windowControls {
|
||||
display: flex;
|
||||
width: 120px;
|
||||
height: 34px;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.header_windowControlsLeft {
|
||||
left: 0px;
|
||||
}
|
||||
.header_windowControlsLeft {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.header_closeWindowLeft {
|
||||
order: 1;
|
||||
}
|
||||
.header_closeWindowLeft {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.header_minimizeWindowLeft {
|
||||
order: 2;
|
||||
}
|
||||
.header_minimizeWindowLeft {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.header_maximizeWindowLeft {
|
||||
order: 3;
|
||||
}
|
||||
.header_maximizeWindowLeft {
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.header_closeWindow:hover {
|
||||
color: #fe354e;
|
||||
}
|
||||
.header_closeWindow:hover {
|
||||
color: #fe354e;
|
||||
}
|
||||
|
||||
.header_closeWindow:active {
|
||||
color: #fe354e;
|
||||
}
|
||||
`}</style>
|
||||
</header>
|
||||
);
|
||||
});
|
||||
|
||||
Header.displayName = 'Header';
|
||||
|
||||
export default Header;
|
||||
.header_closeWindow:active {
|
||||
color: #fe354e;
|
||||
}
|
||||
`}</style>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import React, {useRef, useState} from 'react';
|
||||
|
||||
import {VscChevronDown} from '@react-icons/all-files/vsc/VscChevronDown';
|
||||
import type {configOptions} from '../config';
|
||||
import useClickAway from 'react-use/lib/useClickAway';
|
||||
|
||||
import type {configOptions} from '../../typings/config';
|
||||
|
||||
interface Props {
|
||||
defaultProfile: string;
|
||||
profiles: configOptions['profiles'];
|
||||
|
|
|
|||
|
|
@ -1,110 +1,115 @@
|
|||
import React, {forwardRef, useEffect, useRef, useState} from 'react';
|
||||
import React from 'react';
|
||||
import type {NotificationProps, NotificationState} from '../hyper';
|
||||
|
||||
import type {NotificationProps} from '../../typings/hyper';
|
||||
export default class Notification extends React.PureComponent<NotificationProps, NotificationState> {
|
||||
dismissTimer!: NodeJS.Timeout;
|
||||
constructor(props: NotificationProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dismissing: false
|
||||
};
|
||||
}
|
||||
|
||||
const Notification = forwardRef<HTMLDivElement, React.PropsWithChildren<NotificationProps>>((props, ref) => {
|
||||
const dismissTimer = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const [dismissing, setDismissing] = useState(false);
|
||||
componentDidMount() {
|
||||
if (this.props.dismissAfter) {
|
||||
this.setDismissTimer();
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setDismissTimer();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
componentDidUpdate(prevProps: NotificationProps, prevState: NotificationState) {
|
||||
// if we have a timer going and the notification text
|
||||
// changed we reset the timer
|
||||
resetDismissTimer();
|
||||
setDismissing(false);
|
||||
}, [props.text]);
|
||||
if (this.props.text !== prevProps.text) {
|
||||
if (prevProps.dismissAfter) {
|
||||
this.resetDismissTimer();
|
||||
}
|
||||
if (prevState.dismissing) {
|
||||
this.setState({dismissing: false});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleDismiss = () => {
|
||||
setDismissing(true);
|
||||
handleDismiss = () => {
|
||||
this.setState({dismissing: true});
|
||||
};
|
||||
|
||||
const onElement = (el: HTMLDivElement | null) => {
|
||||
onElement = (el: HTMLDivElement | null) => {
|
||||
if (el) {
|
||||
el.addEventListener('webkitTransitionEnd', () => {
|
||||
if (dismissing) {
|
||||
props.onDismiss();
|
||||
if (this.state.dismissing) {
|
||||
this.props.onDismiss();
|
||||
}
|
||||
});
|
||||
const {backgroundColor} = props;
|
||||
const {backgroundColor} = this.props;
|
||||
if (backgroundColor) {
|
||||
el.style.setProperty('background-color', backgroundColor, 'important');
|
||||
}
|
||||
|
||||
if (ref) {
|
||||
if (typeof ref === 'function') ref(el);
|
||||
else ref.current = el;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setDismissTimer = () => {
|
||||
if (typeof props.dismissAfter === 'number') {
|
||||
dismissTimer.current = setTimeout(() => {
|
||||
handleDismiss();
|
||||
}, props.dismissAfter);
|
||||
}
|
||||
};
|
||||
setDismissTimer() {
|
||||
this.dismissTimer = setTimeout(() => {
|
||||
this.handleDismiss();
|
||||
}, this.props.dismissAfter);
|
||||
}
|
||||
|
||||
const resetDismissTimer = () => {
|
||||
clearTimeout(dismissTimer.current);
|
||||
setDismissTimer();
|
||||
};
|
||||
resetDismissTimer() {
|
||||
clearTimeout(this.dismissTimer);
|
||||
this.setDismissTimer();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearTimeout(dismissTimer.current);
|
||||
};
|
||||
}, []);
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.dismissTimer);
|
||||
}
|
||||
|
||||
const {backgroundColor, color} = props;
|
||||
const opacity = dismissing ? 0 : 1;
|
||||
return (
|
||||
<div ref={onElement} style={{opacity, backgroundColor, color}} className="notification_indicator">
|
||||
{props.customChildrenBefore}
|
||||
{props.children || props.text}
|
||||
{props.userDismissable ? (
|
||||
<a className="notification_dismissLink" onClick={handleDismiss} style={{color: props.userDismissColor}}>
|
||||
[x]
|
||||
</a>
|
||||
) : null}
|
||||
{props.customChildren}
|
||||
render() {
|
||||
const {backgroundColor, color} = this.props;
|
||||
const opacity = this.state.dismissing ? 0 : 1;
|
||||
return (
|
||||
<div ref={this.onElement} style={{opacity, backgroundColor, color}} className="notification_indicator">
|
||||
{this.props.customChildrenBefore}
|
||||
{this.props.children || this.props.text}
|
||||
{this.props.userDismissable ? (
|
||||
<a
|
||||
className="notification_dismissLink"
|
||||
onClick={this.handleDismiss}
|
||||
style={{color: this.props.userDismissColor}}
|
||||
>
|
||||
[x]
|
||||
</a>
|
||||
) : null}
|
||||
{this.props.customChildren}
|
||||
|
||||
<style jsx>{`
|
||||
.notification_indicator {
|
||||
display: inline-block;
|
||||
cursor: default;
|
||||
-webkit-user-select: none;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
padding: 8px 14px 9px;
|
||||
margin-left: 10px;
|
||||
transition: 150ms opacity ease;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
|
||||
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
<style jsx>{`
|
||||
.notification_indicator {
|
||||
display: inline-block;
|
||||
cursor: default;
|
||||
-webkit-user-select: none;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
padding: 8px 14px 9px;
|
||||
margin-left: 10px;
|
||||
transition: 150ms opacity ease;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
|
||||
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
.notification_dismissLink {
|
||||
position: relative;
|
||||
left: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
color: currentColor;
|
||||
transition: font-weight 0.1s ease-in-out;
|
||||
}
|
||||
.notification_dismissLink {
|
||||
position: relative;
|
||||
left: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
color: currentColor;
|
||||
transition: font-weight 0.1s ease-in-out;
|
||||
}
|
||||
|
||||
.notification_dismissLink:hover,
|
||||
.notification_dismissLink:focus {
|
||||
font-weight: 900;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Notification.displayName = 'Notification';
|
||||
|
||||
export default Notification;
|
||||
.notification_dismissLink:hover,
|
||||
.notification_dismissLink:focus {
|
||||
font-weight: 900;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,132 +1,132 @@
|
|||
import React, {forwardRef} from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import type {NotificationsProps} from '../../typings/hyper';
|
||||
import {decorate} from '../utils/plugins';
|
||||
|
||||
import Notification_ from './notification';
|
||||
import type {NotificationsProps} from '../hyper';
|
||||
|
||||
const Notification = decorate(Notification_, 'Notification');
|
||||
|
||||
const Notifications = forwardRef<HTMLDivElement, NotificationsProps>((props, ref) => {
|
||||
return (
|
||||
<div className="notifications_view" ref={ref}>
|
||||
{props.customChildrenBefore}
|
||||
{props.fontShowing && (
|
||||
<Notification
|
||||
key="font"
|
||||
backgroundColor="rgba(255, 255, 255, .2)"
|
||||
text={`${props.fontSize}px`}
|
||||
userDismissable={false}
|
||||
onDismiss={props.onDismissFont}
|
||||
dismissAfter={1000}
|
||||
/>
|
||||
)}
|
||||
export default class Notifications extends React.PureComponent<NotificationsProps> {
|
||||
render() {
|
||||
return (
|
||||
<div className="notifications_view">
|
||||
{this.props.customChildrenBefore}
|
||||
{this.props.fontShowing && (
|
||||
<Notification
|
||||
key="font"
|
||||
backgroundColor="rgba(255, 255, 255, .2)"
|
||||
text={`${this.props.fontSize}px`}
|
||||
userDismissable={false}
|
||||
onDismiss={this.props.onDismissFont}
|
||||
dismissAfter={1000}
|
||||
/>
|
||||
)}
|
||||
|
||||
{props.resizeShowing && (
|
||||
<Notification
|
||||
key="resize"
|
||||
backgroundColor="rgba(255, 255, 255, .2)"
|
||||
text={`${props.cols}x${props.rows}`}
|
||||
userDismissable={false}
|
||||
onDismiss={props.onDismissResize}
|
||||
dismissAfter={1000}
|
||||
/>
|
||||
)}
|
||||
{this.props.resizeShowing && (
|
||||
<Notification
|
||||
key="resize"
|
||||
backgroundColor="rgba(255, 255, 255, .2)"
|
||||
text={`${this.props.cols}x${this.props.rows}`}
|
||||
userDismissable={false}
|
||||
onDismiss={this.props.onDismissResize}
|
||||
dismissAfter={1000}
|
||||
/>
|
||||
)}
|
||||
|
||||
{props.messageShowing && (
|
||||
<Notification
|
||||
key="message"
|
||||
backgroundColor="#FE354E"
|
||||
color="#fff"
|
||||
text={props.messageText}
|
||||
onDismiss={props.onDismissMessage}
|
||||
userDismissable={props.messageDismissable}
|
||||
>
|
||||
{props.messageURL ? (
|
||||
<>
|
||||
{props.messageText} (
|
||||
<a
|
||||
style={{color: '#fff'}}
|
||||
onClick={(ev) => {
|
||||
void window.require('electron').shell.openExternal(ev.currentTarget.href);
|
||||
ev.preventDefault();
|
||||
}}
|
||||
href={props.messageURL}
|
||||
>
|
||||
more
|
||||
</a>
|
||||
)
|
||||
</>
|
||||
) : null}
|
||||
</Notification>
|
||||
)}
|
||||
|
||||
{props.updateShowing && (
|
||||
<Notification
|
||||
key="update"
|
||||
backgroundColor="#18E179"
|
||||
color="#000"
|
||||
text={`Version ${props.updateVersion} ready`}
|
||||
onDismiss={props.onDismissUpdate}
|
||||
userDismissable
|
||||
>
|
||||
Version <b>{props.updateVersion}</b> ready.
|
||||
{props.updateNote && ` ${props.updateNote.trim().replace(/\.$/, '')}`} (
|
||||
<a
|
||||
style={{color: '#000'}}
|
||||
onClick={(ev) => {
|
||||
void window.require('electron').shell.openExternal(ev.currentTarget.href);
|
||||
ev.preventDefault();
|
||||
}}
|
||||
href={`https://github.com/vercel/hyper/releases/tag/${props.updateVersion}`}
|
||||
{this.props.messageShowing && (
|
||||
<Notification
|
||||
key="message"
|
||||
backgroundColor="#FE354E"
|
||||
color="#fff"
|
||||
text={this.props.messageText}
|
||||
onDismiss={this.props.onDismissMessage}
|
||||
userDismissable={this.props.messageDismissable}
|
||||
>
|
||||
notes
|
||||
</a>
|
||||
).{' '}
|
||||
{props.updateCanInstall ? (
|
||||
{this.props.messageURL
|
||||
? [
|
||||
this.props.messageText,
|
||||
' (',
|
||||
<a
|
||||
key="link"
|
||||
style={{color: '#fff'}}
|
||||
onClick={(ev) => {
|
||||
void window.require('electron').shell.openExternal(ev.currentTarget.href);
|
||||
ev.preventDefault();
|
||||
}}
|
||||
href={this.props.messageURL}
|
||||
>
|
||||
more
|
||||
</a>,
|
||||
') '
|
||||
]
|
||||
: null}
|
||||
</Notification>
|
||||
)}
|
||||
|
||||
{this.props.updateShowing && (
|
||||
<Notification
|
||||
key="update"
|
||||
backgroundColor="#18E179"
|
||||
color="#000"
|
||||
text={`Version ${this.props.updateVersion} ready`}
|
||||
onDismiss={this.props.onDismissUpdate}
|
||||
userDismissable
|
||||
>
|
||||
Version <b>{this.props.updateVersion}</b> ready.
|
||||
{this.props.updateNote && ` ${this.props.updateNote.trim().replace(/\.$/, '')}`} (
|
||||
<a
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
textDecoration: 'underline',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
onClick={props.onUpdateInstall}
|
||||
>
|
||||
Restart
|
||||
</a>
|
||||
) : (
|
||||
<a
|
||||
style={{
|
||||
color: '#000',
|
||||
cursor: 'pointer',
|
||||
textDecoration: 'underline',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
style={{color: '#000'}}
|
||||
onClick={(ev) => {
|
||||
void window.require('electron').shell.openExternal(ev.currentTarget.href);
|
||||
ev.preventDefault();
|
||||
}}
|
||||
href={props.updateReleaseUrl!}
|
||||
href={`https://github.com/vercel/hyper/releases/tag/${this.props.updateVersion}`}
|
||||
>
|
||||
Download
|
||||
notes
|
||||
</a>
|
||||
)}
|
||||
.{' '}
|
||||
</Notification>
|
||||
)}
|
||||
{props.customChildren}
|
||||
).{' '}
|
||||
{this.props.updateCanInstall ? (
|
||||
<a
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
textDecoration: 'underline',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
onClick={this.props.onUpdateInstall}
|
||||
>
|
||||
Restart
|
||||
</a>
|
||||
) : (
|
||||
<a
|
||||
style={{
|
||||
color: '#000',
|
||||
cursor: 'pointer',
|
||||
textDecoration: 'underline',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
onClick={(ev) => {
|
||||
void window.require('electron').shell.openExternal(ev.currentTarget.href);
|
||||
ev.preventDefault();
|
||||
}}
|
||||
href={this.props.updateReleaseUrl!}
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
)}
|
||||
.{' '}
|
||||
</Notification>
|
||||
)}
|
||||
{this.props.customChildren}
|
||||
|
||||
<style jsx>{`
|
||||
.notifications_view {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Notifications.displayName = 'Notifications';
|
||||
|
||||
export default Notifications;
|
||||
<style jsx>{`
|
||||
.notifications_view {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
import React, {useCallback, useRef, useEffect, forwardRef} from 'react';
|
||||
|
||||
import {VscArrowDown} from '@react-icons/all-files/vsc/VscArrowDown';
|
||||
import React, {useCallback} from 'react';
|
||||
import type {SearchBoxProps} from '../hyper';
|
||||
import {VscArrowUp} from '@react-icons/all-files/vsc/VscArrowUp';
|
||||
import {VscCaseSensitive} from '@react-icons/all-files/vsc/VscCaseSensitive';
|
||||
import {VscArrowDown} from '@react-icons/all-files/vsc/VscArrowDown';
|
||||
import {VscClose} from '@react-icons/all-files/vsc/VscClose';
|
||||
import {VscCaseSensitive} from '@react-icons/all-files/vsc/VscCaseSensitive';
|
||||
import {VscRegex} from '@react-icons/all-files/vsc/VscRegex';
|
||||
import {VscWholeWord} from '@react-icons/all-files/vsc/VscWholeWord';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import type {SearchBoxProps} from '../../typings/hyper';
|
||||
|
||||
type SearchButtonColors = {
|
||||
foregroundColor: string;
|
||||
selectionColor: string;
|
||||
|
|
@ -84,154 +82,179 @@ const SearchButton = ({
|
|||
);
|
||||
};
|
||||
|
||||
const SearchBox = forwardRef<HTMLDivElement, SearchBoxProps>((props, ref) => {
|
||||
const {
|
||||
caseSensitive,
|
||||
wholeWord,
|
||||
regex,
|
||||
results,
|
||||
toggleCaseSensitive,
|
||||
toggleWholeWord,
|
||||
toggleRegex,
|
||||
next,
|
||||
prev,
|
||||
close,
|
||||
backgroundColor,
|
||||
foregroundColor,
|
||||
borderColor,
|
||||
selectionColor,
|
||||
font
|
||||
} = props;
|
||||
class SearchBox extends React.PureComponent<SearchBoxProps> {
|
||||
searchTerm: string;
|
||||
input: HTMLInputElement | null = null;
|
||||
searchButtonColors: SearchButtonColors;
|
||||
|
||||
const searchTermRef = useRef<string>('');
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
constructor(props: SearchBoxProps) {
|
||||
super(props);
|
||||
this.searchTerm = '';
|
||||
this.searchButtonColors = {
|
||||
backgroundColor: this.props.borderColor,
|
||||
selectionColor: this.props.selectionColor,
|
||||
foregroundColor: this.props.foregroundColor
|
||||
};
|
||||
}
|
||||
|
||||
const handleChange = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
searchTermRef.current = event.currentTarget.value;
|
||||
if (event.shiftKey && event.key === 'Enter') {
|
||||
prev(searchTermRef.current);
|
||||
} else if (event.key === 'Enter') {
|
||||
next(searchTermRef.current);
|
||||
}
|
||||
},
|
||||
[prev, next]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
inputRef.current?.focus();
|
||||
}, [inputRef.current]);
|
||||
|
||||
const searchButtonColors: SearchButtonColors = {
|
||||
backgroundColor: borderColor,
|
||||
selectionColor,
|
||||
foregroundColor
|
||||
handleChange = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
this.searchTerm = event.currentTarget.value;
|
||||
if (event.shiftKey && event.key === 'Enter') {
|
||||
this.props.prev(this.searchTerm);
|
||||
} else if (event.key === 'Enter') {
|
||||
this.props.next(this.searchTerm);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex-row search-container" ref={ref}>
|
||||
<div className="flex-row search-box">
|
||||
<input className="search-input" type="text" onKeyDown={handleChange} ref={inputRef} placeholder="Search" />
|
||||
componentDidMount(): void {
|
||||
this.input?.focus();
|
||||
}
|
||||
|
||||
<SearchButton onClick={toggleCaseSensitive} active={caseSensitive} title="Match Case" {...searchButtonColors}>
|
||||
<VscCaseSensitive size="14px" />
|
||||
</SearchButton>
|
||||
render() {
|
||||
const {
|
||||
caseSensitive,
|
||||
wholeWord,
|
||||
regex,
|
||||
results,
|
||||
toggleCaseSensitive,
|
||||
toggleWholeWord,
|
||||
toggleRegex,
|
||||
next,
|
||||
prev,
|
||||
close,
|
||||
backgroundColor,
|
||||
foregroundColor,
|
||||
borderColor,
|
||||
selectionColor,
|
||||
font
|
||||
} = this.props;
|
||||
|
||||
<SearchButton onClick={toggleWholeWord} active={wholeWord} title="Match Whole Word" {...searchButtonColors}>
|
||||
<VscWholeWord size="14px" />
|
||||
</SearchButton>
|
||||
return (
|
||||
<div className="flex-row search-container">
|
||||
<div className="flex-row search-box">
|
||||
<input
|
||||
className="search-input"
|
||||
type="text"
|
||||
onKeyDown={this.handleChange}
|
||||
ref={(input) => {
|
||||
this.input = input;
|
||||
}}
|
||||
placeholder="Search"
|
||||
></input>
|
||||
|
||||
<SearchButton onClick={toggleRegex} active={regex} title="Use Regular Expression" {...searchButtonColors}>
|
||||
<VscRegex size="14px" />
|
||||
</SearchButton>
|
||||
</div>
|
||||
<SearchButton
|
||||
onClick={toggleCaseSensitive}
|
||||
active={caseSensitive}
|
||||
title="Match Case"
|
||||
{...this.searchButtonColors}
|
||||
>
|
||||
<VscCaseSensitive size="14px" />
|
||||
</SearchButton>
|
||||
|
||||
<span style={{minWidth: '60px', marginLeft: '4px'}}>
|
||||
{results === undefined
|
||||
? ''
|
||||
: results.resultCount === 0
|
||||
<SearchButton
|
||||
onClick={toggleWholeWord}
|
||||
active={wholeWord}
|
||||
title="Match Whole Word"
|
||||
{...this.searchButtonColors}
|
||||
>
|
||||
<VscWholeWord size="14px" />
|
||||
</SearchButton>
|
||||
|
||||
<SearchButton
|
||||
onClick={toggleRegex}
|
||||
active={regex}
|
||||
title="Use Regular Expression"
|
||||
{...this.searchButtonColors}
|
||||
>
|
||||
<VscRegex size="14px" />
|
||||
</SearchButton>
|
||||
</div>
|
||||
|
||||
<span style={{minWidth: '60px', marginLeft: '4px'}}>
|
||||
{results === undefined
|
||||
? ''
|
||||
: results.resultCount === 0
|
||||
? 'No results'
|
||||
: `${results.resultIndex + 1} of ${results.resultCount}`}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div className="flex-row">
|
||||
<SearchButton
|
||||
onClick={() => prev(searchTermRef.current)}
|
||||
active={false}
|
||||
title="Previous Match"
|
||||
{...searchButtonColors}
|
||||
>
|
||||
<VscArrowUp size="14px" />
|
||||
</SearchButton>
|
||||
<div className="flex-row">
|
||||
<SearchButton
|
||||
onClick={() => prev(this.searchTerm)}
|
||||
active={false}
|
||||
title="Previous Match"
|
||||
{...this.searchButtonColors}
|
||||
>
|
||||
<VscArrowUp size="14px" />
|
||||
</SearchButton>
|
||||
|
||||
<SearchButton
|
||||
onClick={() => next(searchTermRef.current)}
|
||||
active={false}
|
||||
title="Next Match"
|
||||
{...searchButtonColors}
|
||||
>
|
||||
<VscArrowDown size="14px" />
|
||||
</SearchButton>
|
||||
<SearchButton
|
||||
onClick={() => next(this.searchTerm)}
|
||||
active={false}
|
||||
title="Next Match"
|
||||
{...this.searchButtonColors}
|
||||
>
|
||||
<VscArrowDown size="14px" />
|
||||
</SearchButton>
|
||||
|
||||
<SearchButton onClick={close} active={false} title="Close" {...searchButtonColors}>
|
||||
<VscClose size="14px" />
|
||||
</SearchButton>
|
||||
<SearchButton onClick={() => close()} active={false} title="Close" {...this.searchButtonColors}>
|
||||
<VscClose size="14px" />
|
||||
</SearchButton>
|
||||
</div>
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.search-container {
|
||||
background-color: ${backgroundColor};
|
||||
border: 1px solid ${borderColor};
|
||||
border-radius: 2px;
|
||||
position: absolute;
|
||||
right: 13px;
|
||||
top: 4px;
|
||||
z-index: 10;
|
||||
padding: 4px;
|
||||
font-family: ${font};
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: ${foregroundColor};
|
||||
align-self: stretch;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
outline: ${borderColor} solid 1px;
|
||||
background-color: ${backgroundColor};
|
||||
color: ${foregroundColor};
|
||||
padding: 0px 4px;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: ${foregroundColor};
|
||||
}
|
||||
|
||||
.search-box:focus-within {
|
||||
outline: ${selectionColor} solid 2px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.search-container {
|
||||
background-color: ${backgroundColor};
|
||||
border: 1px solid ${borderColor};
|
||||
border-radius: 2px;
|
||||
position: absolute;
|
||||
right: 13px;
|
||||
top: 4px;
|
||||
z-index: 10;
|
||||
padding: 4px;
|
||||
font-family: ${font};
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: ${foregroundColor};
|
||||
align-self: stretch;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
outline: ${borderColor} solid 1px;
|
||||
background-color: ${backgroundColor};
|
||||
color: ${foregroundColor};
|
||||
padding: 0px 4px;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: ${foregroundColor};
|
||||
}
|
||||
|
||||
.search-box:focus-within {
|
||||
outline: ${selectionColor} solid 2px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
SearchBox.displayName = 'SearchBox';
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SearchBox;
|
||||
|
|
|
|||
|
|
@ -1,191 +1,219 @@
|
|||
import React, {useState, useEffect, useRef, forwardRef} from 'react';
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import type {SplitPaneProps} from '../hyper';
|
||||
|
||||
import sum from 'lodash/sum';
|
||||
export default class SplitPane extends React.PureComponent<SplitPaneProps, {dragging: boolean}> {
|
||||
dragPanePosition!: number;
|
||||
dragTarget!: Element;
|
||||
panes!: Element[];
|
||||
paneIndex!: number;
|
||||
d1!: 'height' | 'width';
|
||||
d2!: 'top' | 'left';
|
||||
d3!: 'clientX' | 'clientY';
|
||||
panesSize!: number;
|
||||
dragging!: boolean;
|
||||
constructor(props: SplitPaneProps) {
|
||||
super(props);
|
||||
this.state = {dragging: false};
|
||||
}
|
||||
|
||||
import type {SplitPaneProps} from '../../typings/hyper';
|
||||
componentDidUpdate(prevProps: SplitPaneProps) {
|
||||
if (this.state.dragging && prevProps.sizes !== this.props.sizes) {
|
||||
// recompute positions for ongoing dragging
|
||||
this.dragPanePosition = this.dragTarget.getBoundingClientRect()[this.d2];
|
||||
}
|
||||
}
|
||||
|
||||
const SplitPane = forwardRef<HTMLDivElement, SplitPaneProps>((props, ref) => {
|
||||
const dragPanePosition = useRef<number>(0);
|
||||
const dragTarget = useRef<HTMLDivElement | null>(null);
|
||||
const paneIndex = useRef<number>(0);
|
||||
const d1 = props.direction === 'horizontal' ? 'height' : 'width';
|
||||
const d2 = props.direction === 'horizontal' ? 'top' : 'left';
|
||||
const d3 = props.direction === 'horizontal' ? 'clientY' : 'clientX';
|
||||
const panesSize = useRef<number | null>(null);
|
||||
const [dragging, setDragging] = useState(false);
|
||||
setupPanes(ev: React.MouseEvent<HTMLDivElement>) {
|
||||
const target = ev.target as HTMLDivElement;
|
||||
this.panes = Array.from(target.parentElement?.children || []);
|
||||
this.paneIndex = this.panes.indexOf(target);
|
||||
this.paneIndex -= Math.ceil(this.paneIndex / 2);
|
||||
}
|
||||
|
||||
const handleAutoResize = (ev: React.MouseEvent<HTMLDivElement>, index: number) => {
|
||||
handleAutoResize = (ev: React.MouseEvent<HTMLDivElement>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
paneIndex.current = index;
|
||||
this.setupPanes(ev);
|
||||
|
||||
const sizes_ = getSizes();
|
||||
sizes_[paneIndex.current] = 0;
|
||||
sizes_[paneIndex.current + 1] = 0;
|
||||
const sizes_ = this.getSizes();
|
||||
sizes_[this.paneIndex] = 0;
|
||||
sizes_[this.paneIndex + 1] = 0;
|
||||
|
||||
const availableWidth = 1 - sum(sizes_);
|
||||
sizes_[paneIndex.current] = availableWidth / 2;
|
||||
sizes_[paneIndex.current + 1] = availableWidth / 2;
|
||||
const availableWidth = 1 - _.sum(sizes_);
|
||||
sizes_[this.paneIndex] = availableWidth / 2;
|
||||
sizes_[this.paneIndex + 1] = availableWidth / 2;
|
||||
|
||||
props.onResize(sizes_);
|
||||
this.props.onResize(sizes_);
|
||||
};
|
||||
|
||||
const handleDragStart = (ev: React.MouseEvent<HTMLDivElement>, index: number) => {
|
||||
handleDragStart = (ev: React.MouseEvent<HTMLDivElement>) => {
|
||||
ev.preventDefault();
|
||||
setDragging(true);
|
||||
window.addEventListener('mousemove', onDrag);
|
||||
window.addEventListener('mouseup', onDragEnd);
|
||||
this.setState({dragging: true});
|
||||
window.addEventListener('mousemove', this.onDrag);
|
||||
window.addEventListener('mouseup', this.onDragEnd);
|
||||
|
||||
// dimensions to consider
|
||||
if (this.props.direction === 'horizontal') {
|
||||
this.d1 = 'height';
|
||||
this.d2 = 'top';
|
||||
this.d3 = 'clientY';
|
||||
} else {
|
||||
this.d1 = 'width';
|
||||
this.d2 = 'left';
|
||||
this.d3 = 'clientX';
|
||||
}
|
||||
|
||||
const target = ev.target as HTMLDivElement;
|
||||
dragTarget.current = target;
|
||||
dragPanePosition.current = dragTarget.current.getBoundingClientRect()[d2];
|
||||
panesSize.current = target.parentElement!.getBoundingClientRect()[d1];
|
||||
paneIndex.current = index;
|
||||
this.dragTarget = target;
|
||||
this.dragPanePosition = this.dragTarget.getBoundingClientRect()[this.d2];
|
||||
this.panesSize = target.parentElement!.getBoundingClientRect()[this.d1];
|
||||
this.setupPanes(ev);
|
||||
};
|
||||
|
||||
const getSizes = () => {
|
||||
const {sizes} = props;
|
||||
getSizes() {
|
||||
const {sizes} = this.props;
|
||||
let sizes_: number[];
|
||||
|
||||
if (sizes) {
|
||||
sizes_ = [...sizes.asMutable()];
|
||||
} else {
|
||||
const total = props.children.length;
|
||||
const total = (this.props.children as React.ReactNodeArray).length;
|
||||
const count = new Array<number>(total).fill(1 / total);
|
||||
|
||||
sizes_ = count;
|
||||
}
|
||||
return sizes_;
|
||||
};
|
||||
}
|
||||
|
||||
const onDrag = (ev: MouseEvent) => {
|
||||
const sizes_ = getSizes();
|
||||
onDrag = (ev: MouseEvent) => {
|
||||
const sizes_ = this.getSizes();
|
||||
|
||||
const i = paneIndex.current;
|
||||
const pos = ev[d3];
|
||||
const d = Math.abs(dragPanePosition.current - pos) / panesSize.current!;
|
||||
if (pos > dragPanePosition.current) {
|
||||
const i = this.paneIndex;
|
||||
const pos = ev[this.d3];
|
||||
const d = Math.abs(this.dragPanePosition - pos) / this.panesSize;
|
||||
if (pos > this.dragPanePosition) {
|
||||
sizes_[i] += d;
|
||||
sizes_[i + 1] -= d;
|
||||
} else {
|
||||
sizes_[i] -= d;
|
||||
sizes_[i + 1] += d;
|
||||
}
|
||||
props.onResize(sizes_);
|
||||
this.props.onResize(sizes_);
|
||||
};
|
||||
|
||||
const onDragEnd = () => {
|
||||
window.removeEventListener('mousemove', onDrag);
|
||||
window.removeEventListener('mouseup', onDragEnd);
|
||||
setDragging(false);
|
||||
onDragEnd = () => {
|
||||
if (this.state.dragging) {
|
||||
window.removeEventListener('mousemove', this.onDrag);
|
||||
window.removeEventListener('mouseup', this.onDragEnd);
|
||||
this.setState({dragging: false});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
onDragEnd();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const {children, direction, borderColor} = props;
|
||||
const sizeProperty = direction === 'horizontal' ? 'height' : 'width';
|
||||
// workaround for the fact that if we don't specify
|
||||
// sizes, sometimes flex fails to calculate the
|
||||
// right height for the horizontal panes
|
||||
const sizes = props.sizes || new Array<number>(children.length).fill(1 / children.length);
|
||||
return (
|
||||
<div className={`splitpane_panes splitpane_panes_${direction}`} ref={ref}>
|
||||
{children.map((child, i) => {
|
||||
const style = {
|
||||
// flexBasis doesn't work for the first horizontal pane, height need to be specified
|
||||
[sizeProperty]: `${sizes[i] * 100}%`,
|
||||
flexBasis: `${sizes[i] * 100}%`,
|
||||
flexGrow: 0
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment key={i}>
|
||||
<div className="splitpane_pane" style={style}>
|
||||
render() {
|
||||
const children = this.props.children as React.ReactNodeArray;
|
||||
const {direction, borderColor} = this.props;
|
||||
const sizeProperty = direction === 'horizontal' ? 'height' : 'width';
|
||||
// workaround for the fact that if we don't specify
|
||||
// sizes, sometimes flex fails to calculate the
|
||||
// right height for the horizontal panes
|
||||
const sizes = this.props.sizes || new Array<number>(children.length).fill(1 / children.length);
|
||||
return (
|
||||
<div className={`splitpane_panes splitpane_panes_${direction}`}>
|
||||
{React.Children.map(children, (child, i) => {
|
||||
const style = {
|
||||
// flexBasis doesn't work for the first horizontal pane, height need to be specified
|
||||
[sizeProperty]: `${sizes[i] * 100}%`,
|
||||
flexBasis: `${sizes[i] * 100}%`,
|
||||
flexGrow: 0
|
||||
};
|
||||
return [
|
||||
<div key="pane" className="splitpane_pane" style={style}>
|
||||
{child}
|
||||
</div>
|
||||
{i < children.length - 1 ? (
|
||||
</div>,
|
||||
i < children.length - 1 ? (
|
||||
<div
|
||||
onMouseDown={(e) => handleDragStart(e, i)}
|
||||
onDoubleClick={(e) => handleAutoResize(e, i)}
|
||||
key="divider"
|
||||
onMouseDown={this.handleDragStart}
|
||||
onDoubleClick={this.handleAutoResize}
|
||||
style={{backgroundColor: borderColor}}
|
||||
className={`splitpane_divider splitpane_divider_${direction}`}
|
||||
/>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
<div style={{display: dragging ? 'block' : 'none'}} className="splitpane_shim" />
|
||||
) : null
|
||||
];
|
||||
})}
|
||||
<div style={{display: this.state.dragging ? 'block' : 'none'}} className="splitpane_shim" />
|
||||
|
||||
<style jsx>{`
|
||||
.splitpane_panes {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
outline: none;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
<style jsx>{`
|
||||
.splitpane_panes {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
outline: none;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.splitpane_panes_vertical {
|
||||
flex-direction: row;
|
||||
}
|
||||
.splitpane_panes_vertical {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.splitpane_panes_horizontal {
|
||||
flex-direction: column;
|
||||
}
|
||||
.splitpane_panes_horizontal {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.splitpane_pane {
|
||||
flex: 1;
|
||||
outline: none;
|
||||
position: relative;
|
||||
}
|
||||
.splitpane_pane {
|
||||
flex: 1;
|
||||
outline: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.splitpane_divider {
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
background-clip: padding-box;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.splitpane_divider {
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
background-clip: padding-box;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.splitpane_divider_vertical {
|
||||
border-left: 5px solid rgba(255, 255, 255, 0);
|
||||
border-right: 5px solid rgba(255, 255, 255, 0);
|
||||
width: 11px;
|
||||
margin: 0 -5px;
|
||||
cursor: col-resize;
|
||||
}
|
||||
.splitpane_divider_vertical {
|
||||
border-left: 5px solid rgba(255, 255, 255, 0);
|
||||
border-right: 5px solid rgba(255, 255, 255, 0);
|
||||
width: 11px;
|
||||
margin: 0 -5px;
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.splitpane_divider_horizontal {
|
||||
height: 11px;
|
||||
margin: -5px 0;
|
||||
border-top: 5px solid rgba(255, 255, 255, 0);
|
||||
border-bottom: 5px solid rgba(255, 255, 255, 0);
|
||||
cursor: row-resize;
|
||||
width: 100%;
|
||||
}
|
||||
.splitpane_divider_horizontal {
|
||||
height: 11px;
|
||||
margin: -5px 0;
|
||||
border-top: 5px solid rgba(255, 255, 255, 0);
|
||||
border-bottom: 5px solid rgba(255, 255, 255, 0);
|
||||
cursor: row-resize;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
this shim is used to make sure mousemove events
|
||||
trigger in all the draggable area of the screen
|
||||
this is not the case due to hterm's <iframe>
|
||||
*/
|
||||
.splitpane_shim {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
/*
|
||||
this shim is used to make sure mousemove events
|
||||
trigger in all the draggable area of the screen
|
||||
this is not the case due to hterm's <iframe>
|
||||
*/
|
||||
.splitpane_shim {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
SplitPane.displayName = 'SplitPane';
|
||||
|
||||
export default SplitPane;
|
||||
componentWillUnmount() {
|
||||
// ensure drag end
|
||||
if (this.dragging) {
|
||||
this.onDragEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,24 @@
|
|||
import React, {forwardRef} from 'react';
|
||||
import React from 'react';
|
||||
import type {StyleSheetProps} from '../hyper';
|
||||
|
||||
import type {StyleSheetProps} from '../../typings/hyper';
|
||||
export default class StyleSheet extends React.PureComponent<StyleSheetProps> {
|
||||
render() {
|
||||
const {borderColor} = this.props;
|
||||
|
||||
const StyleSheet = forwardRef<HTMLStyleElement, StyleSheetProps>((props, ref) => {
|
||||
const {borderColor} = props;
|
||||
|
||||
return (
|
||||
<style jsx global ref={ref}>{`
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
background: ${borderColor};
|
||||
}
|
||||
::-webkit-scrollbar-thumb:window-inactive {
|
||||
background: ${borderColor};
|
||||
}
|
||||
`}</style>
|
||||
);
|
||||
});
|
||||
|
||||
StyleSheet.displayName = 'StyleSheet';
|
||||
|
||||
export default StyleSheet;
|
||||
return (
|
||||
<style jsx global>{`
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
background: ${borderColor};
|
||||
}
|
||||
::-webkit-scrollbar-thumb:window-inactive {
|
||||
background: ${borderColor};
|
||||
}
|
||||
`}</style>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,168 +1,164 @@
|
|||
import React, {forwardRef} from 'react';
|
||||
import React from 'react';
|
||||
import type {TabProps} from '../hyper';
|
||||
|
||||
import type {TabProps} from '../../typings/hyper';
|
||||
export default class Tab extends React.PureComponent<TabProps> {
|
||||
constructor(props: TabProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
const Tab = forwardRef<HTMLLIElement, TabProps>((props, ref) => {
|
||||
const handleClick = (event: React.MouseEvent) => {
|
||||
handleClick = (event: React.MouseEvent) => {
|
||||
const isLeftClick = event.nativeEvent.which === 1;
|
||||
|
||||
if (isLeftClick && !props.isActive) {
|
||||
props.onSelect();
|
||||
if (isLeftClick && !this.props.isActive) {
|
||||
this.props.onSelect();
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = (event: React.MouseEvent) => {
|
||||
handleMouseUp = (event: React.MouseEvent) => {
|
||||
const isMiddleClick = event.nativeEvent.which === 2;
|
||||
|
||||
if (isMiddleClick) {
|
||||
props.onClose();
|
||||
this.props.onClose();
|
||||
}
|
||||
};
|
||||
|
||||
const {isActive, isFirst, isLast, borderColor, hasActivity} = props;
|
||||
render() {
|
||||
const {isActive, isFirst, isLast, borderColor, hasActivity} = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<li
|
||||
onClick={props.onClick}
|
||||
style={{borderColor}}
|
||||
className={`tab_tab ${isFirst ? 'tab_first' : ''} ${isActive ? 'tab_active' : ''} ${
|
||||
isFirst && isActive ? 'tab_firstActive' : ''
|
||||
} ${hasActivity ? 'tab_hasActivity' : ''}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.customChildrenBefore}
|
||||
<span
|
||||
className={`tab_text ${isLast ? 'tab_textLast' : ''} ${isActive ? 'tab_textActive' : ''}`}
|
||||
onClick={handleClick}
|
||||
onMouseUp={handleMouseUp}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<li
|
||||
onClick={this.props.onClick}
|
||||
style={{borderColor}}
|
||||
className={`tab_tab ${isFirst ? 'tab_first' : ''} ${isActive ? 'tab_active' : ''} ${
|
||||
isFirst && isActive ? 'tab_firstActive' : ''
|
||||
} ${hasActivity ? 'tab_hasActivity' : ''}`}
|
||||
>
|
||||
<span title={props.text} className="tab_textInner">
|
||||
{props.text}
|
||||
{this.props.customChildrenBefore}
|
||||
<span
|
||||
className={`tab_text ${isLast ? 'tab_textLast' : ''} ${isActive ? 'tab_textActive' : ''}`}
|
||||
onClick={this.handleClick}
|
||||
onMouseUp={this.handleMouseUp}
|
||||
>
|
||||
<span title={this.props.text} className="tab_textInner">
|
||||
{this.props.text}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<i className="tab_icon" onClick={props.onClose}>
|
||||
<svg className="tab_shape">
|
||||
<use xlinkHref="./renderer/assets/icons.svg#close-tab" />
|
||||
</svg>
|
||||
</i>
|
||||
{props.customChildren}
|
||||
</li>
|
||||
<i className="tab_icon" onClick={this.props.onClose}>
|
||||
<svg className="tab_shape">
|
||||
<use xlinkHref="./renderer/assets/icons.svg#close-tab" />
|
||||
</svg>
|
||||
</i>
|
||||
{this.props.customChildren}
|
||||
</li>
|
||||
|
||||
<style jsx>{`
|
||||
.tab_tab {
|
||||
color: #ccc;
|
||||
border-color: #ccc;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
list-style-type: none;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
<style jsx>{`
|
||||
.tab_tab {
|
||||
color: #ccc;
|
||||
border-color: #ccc;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
list-style-type: none;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab_tab:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
.tab_tab:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.tab_first {
|
||||
border-left-width: 0;
|
||||
padding-left: 1px;
|
||||
}
|
||||
.tab_first {
|
||||
border-left-width: 0;
|
||||
padding-left: 1px;
|
||||
}
|
||||
|
||||
.tab_firstActive {
|
||||
border-left-width: 1px;
|
||||
padding-left: 0;
|
||||
}
|
||||
.tab_firstActive {
|
||||
border-left-width: 1px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.tab_active {
|
||||
color: #fff;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
.tab_active:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.tab_active {
|
||||
color: #fff;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
.tab_active:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tab_hasActivity {
|
||||
color: #50e3c2;
|
||||
}
|
||||
.tab_hasActivity {
|
||||
color: #50e3c2;
|
||||
}
|
||||
|
||||
.tab_hasActivity:hover {
|
||||
color: #50e3c2;
|
||||
}
|
||||
.tab_hasActivity:hover {
|
||||
color: #50e3c2;
|
||||
}
|
||||
|
||||
.tab_text {
|
||||
transition: color 0.2s ease;
|
||||
height: 34px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tab_text {
|
||||
transition: color 0.2s ease;
|
||||
height: 34px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab_textInner {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
right: 24px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tab_textInner {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
right: 24px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab_icon {
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
color 0.2s ease,
|
||||
transform 0.25s ease,
|
||||
background-color 0.1s ease;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
top: 10px;
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 100%;
|
||||
color: #e9e9e9;
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
.tab_icon {
|
||||
transition: opacity 0.2s ease, color 0.2s ease, transform 0.25s ease, background-color 0.1s ease;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
top: 10px;
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 100%;
|
||||
color: #e9e9e9;
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.tab_icon:hover {
|
||||
background-color: rgba(255, 255, 255, 0.13);
|
||||
color: #fff;
|
||||
}
|
||||
.tab_icon:hover {
|
||||
background-color: rgba(255, 255, 255, 0.13);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tab_icon:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: #909090;
|
||||
}
|
||||
.tab_icon:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: #909090;
|
||||
}
|
||||
|
||||
.tab_tab:hover .tab_icon {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
pointer-events: all;
|
||||
}
|
||||
.tab_tab:hover .tab_icon {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.tab_shape {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 4px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
vertical-align: middle;
|
||||
fill: currentColor;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
`}</style>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
Tab.displayName = 'Tab';
|
||||
|
||||
export default Tab;
|
||||
.tab_shape {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 4px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
vertical-align: middle;
|
||||
fill: currentColor;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
`}</style>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,113 +1,111 @@
|
|||
import React, {forwardRef} from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import type {TabsProps} from '../../typings/hyper';
|
||||
import {decorate, getTabProps} from '../utils/plugins';
|
||||
|
||||
import DropdownButton from './new-tab';
|
||||
import Tab_ from './tab';
|
||||
import type {TabsProps} from '../hyper';
|
||||
import DropdownButton from './new-tab';
|
||||
|
||||
const Tab = decorate(Tab_, 'Tab');
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
|
||||
const Tabs = forwardRef<HTMLElement, TabsProps>((props, ref) => {
|
||||
const {tabs = [], borderColor, onChange, onClose, fullScreen} = props;
|
||||
export default class Tabs extends React.PureComponent<TabsProps> {
|
||||
render() {
|
||||
const {tabs = [], borderColor, onChange, onClose, fullScreen} = this.props;
|
||||
|
||||
const hide = !isMac && tabs.length === 1;
|
||||
const hide = !isMac && tabs.length === 1;
|
||||
|
||||
return (
|
||||
<nav className={`tabs_nav ${hide ? 'tabs_hiddenNav' : ''}`} ref={ref}>
|
||||
{props.customChildrenBefore}
|
||||
{tabs.length === 1 && isMac ? <div className="tabs_title">{tabs[0].title}</div> : null}
|
||||
{tabs.length > 1 ? (
|
||||
<>
|
||||
<ul key="list" className={`tabs_list ${fullScreen && isMac ? 'tabs_fullScreen' : ''}`}>
|
||||
{tabs.map((tab, i) => {
|
||||
const {uid, title, isActive, hasActivity} = tab;
|
||||
const tabProps = getTabProps(tab, props, {
|
||||
text: title === '' ? 'Shell' : title,
|
||||
isFirst: i === 0,
|
||||
isLast: tabs.length - 1 === i,
|
||||
borderColor,
|
||||
isActive,
|
||||
hasActivity,
|
||||
onSelect: onChange.bind(null, uid),
|
||||
onClose: onClose.bind(null, uid)
|
||||
});
|
||||
return <Tab key={`tab-${uid}`} {...tabProps} />;
|
||||
})}
|
||||
</ul>
|
||||
{isMac && (
|
||||
<div
|
||||
key="shim"
|
||||
style={{borderColor}}
|
||||
className={`tabs_borderShim ${fullScreen ? 'tabs_borderShimUndo' : ''}`}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
<DropdownButton {...props} tabsVisible={tabs.length > 1} />
|
||||
{props.customChildren}
|
||||
return (
|
||||
<nav className={`tabs_nav ${hide ? 'tabs_hiddenNav' : ''}`}>
|
||||
{this.props.customChildrenBefore}
|
||||
{tabs.length === 1 && isMac ? <div className="tabs_title">{tabs[0].title}</div> : null}
|
||||
{tabs.length > 1
|
||||
? [
|
||||
<ul key="list" className={`tabs_list ${fullScreen && isMac ? 'tabs_fullScreen' : ''}`}>
|
||||
{tabs.map((tab, i) => {
|
||||
const {uid, title, isActive, hasActivity} = tab;
|
||||
const props = getTabProps(tab, this.props, {
|
||||
text: title === '' ? 'Shell' : title,
|
||||
isFirst: i === 0,
|
||||
isLast: tabs.length - 1 === i,
|
||||
borderColor,
|
||||
isActive,
|
||||
hasActivity,
|
||||
onSelect: onChange.bind(null, uid),
|
||||
onClose: onClose.bind(null, uid)
|
||||
});
|
||||
return <Tab key={`tab-${uid}`} {...props} />;
|
||||
})}
|
||||
</ul>,
|
||||
isMac && (
|
||||
<div
|
||||
key="shim"
|
||||
style={{borderColor}}
|
||||
className={`tabs_borderShim ${fullScreen ? 'tabs_borderShimUndo' : ''}`}
|
||||
/>
|
||||
)
|
||||
]
|
||||
: null}
|
||||
<DropdownButton {...this.props} tabsVisible={tabs.length > 1} />
|
||||
{this.props.customChildren}
|
||||
|
||||
<style jsx>{`
|
||||
.tabs_nav {
|
||||
font-size: 12px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
vertical-align: middle;
|
||||
color: #9b9b9b;
|
||||
cursor: default;
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-webkit-app-region: ${isMac ? 'drag' : ''};
|
||||
top: ${isMac ? '0px' : '34px'};
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
}
|
||||
<style jsx>{`
|
||||
.tabs_nav {
|
||||
font-size: 12px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
vertical-align: middle;
|
||||
color: #9b9b9b;
|
||||
cursor: default;
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-webkit-app-region: ${isMac ? 'drag' : ''};
|
||||
top: ${isMac ? '0px' : '34px'};
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
}
|
||||
|
||||
.tabs_hiddenNav {
|
||||
display: none;
|
||||
}
|
||||
.tabs_hiddenNav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tabs_title {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-left: 76px;
|
||||
padding-right: 76px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.tabs_title {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-left: 76px;
|
||||
padding-right: 76px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tabs_list {
|
||||
max-height: 34px;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
margin-left: ${isMac ? '76px' : '0'};
|
||||
flex-grow: 1;
|
||||
}
|
||||
.tabs_list {
|
||||
max-height: 34px;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
margin-left: ${isMac ? '76px' : '0'};
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tabs_fullScreen {
|
||||
margin-left: -1px;
|
||||
}
|
||||
.tabs_fullScreen {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
.tabs_borderShim {
|
||||
position: absolute;
|
||||
width: 76px;
|
||||
bottom: 0;
|
||||
border-color: #ccc;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
.tabs_borderShim {
|
||||
position: absolute;
|
||||
width: 76px;
|
||||
bottom: 0;
|
||||
border-color: #ccc;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.tabs_borderShimUndo {
|
||||
border-bottom-width: 0px;
|
||||
}
|
||||
`}</style>
|
||||
</nav>
|
||||
);
|
||||
});
|
||||
|
||||
Tabs.displayName = 'Tabs';
|
||||
|
||||
export default Tabs;
|
||||
.tabs_borderShimUndo {
|
||||
border-bottom-width: 0px;
|
||||
}
|
||||
`}</style>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import React from 'react';
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import type {HyperState, HyperDispatch, TermGroupProps, TermGroupOwnProps} from '../../typings/hyper';
|
||||
import {resizeTermGroup} from '../actions/term-groups';
|
||||
import {decorate, getTermProps, getTermGroupProps} from '../utils/plugins';
|
||||
|
||||
import SplitPane_ from './split-pane';
|
||||
import {resizeTermGroup} from '../actions/term-groups';
|
||||
import Term_ from './term';
|
||||
import SplitPane_ from './split-pane';
|
||||
import type {HyperState, HyperDispatch, TermGroupProps, TermGroupOwnProps} from '../hyper';
|
||||
|
||||
const Term = decorate(Term_, 'Term');
|
||||
const SplitPane = decorate(SplitPane_, 'SplitPane');
|
||||
|
|
|
|||
|
|
@ -1,29 +1,24 @@
|
|||
import {clipboard, shell} from 'electron';
|
||||
import React from 'react';
|
||||
|
||||
import Color from 'color';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import pickBy from 'lodash/pickBy';
|
||||
import {Terminal} from 'xterm';
|
||||
import type {ITerminalOptions, IDisposable} from 'xterm';
|
||||
import {CanvasAddon} from 'xterm-addon-canvas';
|
||||
import {Terminal} from 'xterm';
|
||||
import {FitAddon} from 'xterm-addon-fit';
|
||||
import {ImageAddon} from 'xterm-addon-image';
|
||||
import {LigaturesAddon} from 'xterm-addon-ligatures';
|
||||
import {SearchAddon} from 'xterm-addon-search';
|
||||
import type {ISearchDecorationOptions} from 'xterm-addon-search';
|
||||
import {Unicode11Addon} from 'xterm-addon-unicode11';
|
||||
import {WebLinksAddon} from 'xterm-addon-web-links';
|
||||
import type {ISearchDecorationOptions} from 'xterm-addon-search';
|
||||
import {SearchAddon} from 'xterm-addon-search';
|
||||
import {WebglAddon} from 'xterm-addon-webgl';
|
||||
|
||||
import type {TermProps} from '../../typings/hyper';
|
||||
import {CanvasAddon} from 'xterm-addon-canvas';
|
||||
import {LigaturesAddon} from 'xterm-addon-ligatures';
|
||||
import {Unicode11Addon} from 'xterm-addon-unicode11';
|
||||
import {clipboard, shell} from 'electron';
|
||||
import Color from 'color';
|
||||
import terms from '../terms';
|
||||
import processClipboard from '../utils/paste';
|
||||
import {decorate} from '../utils/plugins';
|
||||
|
||||
import _SearchBox from './searchBox';
|
||||
|
||||
import type {TermProps} from '../hyper';
|
||||
import {pickBy, isEqual} from 'lodash';
|
||||
import {decorate} from '../utils/plugins';
|
||||
import 'xterm/css/xterm.css';
|
||||
import {ImageAddon} from 'xterm-addon-image';
|
||||
|
||||
const SearchBox = decorate(_SearchBox, 'SearchBox');
|
||||
|
||||
|
|
@ -421,8 +416,8 @@ export default class Term extends React.PureComponent<
|
|||
return !e.catched;
|
||||
}
|
||||
|
||||
setBellSound(bell: 'SOUND' | false, sound: string | null) {
|
||||
if (bell && bell.toUpperCase() === 'SOUND') {
|
||||
setBellSound(bell: string | null, sound: string | null) {
|
||||
if (bell?.toUpperCase() === 'SOUND') {
|
||||
this.bellSound = sound ? new Audio(sound) : this.defaultBellSound;
|
||||
} else {
|
||||
this.bellSound = null;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
import React from 'react';
|
||||
|
||||
import type {TermsProps, HyperDispatch} from '../../typings/hyper';
|
||||
import {registerCommandHandlers} from '../command-registry';
|
||||
import {ObjectTypedKeys} from '../utils/object';
|
||||
import {decorate, getTermGroupProps} from '../utils/plugins';
|
||||
|
||||
import StyleSheet_ from './style-sheet';
|
||||
import type Term from './term';
|
||||
import {registerCommandHandlers} from '../command-registry';
|
||||
import TermGroup_ from './term-group';
|
||||
import StyleSheet_ from './style-sheet';
|
||||
import type {TermsProps, HyperDispatch} from '../hyper';
|
||||
import type Term from './term';
|
||||
import {ObjectTypedKeys} from '../utils/object';
|
||||
|
||||
const TermGroup = decorate(TermGroup_, 'TermGroup');
|
||||
const StyleSheet = decorate(StyleSheet_, 'StyleSheet');
|
||||
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
|
||||
export default class Terms extends React.Component<React.PropsWithChildren<TermsProps>> {
|
||||
export default class Terms extends React.Component<TermsProps> {
|
||||
terms: Record<string, Term>;
|
||||
registerCommands: (cmds: Record<string, (e: any, dispatch: HyperDispatch) => void>) => void;
|
||||
constructor(props: TermsProps, context: any) {
|
||||
|
|
|
|||
2
typings/config.d.ts → lib/config.d.ts
vendored
2
typings/config.d.ts → lib/config.d.ts
vendored
|
|
@ -46,7 +46,7 @@ type profileConfigOptions = {
|
|||
* 1. 'SOUND' -> Enables the bell as a sound
|
||||
* 2. false: turns off the bell
|
||||
*/
|
||||
bell: 'SOUND' | false;
|
||||
bell: string;
|
||||
/**
|
||||
* base64 encoded string of the sound file to use for the bell
|
||||
* if null, the default bell will be used
|
||||
|
|
@ -2,10 +2,10 @@ export const TERM_GROUP_REQUEST = 'TERM_GROUP_REQUEST';
|
|||
export const TERM_GROUP_EXIT = 'TERM_GROUP_EXIT';
|
||||
export const TERM_GROUP_RESIZE = 'TERM_GROUP_RESIZE';
|
||||
export const TERM_GROUP_EXIT_ACTIVE = 'TERM_GROUP_EXIT_ACTIVE';
|
||||
export enum DIRECTION {
|
||||
HORIZONTAL = 'HORIZONTAL',
|
||||
VERTICAL = 'VERTICAL'
|
||||
}
|
||||
export const DIRECTION = {
|
||||
HORIZONTAL: 'HORIZONTAL',
|
||||
VERTICAL: 'VERTICAL'
|
||||
} as const;
|
||||
|
||||
export interface TermGroupRequestAction {
|
||||
type: typeof TERM_GROUP_REQUEST;
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import {createSelector} from 'reselect';
|
||||
|
||||
import type {HyperState, HyperDispatch, ITab} from '../../typings/hyper';
|
||||
import {closeTab, changeTab, maximize, openHamburgerMenu, unmaximize, minimize, close} from '../actions/header';
|
||||
import {requestTermGroup} from '../actions/term-groups';
|
||||
import Header from '../components/header';
|
||||
import {getRootGroups} from '../selectors';
|
||||
import {closeTab, changeTab, maximize, openHamburgerMenu, unmaximize, minimize, close} from '../actions/header';
|
||||
import {connect} from '../utils/plugins';
|
||||
import {getRootGroups} from '../selectors';
|
||||
import type {HyperState, HyperDispatch, ITab} from '../hyper';
|
||||
import {requestTermGroup} from '../actions/term-groups';
|
||||
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,142 +1,145 @@
|
|||
import React, {forwardRef, useEffect, useRef} from 'react';
|
||||
|
||||
import Mousetrap from 'mousetrap';
|
||||
import React from 'react';
|
||||
import type {MousetrapInstance} from 'mousetrap';
|
||||
import stylis from 'stylis';
|
||||
import Mousetrap from 'mousetrap';
|
||||
|
||||
import type {HyperState, HyperProps, HyperDispatch} from '../../typings/hyper';
|
||||
import {connect} from '../utils/plugins';
|
||||
import * as uiActions from '../actions/ui';
|
||||
import {getRegisteredKeys, getCommandHandler, shouldPreventDefault} from '../command-registry';
|
||||
import type Terms from '../components/terms';
|
||||
import {connect} from '../utils/plugins';
|
||||
import stylis from 'stylis';
|
||||
|
||||
import {HeaderContainer} from './header';
|
||||
import NotificationsContainer from './notifications';
|
||||
import TermsContainer from './terms';
|
||||
import NotificationsContainer from './notifications';
|
||||
import type {HyperState, HyperProps, HyperDispatch} from '../hyper';
|
||||
import type Terms from '../components/terms';
|
||||
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
|
||||
const Hyper = forwardRef<HTMLDivElement, HyperProps>((props, ref) => {
|
||||
const mousetrap = useRef<MousetrapInstance | null>(null);
|
||||
const terms = useRef<Terms | null>(null);
|
||||
class Hyper extends React.PureComponent<HyperProps> {
|
||||
mousetrap!: MousetrapInstance;
|
||||
terms!: Terms;
|
||||
constructor(props: HyperProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
void attachKeyListeners();
|
||||
}, [props.lastConfigUpdate]);
|
||||
useEffect(() => {
|
||||
handleFocusActive(props.activeSession);
|
||||
}, [props.activeSession]);
|
||||
componentDidUpdate(prev: HyperProps) {
|
||||
const {lastConfigUpdate} = this.props;
|
||||
if (lastConfigUpdate && lastConfigUpdate !== prev.lastConfigUpdate) {
|
||||
this.attachKeyListeners();
|
||||
}
|
||||
if (prev.activeSession !== this.props.activeSession) {
|
||||
this.handleFocusActive(this.props.activeSession);
|
||||
}
|
||||
}
|
||||
|
||||
const handleFocusActive = (uid?: string | null) => {
|
||||
const term = uid && terms.current?.getTermByUid(uid);
|
||||
handleFocusActive = (uid?: string | null) => {
|
||||
const term = uid && this.terms.getTermByUid(uid);
|
||||
if (term) {
|
||||
term.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAll = () => {
|
||||
const term = terms.current?.getActiveTerm();
|
||||
handleSelectAll = () => {
|
||||
const term = this.terms.getActiveTerm();
|
||||
if (term) {
|
||||
term.selectAll();
|
||||
}
|
||||
};
|
||||
|
||||
const attachKeyListeners = async () => {
|
||||
if (!mousetrap.current) {
|
||||
attachKeyListeners() {
|
||||
if (!this.mousetrap) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
mousetrap.current = new (Mousetrap as any)(window, true);
|
||||
mousetrap.current!.stopCallback = () => {
|
||||
this.mousetrap = new (Mousetrap as any)(window, true);
|
||||
this.mousetrap.stopCallback = () => {
|
||||
// All events should be intercepted even if focus is in an input/textarea
|
||||
return false;
|
||||
};
|
||||
} else {
|
||||
mousetrap.current.reset();
|
||||
this.mousetrap.reset();
|
||||
}
|
||||
|
||||
const keys = await getRegisteredKeys();
|
||||
const keys = getRegisteredKeys();
|
||||
Object.keys(keys).forEach((commandKeys) => {
|
||||
mousetrap.current?.bind(
|
||||
this.mousetrap.bind(
|
||||
commandKeys,
|
||||
(e) => {
|
||||
const command = keys[commandKeys];
|
||||
// We should tell xterm to ignore this event.
|
||||
// We should tell to xterm that it should ignore this event.
|
||||
(e as any).catched = true;
|
||||
props.execCommand(command, getCommandHandler(command), e);
|
||||
this.props.execCommand(command, getCommandHandler(command), e);
|
||||
shouldPreventDefault(command) && e.preventDefault();
|
||||
},
|
||||
'keydown'
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
void attachKeyListeners();
|
||||
window.rpc.on('term selectAll', handleSelectAll);
|
||||
}, []);
|
||||
componentDidMount() {
|
||||
this.attachKeyListeners();
|
||||
window.rpc.on('term selectAll', this.handleSelectAll);
|
||||
}
|
||||
|
||||
const onTermsRef = (_terms: Terms | null) => {
|
||||
terms.current = _terms;
|
||||
onTermsRef = (terms: Terms) => {
|
||||
this.terms = terms;
|
||||
window.focusActiveTerm = (uid?: string) => {
|
||||
if (uid) {
|
||||
handleFocusActive(uid);
|
||||
this.handleFocusActive(uid);
|
||||
} else {
|
||||
terms.current?.getActiveTerm()?.focus();
|
||||
this.terms.getActiveTerm().focus();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
mousetrap.current?.reset();
|
||||
};
|
||||
}, []);
|
||||
componentWillUnmount() {
|
||||
this.mousetrap?.reset();
|
||||
}
|
||||
|
||||
const {isMac: isMac_, customCSS, uiFontFamily, borderColor, maximized, fullScreen} = props;
|
||||
const borderWidth = isMac_ ? '' : `${maximized ? '0' : '1'}px`;
|
||||
stylis.set({prefix: false});
|
||||
return (
|
||||
<div id="hyper" ref={ref}>
|
||||
<div
|
||||
style={{fontFamily: uiFontFamily, borderColor, borderWidth}}
|
||||
className={`hyper_main ${isMac_ && 'hyper_mainRounded'} ${fullScreen ? 'fullScreen' : ''}`}
|
||||
>
|
||||
<HeaderContainer />
|
||||
<TermsContainer ref_={onTermsRef} />
|
||||
{props.customInnerChildren}
|
||||
render() {
|
||||
const {isMac: isMac_, customCSS, uiFontFamily, borderColor, maximized, fullScreen} = this.props;
|
||||
const borderWidth = isMac_ ? '' : `${maximized ? '0' : '1'}px`;
|
||||
stylis.set({prefix: false});
|
||||
return (
|
||||
<div id="hyper">
|
||||
<div
|
||||
style={{fontFamily: uiFontFamily, borderColor, borderWidth}}
|
||||
className={`hyper_main ${isMac_ && 'hyper_mainRounded'} ${fullScreen ? 'fullScreen' : ''}`}
|
||||
>
|
||||
<HeaderContainer />
|
||||
<TermsContainer ref_={this.onTermsRef} />
|
||||
{this.props.customInnerChildren}
|
||||
</div>
|
||||
|
||||
<NotificationsContainer />
|
||||
|
||||
{this.props.customChildren}
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.hyper_main {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.hyper_mainRounded {
|
||||
border-radius: 10.5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
|
||||
{/*
|
||||
Add custom CSS to Hyper.
|
||||
We add a scope to the customCSS so that it can get around the weighting applied by styled-jsx
|
||||
*/}
|
||||
<style dangerouslySetInnerHTML={{__html: stylis('#hyper', customCSS)}} />
|
||||
</div>
|
||||
|
||||
<NotificationsContainer />
|
||||
|
||||
{props.customChildren}
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.hyper_main {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.hyper_mainRounded {
|
||||
border-radius: 10.5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
|
||||
{/*
|
||||
Add custom CSS to Hyper.
|
||||
We add a scope to the customCSS so that it can get around the weighting applied by styled-jsx
|
||||
*/}
|
||||
<style dangerouslySetInnerHTML={{__html: stylis('#hyper', customCSS)}} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Hyper.displayName = 'Hyper';
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: HyperState) => {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type {HyperState, HyperDispatch} from '../../typings/hyper';
|
||||
import {dismissNotification} from '../actions/notifications';
|
||||
import {installUpdate} from '../actions/updater';
|
||||
import Notifications from '../components/notifications';
|
||||
import {installUpdate} from '../actions/updater';
|
||||
import {connect} from '../utils/plugins';
|
||||
import {dismissNotification} from '../actions/notifications';
|
||||
import type {HyperState, HyperDispatch} from '../hyper';
|
||||
|
||||
const mapStateToProps = (state: HyperState) => {
|
||||
const {ui} = state;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type {HyperState, HyperDispatch} from '../../typings/hyper';
|
||||
import Terms from '../components/terms';
|
||||
import {connect} from '../utils/plugins';
|
||||
import {
|
||||
resizeSession,
|
||||
sendSessionData,
|
||||
|
|
@ -7,10 +8,10 @@ import {
|
|||
openSearch,
|
||||
closeSearch
|
||||
} from '../actions/sessions';
|
||||
|
||||
import {openContextMenu} from '../actions/ui';
|
||||
import Terms from '../components/terms';
|
||||
import {getRootGroups} from '../selectors';
|
||||
import {connect} from '../utils/plugins';
|
||||
import type {HyperState, HyperDispatch} from '../hyper';
|
||||
|
||||
const mapStateToProps = (state: HyperState) => {
|
||||
const {sessions} = state.sessions;
|
||||
|
|
|
|||
7
lib/ext-modules.d.ts
vendored
Normal file
7
lib/ext-modules.d.ts
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
declare module 'php-escape-shell' {
|
||||
export function php_escapeshellcmd(path: string): string;
|
||||
}
|
||||
|
||||
declare module 'react-deep-force-update' {
|
||||
export default function (...args: any[]): any;
|
||||
}
|
||||
33
typings/hyper.d.ts → lib/hyper.d.ts
vendored
33
typings/hyper.d.ts → lib/hyper.d.ts
vendored
|
|
@ -1,7 +1,5 @@
|
|||
// eslint-disable-next-line eslint-comments/disable-enable-pair
|
||||
/* eslint-disable import/order */
|
||||
import type {Immutable} from 'seamless-immutable';
|
||||
import type Client from '../lib/utils/rpc';
|
||||
import type Client from './utils/rpc';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
@ -49,7 +47,7 @@ export type uiState = Immutable<{
|
|||
activeUid: string | null;
|
||||
activityMarkers: Record<string, boolean>;
|
||||
backgroundColor: string;
|
||||
bell: 'SOUND' | false;
|
||||
bell: string;
|
||||
bellSoundURL: string | null;
|
||||
bellSound: string | null;
|
||||
borderColor: string;
|
||||
|
|
@ -189,10 +187,10 @@ export type HyperActions = (
|
|||
| TabActions
|
||||
) & {effect?: () => void};
|
||||
|
||||
import type configureStore from '../lib/store/configure-store';
|
||||
import type configureStore from './store/configure-store';
|
||||
export type HyperDispatch = ReturnType<typeof configureStore>['dispatch'];
|
||||
|
||||
import type {ReactChild, ReactNode} from 'react';
|
||||
import type {ReactChild} from 'react';
|
||||
type extensionProps = Partial<{
|
||||
customChildren: ReactChild | ReactChild[];
|
||||
customChildrenBefore: ReactChild | ReactChild[];
|
||||
|
|
@ -200,17 +198,17 @@ type extensionProps = Partial<{
|
|||
customInnerChildren: ReactChild | ReactChild[];
|
||||
}>;
|
||||
|
||||
import type {HeaderConnectedProps} from '../lib/containers/header';
|
||||
import type {HeaderConnectedProps} from './containers/header';
|
||||
export type HeaderProps = HeaderConnectedProps & extensionProps;
|
||||
|
||||
import type {HyperConnectedProps} from '../lib/containers/hyper';
|
||||
import type {HyperConnectedProps} from './containers/hyper';
|
||||
export type HyperProps = HyperConnectedProps & extensionProps;
|
||||
|
||||
import type {NotificationsConnectedProps} from '../lib/containers/notifications';
|
||||
import type {NotificationsConnectedProps} from './containers/notifications';
|
||||
export type NotificationsProps = NotificationsConnectedProps & extensionProps;
|
||||
|
||||
import type Terms from '../lib/components/terms';
|
||||
import type {TermsConnectedProps} from '../lib/containers/terms';
|
||||
import type Terms from './components/terms';
|
||||
import type {TermsConnectedProps} from './containers/terms';
|
||||
export type TermsProps = TermsConnectedProps & extensionProps & {ref_: (terms: Terms | null) => void};
|
||||
|
||||
export type StyleSheetProps = {
|
||||
|
|
@ -261,15 +259,18 @@ export type NotificationProps = {
|
|||
userDismissColor?: string;
|
||||
} & extensionProps;
|
||||
|
||||
export type NotificationState = {
|
||||
dismissing: boolean;
|
||||
};
|
||||
|
||||
export type SplitPaneProps = {
|
||||
borderColor: string;
|
||||
direction: 'horizontal' | 'vertical';
|
||||
onResize: (sizes: number[]) => void;
|
||||
onResize: Function;
|
||||
sizes?: Immutable<number[]> | null;
|
||||
children: ReactNode[];
|
||||
};
|
||||
|
||||
import type Term from '../lib/components/term';
|
||||
import type Term from './components/term';
|
||||
|
||||
export type TermGroupOwnProps = {
|
||||
cursorAccentColor?: string;
|
||||
|
|
@ -321,7 +322,7 @@ export type TermGroupOwnProps = {
|
|||
| 'imageSupport'
|
||||
>;
|
||||
|
||||
import type {TermGroupConnectedProps} from '../lib/components/term-group';
|
||||
import type {TermGroupConnectedProps} from './components/term-group';
|
||||
export type TermGroupProps = TermGroupConnectedProps & TermGroupOwnProps;
|
||||
|
||||
export type SearchBoxProps = {
|
||||
|
|
@ -346,7 +347,7 @@ import type {FitAddon} from 'xterm-addon-fit';
|
|||
import type {SearchAddon} from 'xterm-addon-search';
|
||||
export type TermProps = {
|
||||
backgroundColor: string;
|
||||
bell: 'SOUND' | false;
|
||||
bell: string;
|
||||
bellSound: string | null;
|
||||
bellSoundURL: string | null;
|
||||
borderColor: string;
|
||||
|
|
@ -1,25 +1,24 @@
|
|||
import './v8-snapshot-util';
|
||||
import {webFrame} from 'electron';
|
||||
import React from 'react';
|
||||
|
||||
import {createRoot} from 'react-dom/client';
|
||||
import forceUpdate from 'react-deep-force-update';
|
||||
import {Provider} from 'react-redux';
|
||||
import React from 'react';
|
||||
import {render} from 'react-dom';
|
||||
|
||||
import type {configOptions} from '../typings/config';
|
||||
|
||||
import {loadConfig, reloadConfig} from './actions/config';
|
||||
import rpc from './rpc';
|
||||
import init from './actions/index';
|
||||
import {addNotificationMessage} from './actions/notifications';
|
||||
import * as sessionActions from './actions/sessions';
|
||||
import * as termGroupActions from './actions/term-groups';
|
||||
import * as config from './utils/config';
|
||||
import * as plugins from './utils/plugins';
|
||||
import {getBase64FileData} from './utils/file';
|
||||
import * as uiActions from './actions/ui';
|
||||
import * as updaterActions from './actions/updater';
|
||||
import * as sessionActions from './actions/sessions';
|
||||
import * as termGroupActions from './actions/term-groups';
|
||||
import {addNotificationMessage} from './actions/notifications';
|
||||
import {loadConfig, reloadConfig} from './actions/config';
|
||||
import HyperContainer from './containers/hyper';
|
||||
import rpc from './rpc';
|
||||
import configureStore from './store/configure-store';
|
||||
import * as config from './utils/config';
|
||||
import {getBase64FileData} from './utils/file';
|
||||
import * as plugins from './utils/plugins';
|
||||
import type {configOptions} from './config';
|
||||
|
||||
// On Linux, the default zoom was somehow changed with Electron 3 (or maybe 2).
|
||||
// Setting zoom factor to 1.2 brings back the normal default size
|
||||
|
|
@ -233,14 +232,14 @@ rpc.on('leave full screen', () => {
|
|||
store_.dispatch(uiActions.leaveFullScreen());
|
||||
});
|
||||
|
||||
const root = createRoot(document.getElementById('mount')!);
|
||||
|
||||
root.render(
|
||||
const app = render(
|
||||
<Provider store={store_}>
|
||||
<HyperContainer />
|
||||
</Provider>
|
||||
</Provider>,
|
||||
document.getElementById('mount')
|
||||
);
|
||||
|
||||
rpc.on('reload', () => {
|
||||
plugins.reload();
|
||||
forceUpdate(app);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import {combineReducers} from 'redux';
|
||||
import type {Reducer} from 'redux';
|
||||
|
||||
import type {HyperActions, HyperState} from '../../typings/hyper';
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
import ui from './ui';
|
||||
import sessions from './sessions';
|
||||
import termGroups from './term-groups';
|
||||
import ui from './ui';
|
||||
import type {HyperActions, HyperState} from '../hyper';
|
||||
|
||||
export default combineReducers({
|
||||
ui,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Immutable from 'seamless-immutable';
|
||||
|
||||
import {decorateSessionsReducer} from '../utils/plugins';
|
||||
import {
|
||||
SESSION_ADD,
|
||||
SESSION_PTY_EXIT,
|
||||
|
|
@ -11,9 +11,8 @@ import {
|
|||
SESSION_SET_XTERM_TITLE,
|
||||
SESSION_SET_CWD,
|
||||
SESSION_SEARCH
|
||||
} from '../../typings/constants/sessions';
|
||||
import type {sessionState, session, Mutable, ISessionReducer} from '../../typings/hyper';
|
||||
import {decorateSessionsReducer} from '../utils/plugins';
|
||||
} from '../constants/sessions';
|
||||
import type {sessionState, session, Mutable, ISessionReducer} from '../hyper';
|
||||
|
||||
const initialState: sessionState = Immutable<Mutable<sessionState>>({
|
||||
sessions: {},
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import Immutable from 'seamless-immutable';
|
||||
import type {Immutable as ImmutableType} from 'seamless-immutable';
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
import {SESSION_ADD, SESSION_SET_ACTIVE} from '../../typings/constants/sessions';
|
||||
import type {SessionAddAction} from '../../typings/constants/sessions';
|
||||
import {TERM_GROUP_EXIT, TERM_GROUP_RESIZE} from '../../typings/constants/term-groups';
|
||||
import type {ITermGroup, ITermState, ITermGroups, ITermGroupReducer, Mutable} from '../../typings/hyper';
|
||||
import {decorateTermGroupsReducer} from '../utils/plugins';
|
||||
import type {Immutable as ImmutableType} from 'seamless-immutable';
|
||||
import Immutable from 'seamless-immutable';
|
||||
import {TERM_GROUP_EXIT, TERM_GROUP_RESIZE} from '../constants/term-groups';
|
||||
import type {SessionAddAction} from '../constants/sessions';
|
||||
import {SESSION_ADD, SESSION_SET_ACTIVE} from '../constants/sessions';
|
||||
import findBySession from '../utils/term-groups';
|
||||
import {decorateTermGroupsReducer} from '../utils/plugins';
|
||||
import type {ITermGroup, ITermState, ITermGroups, ITermGroupReducer, Mutable} from '../hyper';
|
||||
|
||||
const MIN_SIZE = 0.05;
|
||||
const initialState: ITermState = Immutable<Mutable<ITermState>>({
|
||||
|
|
|
|||
|
|
@ -1,18 +1,7 @@
|
|||
import {release} from 'os';
|
||||
|
||||
import Immutable from 'seamless-immutable';
|
||||
import type {Immutable as ImmutableType} from 'seamless-immutable';
|
||||
|
||||
import {CONFIG_LOAD, CONFIG_RELOAD} from '../../typings/constants/config';
|
||||
import {NOTIFICATION_MESSAGE, NOTIFICATION_DISMISS} from '../../typings/constants/notifications';
|
||||
import {
|
||||
SESSION_ADD,
|
||||
SESSION_RESIZE,
|
||||
SESSION_PTY_DATA,
|
||||
SESSION_PTY_EXIT,
|
||||
SESSION_SET_ACTIVE,
|
||||
SESSION_SET_CWD
|
||||
} from '../../typings/constants/sessions';
|
||||
import Immutable from 'seamless-immutable';
|
||||
import {decorateUIReducer} from '../utils/plugins';
|
||||
import {CONFIG_LOAD, CONFIG_RELOAD} from '../constants/config';
|
||||
import {
|
||||
UI_FONT_SIZE_SET,
|
||||
UI_FONT_SIZE_RESET,
|
||||
|
|
@ -22,10 +11,19 @@ import {
|
|||
UI_WINDOW_GEOMETRY_CHANGED,
|
||||
UI_ENTER_FULLSCREEN,
|
||||
UI_LEAVE_FULLSCREEN
|
||||
} from '../../typings/constants/ui';
|
||||
import {UPDATE_AVAILABLE} from '../../typings/constants/updater';
|
||||
import type {uiState, Mutable, IUiReducer} from '../../typings/hyper';
|
||||
import {decorateUIReducer} from '../utils/plugins';
|
||||
} from '../constants/ui';
|
||||
import {NOTIFICATION_MESSAGE, NOTIFICATION_DISMISS} from '../constants/notifications';
|
||||
import {
|
||||
SESSION_ADD,
|
||||
SESSION_RESIZE,
|
||||
SESSION_PTY_DATA,
|
||||
SESSION_PTY_EXIT,
|
||||
SESSION_SET_ACTIVE,
|
||||
SESSION_SET_CWD
|
||||
} from '../constants/sessions';
|
||||
import {UPDATE_AVAILABLE} from '../constants/updater';
|
||||
import type {uiState, Mutable, IUiReducer} from '../hyper';
|
||||
import {release} from 'os';
|
||||
|
||||
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform) || process.platform === 'win32';
|
||||
|
||||
|
|
@ -219,7 +217,7 @@ const reducer: IUiReducer = (state = initial, action) => {
|
|||
}
|
||||
|
||||
if (allowedBells.has(config.bell)) {
|
||||
ret.bell = (config.bell as any) === 'false' ? false : config.bell;
|
||||
ret.bell = config.bell;
|
||||
}
|
||||
|
||||
if (config.bellSoundURL !== state.bellSoundURL) {
|
||||
|
|
@ -461,7 +459,13 @@ const reducer: IUiReducer = (state = initial, action) => {
|
|||
}
|
||||
}
|
||||
|
||||
if (state.cols !== null && state.rows !== null && (state.rows !== state_.rows || state.cols !== state_.cols)) {
|
||||
if (
|
||||
typeof state.cols !== 'undefined' &&
|
||||
state.cols !== null &&
|
||||
typeof state.rows !== 'undefined' &&
|
||||
state.rows !== null &&
|
||||
(state.rows !== state_.rows || state.cols !== state_.cols)
|
||||
) {
|
||||
state_ = state_.merge({notifications: {resize: true}}, {deep: true});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import RPC from './utils/rpc';
|
||||
|
||||
const rpc = new RPC();
|
||||
|
||||
export default rpc;
|
||||
export default new RPC();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import {createSelector} from 'reselect';
|
||||
|
||||
import type {HyperState} from '../typings/hyper';
|
||||
import type {HyperState} from './hyper';
|
||||
|
||||
const getTermGroups = ({termGroups}: Pick<HyperState, 'termGroups'>) => termGroups.termGroups;
|
||||
export const getRootGroups = createSelector(getTermGroups, (termGroups) =>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,16 @@
|
|||
import {composeWithDevTools} from '@redux-devtools/extension';
|
||||
import {createStore, applyMiddleware} from 'redux';
|
||||
import _thunk from 'redux-thunk';
|
||||
import type {ThunkMiddleware} from 'redux-thunk';
|
||||
|
||||
import type {HyperState, HyperActions} from '../../typings/hyper';
|
||||
import _thunk from 'redux-thunk';
|
||||
import rootReducer from '../reducers/index';
|
||||
import effects from '../utils/effects';
|
||||
import * as plugins from '../utils/plugins';
|
||||
|
||||
import writeMiddleware from './write-middleware';
|
||||
|
||||
import {composeWithDevTools} from 'redux-devtools-extension';
|
||||
import type {HyperState, HyperActions} from '../hyper';
|
||||
const thunk: ThunkMiddleware<HyperState, HyperActions> = _thunk;
|
||||
|
||||
const configureStoreForDevelopment = () => {
|
||||
export default () => {
|
||||
const enhancer = composeWithDevTools(applyMiddleware(thunk, plugins.middleware, thunk, writeMiddleware, effects));
|
||||
|
||||
return createStore(rootReducer, enhancer);
|
||||
};
|
||||
|
||||
export default configureStoreForDevelopment;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
import {createStore, applyMiddleware} from 'redux';
|
||||
import _thunk from 'redux-thunk';
|
||||
import type {ThunkMiddleware} from 'redux-thunk';
|
||||
|
||||
import type {HyperState, HyperActions} from '../../typings/hyper';
|
||||
import _thunk from 'redux-thunk';
|
||||
import rootReducer from '../reducers/index';
|
||||
import effects from '../utils/effects';
|
||||
import * as plugins from '../utils/plugins';
|
||||
|
||||
import writeMiddleware from './write-middleware';
|
||||
|
||||
import type {HyperState, HyperActions} from '../hyper';
|
||||
const thunk: ThunkMiddleware<HyperState, HyperActions> = _thunk;
|
||||
|
||||
const configureStoreForProd = () =>
|
||||
export default () =>
|
||||
createStore(rootReducer, applyMiddleware(thunk, plugins.middleware, thunk, writeMiddleware, effects));
|
||||
|
||||
export default configureStoreForProd;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import configureStoreForDevelopment from './configure-store.dev';
|
||||
import configureStoreForProduction from './configure-store.prod';
|
||||
import configureStoreForDevelopment from './configure-store.dev';
|
||||
|
||||
const configureStore = () => {
|
||||
export default () => {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
return configureStoreForProduction();
|
||||
}
|
||||
|
||||
return configureStoreForDevelopment();
|
||||
};
|
||||
export default configureStore;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import type {Dispatch, Middleware} from 'redux';
|
||||
|
||||
import type {HyperActions, HyperState} from '../../typings/hyper';
|
||||
import type {HyperActions, HyperState} from '../hyper';
|
||||
import terms from '../terms';
|
||||
import type {Dispatch, Middleware} from 'redux';
|
||||
|
||||
// the only side effect we perform from middleware
|
||||
// is to write to the react term instance directly
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import {ipcRenderer} from 'electron';
|
||||
import {require as remoteRequire, getCurrentWindow} from '@electron/remote';
|
||||
// TODO: Should be updates to new async API https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31
|
||||
|
||||
import {ipcRenderer} from './ipc';
|
||||
|
||||
const plugins = remoteRequire('./plugins') as typeof import('../../app/plugins');
|
||||
|
||||
Object.defineProperty(window, 'profileName', {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import type {Dispatch, Middleware} from 'redux';
|
||||
|
||||
import type {HyperActions, HyperState} from '../../typings/hyper';
|
||||
import type {HyperActions, HyperState} from '../hyper';
|
||||
/**
|
||||
* Simple redux middleware that executes
|
||||
* the `effect` field if provided in an action
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
* PR: https://github.com/kevva/executable/pull/10
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import type {Stats} from 'fs';
|
||||
import fs from 'fs';
|
||||
|
||||
export function isExecutable(fileStat: Stats): boolean {
|
||||
if (process.platform === 'win32') {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import electron from 'electron';
|
||||
import type {IpcRendererWithCommands} from '../../common';
|
||||
import type {ExecFileOptions, ExecOptions} from 'child_process';
|
||||
|
||||
import {ipcRenderer} from './ipc';
|
||||
const ipcRenderer = electron.ipcRenderer as IpcRendererWithCommands;
|
||||
|
||||
export function exec(command: string, options: ExecOptions, callback: (..._args: any) => void) {
|
||||
if (typeof options === 'function') {
|
||||
|
|
@ -49,7 +50,7 @@ export function fork() {
|
|||
console.error('Calling fork from renderer is disabled');
|
||||
}
|
||||
|
||||
const IPCChildProcess = {
|
||||
export default {
|
||||
exec,
|
||||
execSync,
|
||||
execFile,
|
||||
|
|
@ -58,5 +59,3 @@ const IPCChildProcess = {
|
|||
spawnSync,
|
||||
fork
|
||||
};
|
||||
|
||||
export default IPCChildProcess;
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
import {ipcRenderer as _ipc} from 'electron';
|
||||
|
||||
import type {IpcRendererWithCommands} from '../../typings/common';
|
||||
|
||||
export const ipcRenderer = _ipc as IpcRendererWithCommands;
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import {clipboard} from 'electron';
|
||||
|
||||
import plist from 'plist';
|
||||
|
||||
const getPath = (platform: string) => {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
// eslint-disable-next-line eslint-comments/disable-enable-pair
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import ChildProcess from 'child_process';
|
||||
import pathModule from 'path';
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import type {ComponentType} from 'react';
|
||||
|
||||
import {require as remoteRequire} from '@electron/remote';
|
||||
// TODO: Should be updates to new async API https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31
|
||||
import ReactDOM from 'react-dom';
|
||||
import {connect as reduxConnect} from 'react-redux';
|
||||
import type {ConnectOptions} from 'react-redux/es/components/connect';
|
||||
import type {Dispatch, Middleware} from 'redux';
|
||||
|
||||
import type {Options} from 'react-redux';
|
||||
import {connect as reduxConnect} from 'react-redux';
|
||||
import {basename} from 'path';
|
||||
|
||||
// patching Module._load
|
||||
// so plugins can `require` them without needing their own version
|
||||
// https://github.com/vercel/hyper/issues/619
|
||||
import type {ComponentType} from 'react';
|
||||
import React, {PureComponent} from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Notification from '../components/notification';
|
||||
import notify from './notify';
|
||||
import type {
|
||||
hyperPlugin,
|
||||
IUiReducer,
|
||||
|
|
@ -26,12 +28,11 @@ import type {
|
|||
TermProps,
|
||||
Assignable,
|
||||
HyperActions
|
||||
} from '../../typings/hyper';
|
||||
import Notification from '../components/notification';
|
||||
|
||||
import IPCChildProcess from './ipc-child-process';
|
||||
import notify from './notify';
|
||||
} from '../hyper';
|
||||
import type {Dispatch, Middleware} from 'redux';
|
||||
import {ObjectTypedKeys} from './object';
|
||||
import IPCChildProcess from './ipc-child-process';
|
||||
import ChildProcess from 'child_process';
|
||||
|
||||
// remote interface to `../plugins`
|
||||
const plugins = remoteRequire('./plugins') as typeof import('../../app/plugins');
|
||||
|
|
@ -165,9 +166,6 @@ export function decorate<P extends Record<string, any>>(
|
|||
};
|
||||
}
|
||||
|
||||
// patching Module._load
|
||||
// so plugins can `require` them without needing their own version
|
||||
// https://github.com/vercel/hyper/issues/619
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const Module = require('module') as typeof import('module') & {_load: Function};
|
||||
const originalLoad = Module._load;
|
||||
|
|
@ -221,10 +219,12 @@ const clearModulesCache = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const pathModule = window.require('path') as typeof import('path');
|
||||
|
||||
const getPluginName = (path: string) => pathModule.basename(path);
|
||||
|
||||
const getPluginVersion = (path: string): string | null => {
|
||||
let version: string | null = null;
|
||||
let version = null;
|
||||
try {
|
||||
version = window.require(pathModule.resolve(path, 'package.json')).version as string;
|
||||
} catch (err) {
|
||||
|
|
@ -269,7 +269,7 @@ const loadModules = () => {
|
|||
const loadedPlugins = plugins.getLoadedPluginVersions().map((plugin: any) => plugin.name);
|
||||
modules = paths.plugins
|
||||
.concat(paths.localPlugins)
|
||||
.filter((plugin) => loadedPlugins.indexOf(pathModule.basename(plugin)) !== -1)
|
||||
.filter((plugin) => loadedPlugins.indexOf(basename(plugin)) !== -1)
|
||||
.map((path) => {
|
||||
let mod: hyperPlugin;
|
||||
const pluginName = getPluginName(path);
|
||||
|
|
@ -460,14 +460,11 @@ export function connect<stateProps extends {}, dispatchProps>(
|
|||
stateFn: (state: HyperState) => stateProps,
|
||||
dispatchFn: (dispatch: HyperDispatch) => dispatchProps,
|
||||
c: null | undefined,
|
||||
d: ConnectOptions = {}
|
||||
d: Options = {}
|
||||
) {
|
||||
return <P extends Record<string, unknown>>(
|
||||
Class: ComponentType<P & stateProps & dispatchProps>,
|
||||
name: keyof typeof connectors
|
||||
) => {
|
||||
return reduxConnect(
|
||||
(state: HyperState) => {
|
||||
return (Class: ComponentType<any>, name: keyof typeof connectors) => {
|
||||
return reduxConnect<stateProps, dispatchProps, any, HyperState>(
|
||||
(state) => {
|
||||
let ret = stateFn(state);
|
||||
connectors[name].state.forEach((fn) => {
|
||||
let ret_;
|
||||
|
|
@ -493,7 +490,7 @@ export function connect<stateProps extends {}, dispatchProps>(
|
|||
});
|
||||
return ret;
|
||||
},
|
||||
(dispatch: HyperDispatch) => {
|
||||
(dispatch) => {
|
||||
let ret = dispatchFn(dispatch);
|
||||
connectors[name].dispatch.forEach((fn) => {
|
||||
let ret_;
|
||||
|
|
@ -524,7 +521,7 @@ export function connect<stateProps extends {}, dispatchProps>(
|
|||
},
|
||||
c,
|
||||
d
|
||||
)(decorate(Class, name) as any) as ComponentType<P>;
|
||||
)(decorate(Class, name));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue