= 5}, {"running": running})}>
+
= 5}, {"running": running}, {"detached": detached})}>
{lineid}
@@ -353,7 +356,6 @@ class SessionView extends React.Component<{session : Session}, {}> {
@boundMethod
changeSizeCallback(term : TermWrap) {
- console.log("changesize", term);
if (this.shouldFollow.get()) {
let session = this.props.session;
let window = session.getActiveWindow();
diff --git a/src/session.ts b/src/session.ts
index 83e427e2..3dca4c57 100644
--- a/src/session.ts
+++ b/src/session.ts
@@ -318,13 +318,19 @@ class Session {
}
getTermWrapByLine(line : LineType) : TermWrap {
+ if (!line.cmdid) {
+ return null;
+ }
let termKey = makeTermKey(line.sessionid, line.cmdid, line.windowid, line.lineid);
let termWrap = this.termMap[termKey];
if (termWrap != null) {
return termWrap;
}
- termWrap = new TermWrap(line.sessionid, line.cmdid);
- console.log("create term", termWrap);
+ let cmd = this.getCmd(line.cmdid);
+ if (!cmd) {
+ return null;
+ }
+ termWrap = new TermWrap(line.sessionid, line.cmdid, cmd.status);
this.termMap[termKey] = termWrap;
this.termMapById[termWrap.termId] = termWrap;
termWrap.initialized = true;
diff --git a/src/sh2.less b/src/sh2.less
index 617f6645..dbcf7605 100644
--- a/src/sh2.less
+++ b/src/sh2.less
@@ -203,7 +203,7 @@ html, body, #main {
.avatar {
height: 38px;
width: 38px;
- background-color: #729fcf;
+ background-color: #555;
display: flex;
align-items: center;
justify-content: center;
@@ -222,7 +222,12 @@ html, body, #main {
}
&.running {
- background-color: #cc0000;
+ background-color: #729fcf;
+ }
+
+ &.detached {
+ background-color: #729fcf;
+ outline: 2px solid white;
}
}
diff --git a/src/term.ts b/src/term.ts
index ef7a4c6e..90e8f95c 100644
--- a/src/term.ts
+++ b/src/term.ts
@@ -34,41 +34,79 @@ class TermWrap {
initialized : boolean = false;
changeSizeCallback : (TermWrap) => void = null;
usedRows : number;
+ tailReqId : string;
+ cmdStatus : string;
- constructor(sessionId : string, cmdId : string) {
+ constructor(sessionId : string, cmdId : string, status : string) {
this.termId = uuidv4();
this.sessionId = sessionId;
this.cmdId = cmdId;
+ this.cmdStatus = status;
this.terminal = new Terminal({rows: 25, cols: 80, theme: {foreground: "#d3d7cf"}});
this.usedRows = 2;
}
destroy() {
-
+ this.stopPtyTail();
+ }
+
+ setCmdStatus(status : string) {
+ if (this.cmdStatus == status) {
+ return;
+ }
+ this.cmdStatus = status;
+ if (!this.canTailPty() && this.tailReqId) {
+ this.stopPtyTail();
+ }
+ }
+
+ canTailPty() : boolean {
+ return this.cmdStatus == "running" || this.cmdStatus == "detached";
}
@boundMethod
onKeyHandler(event : any) {
let inputPacket = {
type: "input",
- sessionid: this.sessionId,
- cmdid: this.cmdId,
+ ck: this.sessionId + "/" + this.cmdId,
inputdata: event.key,
};
GlobalWS.pushMessage(inputPacket);
}
+ stopPtyTail() {
+ if (this.tailReqId == null) {
+ return;
+ }
+ let untailCmdPacket = {
+ type: "untailcmd",
+ reqid: uuidv4(),
+ ck: this.sessionId + "/" + this.cmdId,
+ };
+ GlobalWS.sendMessage(untailCmdPacket);
+ GlobalWS.unregisterReq(this.tailReqId);
+ this.tailReqId = null;
+ }
+
startPtyTail() {
+ if (this.tailReqId != null) {
+ return;
+ }
+ if (!this.canTailPty()) {
+ return;
+ }
+ this.tailReqId = uuidv4();
let getCmdPacket = {
type: "getcmd",
- reqid: this.termId,
- sessionid: this.sessionId,
- cmdid: this.cmdId,
+ reqid: this.tailReqId,
+ ck: this.sessionId + "/" + this.cmdId,
ptypos: this.ptyPos,
tail: true,
+ ptyonly: true,
};
GlobalWS.registerAndSendGetCmd(getCmdPacket, (dataPacket) => {
- this.updatePtyData(this.ptyPos, dataPacket.ptydata, dataPacket.ptydatalen);
+ let realData = atob(dataPacket.ptydata64);
+ this.updatePtyData(this.ptyPos, realData, dataPacket.ptydatalen);
});
}
@@ -109,7 +147,13 @@ class TermWrap {
usedRows = i+1;
}
}
- this.usedRows = usedRows;
+ if (this.usedRows != usedRows) {
+ this.usedRows = usedRows;
+ if (this.changeSizeCallback != null) {
+ let cb = this.changeSizeCallback;
+ setTimeout(() => cb(this), 0);
+ }
+ }
return;
}
diff --git a/src/ws.ts b/src/ws.ts
index cf1bda2e..f0d2f4e3 100644
--- a/src/ws.ts
+++ b/src/ws.ts
@@ -29,6 +29,10 @@ class WSControl {
this.pushMessage(pk)
}
+ unregisterReq(reqid : string) {
+ delete this.reqMap[reqid];
+ }
+
reconnect() {
if (this.open.get()) {
this.wsConn.close();
@@ -123,9 +127,9 @@ class WSControl {
return;
}
if (eventData.type == "cmddata") {
- let cb = this.reqMap[eventData.reqid];
+ let cb = this.reqMap[eventData.respid];
if (!cb) {
- console.log(sprintf("websocket cmddata req=%s -- no callback", eventData.reqid));
+ console.log(sprintf("websocket cmddata req=%s -- no callback", eventData.respid));
return;
}
cb(eventData);