From 9027edc0e1977a760fa034b6b12950a86115cd66 Mon Sep 17 00:00:00 2001 From: sawka Date: Fri, 28 Oct 2022 14:17:45 -0700 Subject: [PATCH] disconnected modal --- src/main.tsx | 146 ++++++++++++++++++++------------------------------- src/model.ts | 6 +-- src/sh2.less | 45 ++++++++-------- src/ws.ts | 72 ++++++++++++++++--------- 4 files changed, 128 insertions(+), 141 deletions(-) diff --git a/src/main.tsx b/src/main.tsx index ac2110a46..2464631bb 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2488,113 +2488,82 @@ function sortAndFilterRemotes(origRemotes : RemoteType[]) : RemoteType[] { } @mobxReact.observer -class AddRemoteModal extends React.Component<{}, {}> { - @boundMethod - handleModalClose() : void { - mobx.action(() => { - GlobalModel.addRemoteModalOpen.set(false); - })(); - } +class DisconnectedModal extends React.Component<{}, {}> { + logRef : any = React.createRef(); + showLog : mobx.IObservableValue = mobx.observable.box(false) - render() { - return ( -
-
-
-
-

Add Remote

-
-
- hello -
-
- -
- -
-
-
- ); - } -} - -@mobxReact.observer -class RemoteModal extends React.Component<{}, {}> { @boundMethod - handleModalClose() : void { - mobx.action(() => { - GlobalModel.remotesModalOpen.set(false); - })(); + restartServer() { } @boundMethod - handleAddRemote() : void { + tryReconnect() { + GlobalModel.ws.connectNow("manual"); + } + + componentDidMount() { + if (this.logRef.current != null) { + this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + } + } + + componentDidUpdate() { + if (this.logRef.current != null) { + this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + } + } + + @boundMethod + handleShowLog() : void { mobx.action(() => { - GlobalModel.addRemoteModalOpen.set(true); + this.showLog.set(!this.showLog.get()); })(); } render() { let model = GlobalModel; - let remotes = sortAndFilterRemotes(model.remotes); - let remote : RemoteType = null; + let logLine : string = null; + let idx : number = 0; return ( -
-
+
+
-

Remotes

+

ScriptHaus Client Disconnected

-
- - - - - - - - - - - - - - - - - + +
+
+ +
{logLine}
-
-
StatusAliasUser@HostConnect
-
-
- {remote.remotealias} - - - - - - {remote.remotecanonicalname} - - {remote.connectmode} -
-
+
+
+
- + -
-
- ); } @@ -2617,11 +2586,8 @@ class Main extends React.Component<{}, {}> { - - - - - + + ); diff --git a/src/model.ts b/src/model.ts index 784ed3dc3..986a1aa76 100644 --- a/src/model.ts +++ b/src/model.ts @@ -1525,8 +1525,6 @@ class Model { windows : OMap = mobx.observable.map({}, {name: "windows", deep: false}); // key = "sessionid/windowid" inputModel : InputModel; termUsedRowsCache : Record = {}; - remotesModalOpen : OV = mobx.observable.box(false); - addRemoteModalOpen : OV = mobx.observable.box(false); debugCmds : number = 0; debugSW : OV = mobx.observable.box(false); @@ -1653,7 +1651,7 @@ class Model { } cmdStatusUpdate(sessionId : string, cmdId : string, origStatus : string, newStatus : string) { - console.log("cmd status", sessionId, cmdId, origStatus, "=>", newStatus); + // console.log("cmd status", sessionId, cmdId, origStatus, "=>", newStatus); let lines = this.getActiveLinesByCmdId(sessionId, cmdId); for (let ptr of lines) { let sw = ptr.sw; @@ -2290,7 +2288,7 @@ function cmdPacketString(pk : FeCmdPacketType) : string { let GlobalModel : Model = null; let GlobalCommandRunner : CommandRunner = null; -if ((window as any).GlobalModal == null) { +if ((window as any).GlobalModel == null) { (window as any).GlobalModel = new Model(); (window as any).GlobalCommandRunner = new CommandRunner(); } diff --git a/src/sh2.less b/src/sh2.less index e8ea02c9b..2cf582f50 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -1330,9 +1330,11 @@ input[type=checkbox] { .sc-modal { .modal-content { padding: 10px; + background-color: #666; .message-header { - font-size: 20px; + .mono-font(); + font-size: 16px; margin-bottom: 10px; } @@ -1342,43 +1344,44 @@ input[type=checkbox] { overflow-y: auto; display: flex; flex-direction: column; + margin-bottom: 10px; } .message-footer { border-top: 1px solid #666; - padding-top: 15px; display: flex; flex-direction: row; justify-content: center; + align-items: center; .spacer { flex-grow: 1; } + + .footer-text-link { + .mono-font(12px); + color: @term-white; + cursor: pointer; + } + } + + .button { + .mono-font(); } } } -.remote-modal { +.disconnected-modal { .message-content { - .table { - th.status-header { - width: 40px; - } + .ws-log { + padding: 5px; + background-color: black; + height: 250px; + overflow: auto; - tbody td { - vertical-align: middle; - } - - .status-cell { - .remote-status { - font-size: 16px; - top: 0; - margin-right: 0; - } - - .status-text { - font-size: 12px; - } + .ws-logline { + .mono-font(12px); + color: @term-white; } } } diff --git a/src/ws.ts b/src/ws.ts index f352ce800..d7953fea4 100644 --- a/src/ws.ts +++ b/src/ws.ts @@ -2,6 +2,7 @@ import * as mobx from "mobx"; import {sprintf} from "sprintf-js"; import {boundMethod} from "autobind-decorator"; import {WatchScreenPacketType} from "./types"; +import dayjs from "dayjs"; class WSControl { wsConn : any; @@ -13,6 +14,7 @@ class WSControl { messageCallback : (any) => void = null; watchSessionId : string = null; watchScreenId : string = null; + wsLog : mobx.IObservableArray = mobx.observable.array([], {name: "wsLog"}) constructor(clientId : string, messageCallback : (any) => void) { this.messageCallback = messageCallback; @@ -21,19 +23,47 @@ class WSControl { setInterval(this.sendPing, 5000); } - @mobx.action - setOpen(val : boolean) { - this.open.set(val); + log(str : string) { + mobx.action(() => { + let ts = dayjs().format("YYYY-MM-DD HH:mm:ss"); + this.wsLog.push("[" + ts + "] " + str); + if (this.wsLog.length > 50) { + this.wsLog.splice(0, this.wsLog.length-50); + } + })(); } - reconnect() { + @mobx.action + setOpen(val : boolean) { + mobx.action(() => { + this.open.set(val); + })(); + } + + connectNow(desc : string) { if (this.open.get()) { - this.wsConn.close(); // this will force a reconnect + return; + } + this.log(sprintf("try reconnect (%s)", desc)); + this.opening = true; + this.wsConn = new WebSocket("ws://localhost:8081/ws?clientid=" + this.clientId); + this.wsConn.onopen = this.onopen; + this.wsConn.onmessage = this.onmessage; + this.wsConn.onclose = this.onclose; + // turns out onerror is not necessary (onclose always follows onerror) + // this.wsConn.onerror = this.onerror; + } + + reconnect(forceClose? : boolean) { + if (this.open.get()) { + if (forceClose) { + this.wsConn.close(); // this will force a reconnect + } return; } this.reconnectTimes++; if (this.reconnectTimes > 20) { - console.log("websocket cannot connect, giving up"); + this.log("cannot connect, giving up"); return; } let timeoutArr = [0, 0, 2, 5, 10, 10, 30, 60]; @@ -42,32 +72,22 @@ class WSControl { timeout = timeoutArr[this.reconnectTimes]; } if (timeout > 0) { - console.log(sprintf("websocket reconnect(%d), sleep %ds", this.reconnectTimes, timeout)); + this.log(sprintf("sleeping %ds", timeout)); } setTimeout(() => { - console.log(sprintf("websocket reconnect(%d)", this.reconnectTimes)); - this.opening = true; - this.wsConn = new WebSocket("ws://localhost:8081/ws?clientid=" + this.clientId); - this.wsConn.onopen = this.onopen; - this.wsConn.onmessage = this.onmessage; - this.wsConn.onerror = this.onerror; - this.wsConn.onclose = this.onclose; + this.connectNow(String(this.reconnectTimes)); }, timeout*1000); } - @boundMethod - onerror(event : any) { - console.log("websocket error", event); - if (this.open.get() || this.opening) { - this.setOpen(false); - this.opening = false; - this.reconnect(); - } - } - @boundMethod onclose(event : any) { - console.log("websocket closed", event); + console.log("close", event); + if (event.wasClean) { + this.log("connection closed"); + } + else { + this.log("connection error/disconnected"); + } if (this.open.get() || this.opening) { this.setOpen(false); this.opening = false; @@ -77,7 +97,7 @@ class WSControl { @boundMethod onopen() { - console.log("websocket open"); + this.log("connection open"); this.setOpen(true); this.opening = false; this.runMsgQueue();