From b2a1bb3818f0ddc2cacc23ecac38954e867e0928 Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Fri, 5 Jan 2024 02:13:40 +0800 Subject: [PATCH] When client is disconnected change log to show last 50 lines of wavesrv.log (#210) * improved disconnected modal * wrap pre with div * make number of a lines param a constant * revert app.tsx * use tail command and capture the output instead * reset TabSwitcherModal --- src/app/app.tsx | 1 - src/app/common/common.tsx | 10 ++-- src/app/common/modals/modals.less | 52 ++++++++++++----- src/app/common/modals/modals.tsx | 95 ++++++++++++++++--------------- src/electron/emain.ts | 27 +++++++++ src/electron/preload.js | 4 ++ src/model/model.ts | 5 ++ 7 files changed, 128 insertions(+), 66 deletions(-) diff --git a/src/app/app.tsx b/src/app/app.tsx index 690b6f088..374cf232a 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -68,7 +68,6 @@ class App extends React.Component<{}, {}> { } render() { - let clientSettingsModal = GlobalModel.clientSettingsModal.get(); let remotesModel = GlobalModel.remotesModel; let disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get(); let hasClientStop = GlobalModel.getHasClientStop(); diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index c6042382e..0f263a8ad 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -1085,16 +1085,18 @@ class Dropdown extends React.Component { } interface ModalHeaderProps { - onClose: () => void; + onClose?: () => void; title: string; } const ModalHeader: React.FC = ({ onClose, title }) => (
{
{title}
} - - - + + + + +
); diff --git a/src/app/common/modals/modals.less b/src/app/common/modals/modals.less index f40745397..7a8744183 100644 --- a/src/app/common/modals/modals.less +++ b/src/app/common/modals/modals.less @@ -17,24 +17,46 @@ } .disconnected-modal { - .modal-content { - footer { - .footer-text-link { - color: @term-white; - cursor: pointer; + .wave-modal-content { + .wave-modal-body { + padding: 0; + + .modal-content { + footer { + .footer-text-link { + color: @term-white; + cursor: pointer; + } + } + } + + .inner-content { + .log { + height: 335px; + margin-bottom: 20px; + overflow: auto; + + &::-webkit-scrollbar-track, + &::-webkit-scrollbar-thumb, + &::-webkit-scrollbar-corner { + display: none; + } + + &:hover::-webkit-scrollbar-thumb { + display: block; + } + + pre { + color: @term-white; + background-color: @term-black; + } + } } } - } - .inner-content { - .ws-log { - padding: 5px; - background-color: @term-black; - height: 250px; - overflow: auto; - - .ws-logline { - color: @term-white; + .wave-modal-footer { + button:first-child { + color: @term-green; } } } diff --git a/src/app/common/modals/modals.tsx b/src/app/common/modals/modals.tsx index bbf1df332..f19c4cb0a 100644 --- a/src/app/common/modals/modals.tsx +++ b/src/app/common/modals/modals.tsx @@ -27,10 +27,9 @@ import { import * as util from "../../../util/util"; import * as textmeasure from "../../../util/textmeasure"; import { ClientDataType } from "../../../types/types"; -import { Session, Screen } from "../../../model/model"; +import { Screen } from "../../../model/model"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; -import { ReactComponent as WarningIcon } from "../../assets/icons/line/triangle-exclamation.svg"; import shield from "../../assets/icons/shield_check.svg"; import help from "../../assets/icons/help_filled.svg"; import github from "../../assets/icons/github.svg"; @@ -48,6 +47,7 @@ type OArr = mobx.IObservableArray; const RemotePtyRows = 9; const RemotePtyCols = 80; +const NumOfLines = 50; const PasswordUnchangedSentinel = "--unchanged--"; @mobxReact.observer @@ -70,7 +70,8 @@ class ModalsProvider extends React.Component { @mobxReact.observer class DisconnectedModal extends React.Component<{}, {}> { logRef: any = React.createRef(); - showLog: mobx.IObservableValue = mobx.observable.box(false); + logs: mobx.IObservableValue = mobx.observable.box(""); + logInterval: NodeJS.Timeout = null; @boundMethod restartServer() { @@ -83,8 +84,16 @@ class DisconnectedModal extends React.Component<{}, {}> { } componentDidMount() { - if (this.logRef.current != null) { - this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + this.fetchLogs(); + + this.logInterval = setInterval(() => { + this.fetchLogs(); + }, 5000); + } + + componentWillUnmount() { + if (this.logInterval) { + clearInterval(this.logInterval); } } @@ -94,58 +103,52 @@ class DisconnectedModal extends React.Component<{}, {}> { } } - @boundMethod - handleShowLog(): void { - mobx.action(() => { - this.showLog.set(!this.showLog.get()); - })(); + fetchLogs() { + GlobalModel.getLastLogs( + NumOfLines, + mobx.action((logs) => { + this.logs.set(logs); + if (this.logRef.current != null) { + this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + } + }) + ); } render() { - let model = GlobalModel; - let logLine: string = null; - let idx: number = 0; return ( -
-
-
-
-
Wave Client Disconnected
-
- + + +
+
-
- -
- {logLine} -
-
+
+
{this.logs.get()}
- -
-
- - Show Log - - - Hide Log - -
-
-
+
+
+ - - + } + > + Try Reconnect + +
-
+ ); } } diff --git a/src/electron/emain.ts b/src/electron/emain.ts index c31d3912c..4f4602fa6 100644 --- a/src/electron/emain.ts +++ b/src/electron/emain.ts @@ -485,6 +485,33 @@ electron.ipcMain.on("reload-window", (event) => { return; }); +electron.ipcMain.on("get-last-logs", async (event, numberOfLines) => { + try { + const logPath = path.join(getWaveHomeDir(), "wavesrv.log"); + const lastLines = await readLastLinesOfFile(logPath, numberOfLines); + event.reply("last-logs", lastLines); + } catch (err) { + console.error("Error reading log file:", err); + event.reply("last-logs", "Error reading log file."); + } +}); + +function readLastLinesOfFile(filePath, lineCount) { + return new Promise((resolve, reject) => { + child_process.exec(`tail -n ${lineCount} "${filePath}"`, (err, stdout, stderr) => { + if (err) { + reject(err.message); + return; + } + if (stderr) { + reject(stderr); + return; + } + resolve(stdout); + }); + }); +} + function getContextMenu(): any { let menu = new electron.Menu(); let menuItem = new electron.MenuItem({ label: "Testing", click: () => console.log("click testing!") }); diff --git a/src/electron/preload.js b/src/electron/preload.js index 6dc8f108c..1abe03611 100644 --- a/src/electron/preload.js +++ b/src/electron/preload.js @@ -6,6 +6,10 @@ contextBridge.exposeInMainWorld("api", { getIsDev: () => ipcRenderer.sendSync("get-isdev"), getAuthKey: () => ipcRenderer.sendSync("get-authkey"), getWaveSrvStatus: () => ipcRenderer.sendSync("wavesrv-status"), + getLastLogs: (numberOfLines, callback) => { + ipcRenderer.send("get-last-logs", numberOfLines); + ipcRenderer.once("last-logs", (event, data) => callback(data)); + }, restartWaveSrv: () => ipcRenderer.sendSync("restart-server"), reloadWindow: () => ipcRenderer.sendSync("reload-window"), onTCmd: (callback) => ipcRenderer.on("t-cmd", callback), diff --git a/src/model/model.ts b/src/model/model.ts index a4cec535a..4ba81bd19 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -208,6 +208,7 @@ type ElectronApi = { contextScreen: (screenOpts: { screenId: string }, position: { x: number; y: number }) => void; contextEditMenu: (position: { x: number; y: number }, opts: ContextMenuOpts) => void; onWaveSrvStatusChange: (callback: (status: boolean, pid: number) => void) => void; + getLastLogs: (numOfLines: number, callback: (logs: any) => void) => void; }; function getApi(): ElectronApi { @@ -3476,6 +3477,10 @@ class Model { })(); } + getLastLogs(numbOfLines: number, cb: (logs: any) => void): void { + getApi().getLastLogs(numbOfLines, cb); + } + getContentHeight(context: RendererContext): number { let key = context.screenId + "/" + context.lineId; return this.termUsedRowsCache[key];