diff --git a/spug_web/package.json b/spug_web/package.json index 1c0b6f4..229e9da 100644 --- a/spug_web/package.json +++ b/spug_web/package.json @@ -5,7 +5,7 @@ "dependencies": { "@ant-design/icons": "^4.3.0", "ace-builds": "^1.4.13", - "antd": "^4.10.3", + "antd": "^4.19.2", "axios": "^0.21.0", "bizcharts": "^3.5.9", "history": "^4.10.1", diff --git a/spug_web/src/pages/ssh/Terminal.js b/spug_web/src/pages/ssh/Terminal.js index 7757b6a..0069632 100644 --- a/spug_web/src/pages/ssh/Terminal.js +++ b/spug_web/src/pages/ssh/Terminal.js @@ -3,7 +3,7 @@ * Copyright (c) * Released under the AGPL-3.0 License. */ -import React, { useEffect, useState, useRef } from 'react'; +import React, { useEffect, useState, useRef, useLayoutEffect } from 'react'; import { Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; import { X_TOKEN } from 'libs'; @@ -14,9 +14,9 @@ import styles from './index.module.less'; function WebSSH(props) { const container = useRef(); const [term] = useState(new Terminal()); + const [fitPlugin] = useState(new FitAddon()); useEffect(() => { - const fitPlugin = new FitAddon(); term.loadAddon(fitPlugin); term.setOption('fontFamily', 'Source Code Pro, Courier New, Courier, Monaco, monospace, PingFang SC, Microsoft YaHei') term.open(container.current); @@ -33,12 +33,15 @@ function WebSSH(props) { setTimeout(() => term.write('\r\nConnection is closed.\r\n'), 200) }; term.onData(data => socket.send(JSON.stringify({data}))); - term.onResize(({cols, rows}) => socket.send(JSON.stringify({resize: [cols, rows]}))); - const resize = () => fitPlugin.fit(); - window.addEventListener('resize', resize) + term.onResize(({cols, rows}) => { + if (socket.readyState === 1) { + socket.send(JSON.stringify({resize: [cols, rows]})) + } + }); + window.addEventListener('resize', fitTerminal) return () => { - window.removeEventListener('resize', resize); + window.removeEventListener('resize', fitTerminal); if (socket) socket.close() } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -51,6 +54,19 @@ function WebSSH(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.activeId]) + useLayoutEffect(fitTerminal) + + function fitTerminal() { + if (props.vId === props.activeId) { + const dims = fitPlugin.proposeDimensions(); + if (!dims || !term || !dims.cols || !dims.rows) return; + if (term.rows !== dims.rows || term.cols !== dims.cols) { + term._core._renderService.clear(); + term.resize(dims.cols, dims.rows); + } + } + } + function _read_as_text(data) { const reader = new window.FileReader(); reader.onload = () => term.write(reader.result); diff --git a/spug_web/src/pages/ssh/index.js b/spug_web/src/pages/ssh/index.js index 440276c..57731e5 100644 --- a/spug_web/src/pages/ssh/index.js +++ b/spug_web/src/pages/ssh/index.js @@ -6,7 +6,13 @@ import React, { useEffect, useState } from 'react'; import { observer } from 'mobx-react'; import { Tabs, Tree, Input, Spin, Button } from 'antd'; -import { FolderOutlined, FolderOpenOutlined, CloudServerOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons'; +import { + FolderOutlined, + FolderOpenOutlined, + CloudServerOutlined, + SearchOutlined, + SyncOutlined +} from '@ant-design/icons'; import { NotFound, AuthButton } from 'components'; import Terminal from './Terminal'; import FileManager from './FileManager'; @@ -15,6 +21,7 @@ import styles from './index.module.less'; import LogoSpugText from 'layout/logo-spug-txt.png'; import lds from 'lodash'; +let posX = 0 function WebSSH(props) { const [visible, setVisible] = useState(false); @@ -26,6 +33,7 @@ function WebSSH(props) { const [hosts, setHosts] = useState([]); const [activeId, setActiveId] = useState(); const [hostId, setHostId] = useState(); + const [width, setWidth] = useState(280); useEffect(() => { window.document.title = 'Spug web terminal' @@ -125,6 +133,12 @@ function WebSSH(props) { } } + function handleMouseMove(e) { + if (posX) { + setWidth(e.pageX); + } + } + const spug_web_terminal = ' __ __ _ __\n' + ' _____ ____ __ __ ____ _ _ __ ___ / /_ / /_ ___ _____ ____ ___ (_)____ ____ _ / /\n' + @@ -134,8 +148,8 @@ function WebSSH(props) { ' /_/ /____/ \n' return hasPermission('host.console.view') ? ( -
-
+
posX = 0} onMouseMove={handleMouseMove}> +
logo
@@ -152,6 +166,7 @@ function WebSSH(props) { onSelect={(k, e) => handleSelect(e)}/>
+
posX = e.pageX}/>
setActiveId(key)} onEdit={handleRemove} + style={{width: `calc(100vw - ${width}px)`}} tabBarExtraContent={