Skip to content

Commit

Permalink
Показ времени до автоматического подключения к серверу (#426)
Browse files Browse the repository at this point in the history
  • Loading branch information
Roundabout1 authored Aug 30, 2024
1 parent 82bd2bc commit 1e0816e
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/renderer/src/components/Modules/Compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ export class Compiler extends ClientWS {
setCompilerData: Dispatch<SetStateAction<CompilerResult | undefined>>,
setCompilerStatus: Dispatch<SetStateAction<string>>,
setImportData: Dispatch<SetStateAction<Elements | undefined>>,
setCompilerNoDataStatus: Dispatch<SetStateAction<string>>
setCompilerNoDataStatus: Dispatch<SetStateAction<string>>,
setSecondsUntilReconnect: Dispatch<SetStateAction<number | null>>
): void {
this.setOnStatusChange(setCompilerStatus);
super.bind(setCompilerStatus, setSecondsUntilReconnect);
this.setCompilerData = setCompilerData;
this.setImportData = setImportData;
this.setCompilerNoDataStatus = setCompilerNoDataStatus;
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/src/components/Modules/Flasher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ export class Flasher extends ClientWS {
setFlasherFile: Dispatch<SetStateAction<string | undefined | null>>,
onFlashingChange: (flashing: boolean) => void,
setErrorMessage: Dispatch<SetStateAction<string | undefined>>,
setFlashResult: Dispatch<SetStateAction<FlashResult | undefined>>
setFlashResult: Dispatch<SetStateAction<FlashResult | undefined>>,
setSecondsUntilReconnect: Dispatch<SetStateAction<number | null>>
): void {
super.setOnStatusChange(setFlasherConnectionStatus);
super.bind(setFlasherConnectionStatus, setSecondsUntilReconnect);
this.setFlasherDevices = setFlasherDevices;
this.setFlasherLog = setFlasherLog;
this.setFlasherFile = setFlasherFile;
Expand Down
22 changes: 21 additions & 1 deletion src/renderer/src/components/Modules/Websocket/ClientWS.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Dispatch, SetStateAction } from 'react';

import Websocket from 'isomorphic-ws';

import { ClientStatus } from './ClientStatus';
Expand All @@ -14,8 +16,15 @@ export abstract class ClientWS {

static onStatusChange: (newConnectionStatus: string) => void;

static setOnStatusChange(onStatusChange: (newConnectionStatus: string) => void): void {
// секунд до переподключения, null - означает, что отчёт до переподключения не ведётся
static setSecondsUntilReconnect: Dispatch<SetStateAction<number | null>>;

static bind(
onStatusChange: (newConnectionStatus: string) => void,
setSecondsUntilReconnect: Dispatch<SetStateAction<number | null>>
): void {
this.onStatusChange = onStatusChange;
this.setSecondsUntilReconnect = setSecondsUntilReconnect;
}

/**
Expand Down Expand Up @@ -50,6 +59,7 @@ export abstract class ClientWS {
this.port = port;
this.connection?.close();
this.onStatusChange(ClientStatus.CONNECTING);
this.setSecondsUntilReconnect(null);

let ws: Websocket;
try {
Expand Down Expand Up @@ -88,13 +98,22 @@ export abstract class ClientWS {

static closeHandler(host: string, port: number, event: Websocket.CloseEvent) {
console.log('Close connection', event);
this.setSecondsUntilReconnect(null);
if (host == this.host && port == this.port) {
this.onStatusChange(ClientStatus.NO_CONNECTION);
this.connection = undefined;
if (this.reconnectTimer && this.reconnectTimer.isAutoReconnect()) {
this.reconnectTimer.tryToReconnect(() => {
this.reconnect();
});
this.reconnectTimer.startInterval((remainingTime: number) => {
const seconds: number = Math.round(remainingTime / 1000);
if (seconds == 0) {
this.setSecondsUntilReconnect(null);
} else {
this.setSecondsUntilReconnect(Math.round(remainingTime / 1000));
}
});
}
}
}
Expand All @@ -109,6 +128,7 @@ export abstract class ClientWS {
this.initOrResetReconnectTimer();
//console.log(`Client: connected to ${this.host}:${this.port}!`);
this.onStatusChange(ClientStatus.CONNECTED);
this.setSecondsUntilReconnect(null);
}

static cancelConnection() {
Expand Down
48 changes: 42 additions & 6 deletions src/renderer/src/components/Modules/Websocket/ReconnectTimer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,22 @@ export class ReconnectTimer {
private autoReconnect: boolean = false;
// true = установлен timerID
private timeoutSetted: boolean = false;
// true = соединение было отменено пользователем и переподключаться не нунжо.
// private connectionCanceled: boolean = false;
// время окончания таймера
private timeoutEnd: number = 0;
private intervalID: NodeJS.Timeout | undefined;
// длительность интервала intervalID
private intervalMS: number = 1000;
// таймер, отвечающий за уничтожение интервала intervalID, по истечению таймаута переподключения
private intervalDestructorID: NodeJS.Timeout | undefined;

constructor(
initialTimeout: number = 5000,
incTimeout: number = 5000,
maxReconnectAttempts: number = 3,
maxTimeout: number = 50000,
freezeTimeout: number = 1000,
autoReconnect: boolean = true
autoReconnect: boolean = true,
intervalMS: number = 1000
) {
this.initialTimeout = initialTimeout;
this.curTimeout = initialTimeout;
Expand All @@ -47,17 +53,23 @@ export class ReconnectTimer {

this.autoReconnect = autoReconnect;
this.freezeReconnection = false;
}

setTimerID(timerID: NodeJS.Timeout | undefined) {
this.timerID = timerID;
this.timeoutEnd = 0;
this.intervalMS = intervalMS;
}

clearTimer() {
if (this.timerID) {
clearTimeout(this.timerID);
this.timerID = undefined;
this.timeoutSetted = false;
this.timeoutEnd = 0;
}
if (this.intervalID) {
clearTimeout(this.intervalID);
}
if (this.intervalDestructorID) {
clearTimeout(this.intervalDestructorID);
}
}

Expand Down Expand Up @@ -98,6 +110,9 @@ export class ReconnectTimer {
return;
}
this.timeoutSetted = true;
// может быть рассинхрон между значением этой переменной и настоящим временем завершения таймера в несколько мс (см. докуметацию setTimeout),
// но такая погрешность вряд ли сильно повлияет, если округлить результат до секунд
this.timeoutEnd = new Date().getTime() + nextTimeout;
this.timerID = setTimeout(() => {
console.log(
`inTimer: ${this.curTimeout}, attempt ${this.curReconnectAttempts + 1}/${
Expand All @@ -116,6 +131,27 @@ export class ReconnectTimer {
}
}, nextTimeout);
}

// получить время до завершения таймера
getRemainingTime() {
const remainingTime = this.timeoutEnd - new Date().getTime();
return remainingTime > 0 ? remainingTime : 0;
}

// запустить интервал, который будет работать до попытки переподключения
// длительность интервала указывается при создании таймера
// при вызове таймера, будет выполнять функцию action, в которую будет передавать оставшееся время до переподключения
// возвращает время в мс
startInterval(action: (remainingTime: number) => void) {
action(this.getRemainingTime());
this.intervalID = setInterval(() => {
action(this.getRemainingTime());
}, this.intervalMS);
this.intervalDestructorID = setTimeout(() => {
clearTimeout(this.intervalID);
this.intervalID = undefined;
}, this.curTimeout);
}
}

export class ComplierTimeoutTimer {
Expand Down
16 changes: 14 additions & 2 deletions src/renderer/src/components/Sidebar/Compiler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const CompilerTab: React.FC<CompilerProps> = ({
const [compilerNoDataStatus, setCompilerNoDataStatus] = useState<string>(
CompilerNoDataStatus.DEFAULT
);
// секунд до переподключения, null - означает, что отчёт до переподключения не ведётся
const [secondsUntilReconnect, setSecondsUntilReconnect] = useState<number | null>(null);
const openTab = useTabs((state) => state.openTab);
const changeSidebarTab = useSidebar((state) => state.changeTab);

Expand Down Expand Up @@ -111,7 +113,13 @@ export const CompilerTab: React.FC<CompilerProps> = ({

const { host, port } = compilerSetting;

Compiler.bindReact(setCompilerData, setCompilerStatus, setImportData, setCompilerNoDataStatus);
Compiler.bindReact(
setCompilerData,
setCompilerStatus,
setImportData,
setCompilerNoDataStatus,
setSecondsUntilReconnect
);
Compiler.connect(host, port);
}, [compilerSetting]);

Expand Down Expand Up @@ -152,6 +160,10 @@ export const CompilerTab: React.FC<CompilerProps> = ({
const canCompile = compilerStatus == CompilerStatus.CONNECTED && isInitialized;
const disabled =
processing || (!processing && !canCompile && compilerStatus !== CompilerStatus.NO_CONNECTION);
const showReconnectTime = () => {
if (secondsUntilReconnect == null) return;
return <p>До подключения: {secondsUntilReconnect} сек.</p>;
};
return (
<section>
<h3 className="mx-4 mb-3 border-b border-border-primary py-2 text-center text-lg">
Expand Down Expand Up @@ -186,7 +198,7 @@ export const CompilerTab: React.FC<CompilerProps> = ({
{compilerStatus}
</span>
</p>

{showReconnectTime()}
<div className="mb-4 min-h-[350px] select-text overflow-y-auto break-words rounded bg-bg-primary p-2">
Результат компиляции: {compilerData ? compilerData.result : compilerNoDataStatus}
</div>
Expand Down
12 changes: 10 additions & 2 deletions src/renderer/src/components/Sidebar/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export const Loader: React.FC<FlasherProps> = ({
};

const [flashResult, setFlashResult] = useState<FlashResult>();
// секунд до переподключения, null - означает, что отчёт до переподключения не ведётся
const [secondsUntilReconnect, setSecondsUntilReconnect] = useState<number | null>(null);

const closeMsgModal = () => setIsMsgModalOpen(false);

Expand Down Expand Up @@ -223,7 +225,8 @@ export const Loader: React.FC<FlasherProps> = ({
setFlasherFile,
setIsFlashing,
setFlasherError,
setFlashResult
setFlashResult,
setSecondsUntilReconnect
);
SerialMonitor.bindReact(
addDeviceMessage,
Expand Down Expand Up @@ -283,7 +286,7 @@ export const Loader: React.FC<FlasherProps> = ({
if (flasherIsLocal) {
return 'Перезапустить';
} else {
return 'Переподключиться';
return 'Подключиться';
}
}
};
Expand Down Expand Up @@ -361,6 +364,10 @@ export const Loader: React.FC<FlasherProps> = ({
</button>
);
};
const showReconnectTime = () => {
if (secondsUntilReconnect == null) return;
return <p>До подключения: {secondsUntilReconnect} сек.</p>;
};
return (
<section className="flex h-full flex-col text-center">
<h3 className="mx-4 mb-3 border-b border-border-primary py-2 text-center text-lg">
Expand Down Expand Up @@ -400,6 +407,7 @@ export const Loader: React.FC<FlasherProps> = ({
<div className="mb-2 h-40 overflow-y-auto break-words rounded bg-bg-primary p-2">
<ErrorModal isOpen={isMsgModalOpen} data={msgModalData} onClose={closeMsgModal} />
<p>{connectionStatus}</p>
{showReconnectTime()}
<br></br>
<button
className="btn-primary mb-2 w-full"
Expand Down

0 comments on commit 1e0816e

Please sign in to comment.