mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-21 21:32:13 +01:00
auto resize terminal width to window size
This commit is contained in:
parent
8a710669ec
commit
879cb03da0
143
src/main.tsx
143
src/main.tsx
@ -18,20 +18,6 @@ function getLineId(line : LineType) : string {
|
|||||||
return sprintf("%s-%s-%s", line.sessionid, line.windowid, line.lineid);
|
return sprintf("%s-%s-%s", line.sessionid, line.windowid, line.lineid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
|
||||||
class LineMeta extends React.Component<{line : LineType}, {}> {
|
|
||||||
render() {
|
|
||||||
let line = this.props.line;
|
|
||||||
return (
|
|
||||||
<div className="meta">
|
|
||||||
<div className="lineid">{line.lineid}</div>
|
|
||||||
<div className="user">{line.userid}</div>
|
|
||||||
<div className="ts">{dayjs(line.ts).format("hh:mm:ss a")}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLineDateStr(ts : number) : string {
|
function getLineDateStr(ts : number) : string {
|
||||||
let lineDate = new Date(ts);
|
let lineDate = new Date(ts);
|
||||||
let nowDate = new Date();
|
let nowDate = new Date();
|
||||||
@ -76,7 +62,7 @@ class LineText extends React.Component<{sw : ScreenWindow, line : LineType}, {}>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType}, {}> {
|
class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width: number}, {}> {
|
||||||
termLoaded : mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
termLoaded : mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -89,7 +75,7 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType}, {}>
|
|||||||
let cmd = model.getCmd(line);
|
let cmd = model.getCmd(line);
|
||||||
if (cmd != null) {
|
if (cmd != null) {
|
||||||
let termElem = document.getElementById("term-" + getLineId(line));
|
let termElem = document.getElementById("term-" + getLineId(line));
|
||||||
cmd.connectElem(termElem, sw.screenId, sw.windowId);
|
cmd.connectElem(termElem, sw.screenId, sw.windowId, this.props.width);
|
||||||
mobx.action(() => this.termLoaded.set(true))();
|
mobx.action(() => this.termLoaded.set(true))();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,6 +167,8 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType}, {}>
|
|||||||
}
|
}
|
||||||
let termLoaded = this.termLoaded.get();
|
let termLoaded = this.termLoaded.get();
|
||||||
let cellHeightPx = 16;
|
let cellHeightPx = 16;
|
||||||
|
let cellWidthPx = 8;
|
||||||
|
let termWidth = Math.max(Math.trunc((this.props.width - 20)/cellWidthPx), 10);
|
||||||
let usedRows = cmd.getUsedRows(sw.screenId, sw.windowId);
|
let usedRows = cmd.getUsedRows(sw.screenId, sw.windowId);
|
||||||
let totalHeight = cellHeightPx * usedRows;
|
let totalHeight = cellHeightPx * usedRows;
|
||||||
let remote = model.getRemote(cmd.remoteId);
|
let remote = model.getRemote(cmd.remoteId);
|
||||||
@ -190,33 +178,36 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType}, {}>
|
|||||||
let termOpts = cmd.getTermOpts();
|
let termOpts = cmd.getTermOpts();
|
||||||
let isFocused = cmd.getIsFocused(sw.screenId, sw.windowId);
|
let isFocused = cmd.getIsFocused(sw.screenId, sw.windowId);
|
||||||
return (
|
return (
|
||||||
<div className="line line-cmd" id={"line-" + getLineId(line)}>
|
<div className={cn("line", "line-cmd", {"focus": isFocused})} id={"line-" + getLineId(line)}>
|
||||||
<div className={cn("avatar",{"num4": lineid.length == 4}, {"num5": lineid.length >= 5}, {"running": running}, {"detached": detached})} onClick={this.doRefresh}>
|
<div className="line-header">
|
||||||
{lineid}
|
<div className={cn("avatar",{"num4": lineid.length == 4}, {"num5": lineid.length >= 5}, {"running": running}, {"detached": detached})} onClick={this.doRefresh}>
|
||||||
</div>
|
{lineid}
|
||||||
<div className="line-content">
|
|
||||||
<div className="meta">
|
|
||||||
<div className="user" style={{display: "none"}}>{line.userid}</div>
|
|
||||||
<div className="ts">{formattedTime}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="meta">
|
<div className="meta-wrap">
|
||||||
<div className="metapart-mono" style={{display: "none"}}>
|
<div className="meta">
|
||||||
{line.cmdid}
|
<div className="user" style={{display: "none"}}>{line.userid}</div>
|
||||||
({termOpts.rows}x{termOpts.cols})
|
<div className="ts">{formattedTime}</div>
|
||||||
|
width={this.props.width}, cellwidth={termWidth}
|
||||||
|
</div>
|
||||||
|
<div className="meta">
|
||||||
|
<div className="metapart-mono" style={{display: "none"}}>
|
||||||
|
{line.cmdid}
|
||||||
|
({termOpts.rows}x{termOpts.cols})
|
||||||
|
</div>
|
||||||
|
{this.renderCmdText(cmd, remote)}
|
||||||
</div>
|
</div>
|
||||||
{this.renderCmdText(cmd, remote)}
|
|
||||||
</div>
|
|
||||||
<div className={cn("terminal-wrapper", {"focus": isFocused})} style={{overflowY: "hidden"}}>
|
|
||||||
<div className="terminal" id={"term-" + getLineId(line)} data-cmdid={line.cmdid} style={{height: totalHeight}}></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={cn("terminal-wrapper", {"focus": isFocused})} style={{overflowY: "hidden"}}>
|
||||||
|
<div className="terminal" id={"term-" + getLineId(line)} data-cmdid={line.cmdid} style={{height: totalHeight}}></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class Line extends React.Component<{sw : ScreenWindow, line : LineType}, {}> {
|
class Line extends React.Component<{sw : ScreenWindow, line : LineType, width : number}, {}> {
|
||||||
render() {
|
render() {
|
||||||
let line = this.props.line;
|
let line = this.props.line;
|
||||||
if (line.linetype == "text") {
|
if (line.linetype == "text") {
|
||||||
@ -350,10 +341,12 @@ class CmdInput extends React.Component<{}, {}> {
|
|||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
||||||
mutObs : any;
|
mutObs : any;
|
||||||
|
rszObs : any
|
||||||
randomId : string;
|
randomId : string;
|
||||||
|
width : mobx.IObservableValue<number> = mobx.observable.box(0);
|
||||||
|
|
||||||
scrollToBottom(reason : string) {
|
scrollToBottom(reason : string) {
|
||||||
let elem = document.getElementById(this.getLinesId());
|
let elem = document.getElementById(this.getLinesDOMId());
|
||||||
if (elem == null) {
|
if (elem == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -374,23 +367,45 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let elem = document.getElementById(this.getLinesId());
|
let elem = document.getElementById(this.getLinesDOMId());
|
||||||
if (elem == null) {
|
if (elem != null) {
|
||||||
return;
|
this.mutObs = new MutationObserver(this.handleDomMutation.bind(this));
|
||||||
|
this.mutObs.observe(elem, {childList: true});
|
||||||
|
elem.addEventListener("termresize", this.handleTermResize);
|
||||||
|
let {sw} = this.props;
|
||||||
|
if (sw && sw.shouldFollow.get()) {
|
||||||
|
setTimeout(() => this.scrollToBottom("mount"), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.mutObs = new MutationObserver(this.handleDomMutation.bind(this));
|
let wvElem = document.getElementById(this.getWindowViewDOMId());
|
||||||
this.mutObs.observe(elem, {childList: true});
|
if (wvElem != null) {
|
||||||
elem.addEventListener("termresize", this.handleTermResize);
|
this.rszObs = new ResizeObserver(this.handleResize.bind(this));
|
||||||
let {sw} = this.props;
|
this.rszObs.observe(wvElem);
|
||||||
if (sw && sw.shouldFollow.get()) {
|
|
||||||
setTimeout(() => this.scrollToBottom("mount"), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateWidth(width : number) {
|
||||||
|
mobx.action(() => {
|
||||||
|
this.width.set(width);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if (this.mutObs) {
|
if (this.mutObs) {
|
||||||
this.mutObs.disconnect();
|
this.mutObs.disconnect();
|
||||||
}
|
}
|
||||||
|
if (this.rszObs) {
|
||||||
|
this.rszObs.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleResize(entries : any) {
|
||||||
|
if (entries.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let entry = entries[0];
|
||||||
|
let width = entry.target.offsetWidth;
|
||||||
|
this.updateWidth(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDomMutation(mutations, mutObs) {
|
handleDomMutation(mutations, mutObs) {
|
||||||
@ -405,15 +420,8 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
|||||||
return GlobalModel.getWindowById(sw.sessionId, sw.windowId);
|
return GlobalModel.getWindowById(sw.sessionId, sw.windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLinesId() {
|
getLinesDOMId() {
|
||||||
let {sw} = this.props;
|
return "window-lines-" + this.getWindowId();
|
||||||
if (sw == null) {
|
|
||||||
if (!this.randomId) {
|
|
||||||
this.randomId = uuidv4();
|
|
||||||
}
|
|
||||||
return "window-lines-" + this.randomId;
|
|
||||||
}
|
|
||||||
return "window-lines-" + sw.windowId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
@ -425,19 +433,35 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getWindowViewStyle() : any {
|
getWindowViewStyle() : any {
|
||||||
return {width: "100%", height: "100%"};
|
// return {width: "100%", height: "100%"};
|
||||||
|
return {position: "absolute", width: "100%", height: "100%", overflowX: "hidden"};
|
||||||
|
}
|
||||||
|
|
||||||
|
getWindowId() : string {
|
||||||
|
let {sw} = this.props;
|
||||||
|
if (sw == null) {
|
||||||
|
if (!this.randomId) {
|
||||||
|
this.randomId = uuidv4();
|
||||||
|
}
|
||||||
|
return this.randomId;
|
||||||
|
}
|
||||||
|
return sw.windowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWindowViewDOMId() {
|
||||||
|
return sprintf("window-view-%s", this.getWindowId());
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError(message : string) {
|
renderError(message : string) {
|
||||||
let {sw} = this.props;
|
let {sw} = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="window-view" style={this.getWindowViewStyle()}>
|
<div className="window-view" style={this.getWindowViewStyle()} id={this.getWindowViewDOMId()}>
|
||||||
<div key="window-tag" className="window-tag">
|
<div key="window-tag" className="window-tag">
|
||||||
<If condition={sw != null}>
|
<If condition={sw != null}>
|
||||||
<span>{sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}</span>
|
<span>{sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}</span>
|
||||||
</If>
|
</If>
|
||||||
</div>
|
</div>
|
||||||
<div key="lines" className="lines" id={this.getLinesId()}></div>
|
<div key="lines" className="lines" id={this.getLinesDOMId()}></div>
|
||||||
<div key="window-empty" className="window-empty">
|
<div key="window-empty" className="window-empty">
|
||||||
<div>{message}</div>
|
<div>{message}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -457,6 +481,9 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
|||||||
if (!win.linesLoaded.get()) {
|
if (!win.linesLoaded.get()) {
|
||||||
return this.renderError("(loading)");
|
return this.renderError("(loading)");
|
||||||
}
|
}
|
||||||
|
if (this.width.get() == 0) {
|
||||||
|
return this.renderError("");
|
||||||
|
}
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
let line : LineType = null;
|
let line : LineType = null;
|
||||||
let screen = GlobalModel.getScreenById(sw.sessionId, sw.screenId);
|
let screen = GlobalModel.getScreenById(sw.sessionId, sw.screenId);
|
||||||
@ -466,13 +493,13 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
|
|||||||
linesStyle.display = "none";
|
linesStyle.display = "none";
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="window-view" style={this.getWindowViewStyle()}>
|
<div className="window-view" style={this.getWindowViewStyle()} id={this.getWindowViewDOMId()}>
|
||||||
<div key="window-tag" className="window-tag">
|
<div key="window-tag" className="window-tag">
|
||||||
<span>{sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}</span>
|
<span>{sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}</span>
|
||||||
</div>
|
</div>
|
||||||
<div key="lines" className="lines" onScroll={this.scrollHandler} id={this.getLinesId()} style={linesStyle}>
|
<div key="lines" className="lines" onScroll={this.scrollHandler} id={this.getLinesDOMId()} style={linesStyle}>
|
||||||
<For each="line" of={win.lines} index="idx">
|
<For each="line" of={win.lines} index="idx">
|
||||||
<Line key={line.lineid} line={line} sw={sw}/>
|
<Line key={line.lineid} line={line} sw={sw} width={this.width.get()}/>
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
<If condition={win.lines.length == 0}>
|
<If condition={win.lines.length == 0}>
|
||||||
|
@ -49,13 +49,13 @@ class Cmd {
|
|||||||
this.data = mobx.observable.box(cmd, {deep: false});
|
this.data = mobx.observable.box(cmd, {deep: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
connectElem(elem : Element, screenId : string, windowId : string) {
|
connectElem(elem : Element, screenId : string, windowId : string, width : number) {
|
||||||
let termWrap = this.getTermWrap(screenId, windowId);
|
let termWrap = this.getTermWrap(screenId, windowId);
|
||||||
if (termWrap != null) {
|
if (termWrap != null) {
|
||||||
console.log("term-wrap already exists for", screenId, windowId);
|
console.log("term-wrap already exists for", screenId, windowId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
termWrap = new TermWrap(elem, this.sessionId, this.cmdId, 0, this.getTermOpts(), this.handleKey.bind(this));
|
termWrap = new TermWrap(elem, this.sessionId, this.cmdId, 0, this.getTermOpts(), {height: 0, width: width}, this.handleKey.bind(this));
|
||||||
this.instances[screenId + "/" + windowId] = termWrap;
|
this.instances[screenId + "/" + windowId] = termWrap;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
159
src/sh2.less
159
src/sh2.less
@ -17,6 +17,7 @@ html, body, #main {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
min-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.screen-tabs {
|
.screen-tabs {
|
||||||
@ -25,6 +26,7 @@ html, body, #main {
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
border-top: 1px solid #eee;
|
border-top: 1px solid #eee;
|
||||||
border-right: 1px solid #eee;
|
border-right: 1px solid #eee;
|
||||||
|
overflow: scroll;
|
||||||
|
|
||||||
.screen-tab {
|
.screen-tab {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
@ -71,6 +73,7 @@ html, body, #main {
|
|||||||
.screen-view {
|
.screen-view {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
border-right: 1px solid #ccc;
|
border-right: 1px solid #ccc;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-view {
|
.window-view {
|
||||||
@ -143,6 +146,7 @@ html, body, #main {
|
|||||||
color: #ddd;
|
color: #ddd;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: darken(rgb(0, 177, 10), 30%);
|
background-color: darken(rgb(0, 177, 10), 30%);
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
@ -274,9 +278,57 @@ html, body, #main {
|
|||||||
|
|
||||||
.line.line-text {
|
.line.line-text {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
|
.line-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.line.line-cmd {
|
.line.line-cmd {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.meta-wrap {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.focus {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-wrapper {
|
||||||
|
background-color: #000;
|
||||||
|
padding: 2px 10px 5px 4px;
|
||||||
|
margin-left: -4px;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
align-self: flex-start;
|
||||||
|
|
||||||
|
&.focus {
|
||||||
|
/* box-shadow: -8px 0 12px -5px #aaa; */
|
||||||
|
/* box-shadow: 0 0 0 4px hsl(0, 0%, 20%);*/
|
||||||
|
/* filter:drop-shadow(3px 3px 10px #555); */
|
||||||
|
box-shadow: 0 0 4px 4px rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.line {
|
.line {
|
||||||
@ -285,6 +337,8 @@ html, body, #main {
|
|||||||
display: flex;
|
display: flex;
|
||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
border-top: 1px solid #777;
|
border-top: 1px solid #777;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin: 0px 5px 5px 5px;
|
margin: 0px 5px 5px 5px;
|
||||||
@ -302,7 +356,7 @@ html, body, #main {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
margin-right: 15px;
|
margin-right: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
&.num4 {
|
&.num4 {
|
||||||
@ -323,67 +377,40 @@ html, body, #main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.line-cmd .avatar {
|
.meta {
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-content {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
flex-grow: 1;
|
font-size: 1rem;
|
||||||
|
margin-top: -4px;
|
||||||
.meta {
|
|
||||||
display: flex;
|
.user {
|
||||||
flex-direction: row;
|
color: lighten(#729fcf, 10%);
|
||||||
font-size: 1rem;
|
font-weight: bold;
|
||||||
margin-top: -4px;
|
margin-top: 1px;
|
||||||
|
margin-right: 10px;
|
||||||
.user {
|
|
||||||
color: lighten(#729fcf, 10%);
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 1px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ts {
|
|
||||||
color: #ddd;
|
|
||||||
margin-top: 5px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metapart-mono {
|
|
||||||
color: #ddd;
|
|
||||||
margin-left: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-top: 4px;
|
|
||||||
font-family: 'JetBrains Mono', monospace;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmdtext {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.ts {
|
||||||
font-size: 1rem;
|
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
|
margin-top: 5px;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.metapart-mono {
|
||||||
.terminal-wrapper {
|
color: #ddd;
|
||||||
background-color: #000;
|
margin-left: 8px;
|
||||||
padding: 5px 15px 5px 5px;
|
font-size: 14px;
|
||||||
margin-right: 8px;
|
margin-top: 4px;
|
||||||
margin-top: 2px;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
align-self: flex-start;
|
font-weight: 400;
|
||||||
|
}
|
||||||
&.focus {
|
|
||||||
box-shadow: -8px 0 12px -5px #aaa;
|
.cmdtext {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -401,22 +428,6 @@ body .xterm .xterm-viewport {
|
|||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line.line-cmd {
|
|
||||||
.refresh-button {
|
|
||||||
cursor: pointer;
|
|
||||||
border-color: #777;
|
|
||||||
color: #777;
|
|
||||||
margin-right: 10px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #fff;
|
|
||||||
.icon i {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.line.line-invalid {
|
.line.line-invalid {
|
||||||
color: #000;
|
color: #000;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
17
src/term.ts
17
src/term.ts
@ -24,6 +24,14 @@ type DataUpdate = {
|
|||||||
pos : number,
|
pos : number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WindowSize = {
|
||||||
|
height : number,
|
||||||
|
width: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
const DefaultCellWidth = 8;
|
||||||
|
const DefaultCellHeight = 16;
|
||||||
|
|
||||||
// cmd-instance
|
// cmd-instance
|
||||||
class TermWrap {
|
class TermWrap {
|
||||||
terminal : any;
|
terminal : any;
|
||||||
@ -39,7 +47,7 @@ class TermWrap {
|
|||||||
dataUpdates : DataUpdate[] = [];
|
dataUpdates : DataUpdate[] = [];
|
||||||
loadError : mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
loadError : mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
||||||
|
|
||||||
constructor(elem : Element, sessionId : string, cmdId : string, usedRows : number, termOpts : TermOptsType, keyHandler : (event : any) => void) {
|
constructor(elem : Element, sessionId : string, cmdId : string, usedRows : number, termOpts : TermOptsType, winSize : WindowSize, keyHandler : (event : any) => void) {
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.cmdId = cmdId;
|
this.cmdId = cmdId;
|
||||||
this.connectedElem = elem;
|
this.connectedElem = elem;
|
||||||
@ -52,7 +60,12 @@ class TermWrap {
|
|||||||
this.atRowMax = true;
|
this.atRowMax = true;
|
||||||
this.usedRows = mobx.observable.box(termOpts.rows);
|
this.usedRows = mobx.observable.box(termOpts.rows);
|
||||||
}
|
}
|
||||||
this.terminal = new Terminal({rows: termOpts.rows, cols: termOpts.cols, fontSize: 14, theme: {foreground: "#d3d7cf"}});
|
let cols = termOpts.cols;
|
||||||
|
let maxCols = Math.trunc((winSize.width - 25) / DefaultCellWidth);
|
||||||
|
if (maxCols > cols) {
|
||||||
|
cols = maxCols;
|
||||||
|
}
|
||||||
|
this.terminal = new Terminal({rows: termOpts.rows, cols: maxCols, fontSize: 14, theme: {foreground: "#d3d7cf"}});
|
||||||
this.terminal.open(elem);
|
this.terminal.open(elem);
|
||||||
if (keyHandler != null) {
|
if (keyHandler != null) {
|
||||||
this.terminal.onKey(keyHandler);
|
this.terminal.onKey(keyHandler);
|
||||||
|
Loading…
Reference in New Issue
Block a user