From e71064fd2e298f634b32b94b6ae6e937341599f2 Mon Sep 17 00:00:00 2001 From: etopiei Date: Mon, 27 Jul 2020 16:22:13 +1000 Subject: [PATCH 1/5] Align web socket commands with LiveView server --- src/ui/TimerView.tsx | 33 +++++++++++++++++++++++++++++---- src/util/TimeUtil.ts | 10 ++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/ui/TimerView.tsx b/src/ui/TimerView.tsx index 9012e7ad7..5cb05316b 100644 --- a/src/ui/TimerView.tsx +++ b/src/ui/TimerView.tsx @@ -5,6 +5,7 @@ import { TimingMethod, TimeSpan, LayoutStateRefMut, } from "../livesplit-core"; import { Option } from "../util/OptionUtil"; +import { formatTimeForServer } from "../util/TimeUtil"; import DragUpload from "./DragUpload"; import AutoRefresh from "../util/AutoRefresh"; import AutoRefreshLayout from "../layout/AutoRefreshLayout"; @@ -252,13 +253,16 @@ export class TimerView extends React.Component { if (typeof e.data === "string") { const [command, ...args] = e.data.split(" "); switch (command) { - case "start": this.start(); break; + case "starttimer": this.start(); break; + case "getcurrenttime": this.getTime(); break; + case "getcurrenttimerphase": this.getTimerPhase(); break; case "split": this.split(); break; case "splitorstart": this.splitOrStart(); break; case "reset": this.reset(); break; - case "togglepause": this.togglePauseOrStart(); break; - case "undo": this.undoSplit(); break; - case "skip": this.skipSplit(); break; + case "pause": this.togglePauseOrStart(); break; + case "resume": this.togglePauseOrStart(); break; + case "unsplit": this.undoSplit(); break; + case "skipsplit": this.skipSplit(); break; case "initgametime": this.initializeGameTime(); break; case "setgametime": this.setGameTime(args[0]); break; case "setloadingtimes": this.setLoadingTimes(args[0]); break; @@ -276,6 +280,27 @@ export class TimerView extends React.Component { }; } + private getTime() { + console.log(`Fetching game time`); + this.readWith((t) => { + console.log(`Read time: ${formatTimeForServer(t.currentTime().realTime()!.totalSeconds(), false)}`); + this.connection?.send(formatTimeForServer(t.currentTime().realTime()!.totalSeconds(), false)); + }); + } + + private getTimerPhase() { + this.readWith((t) => { + let result = ""; + switch (t.currentPhase()) { + case 0: result = "NotRunning"; break; + case 1: result = "Running"; break; + case 2: result = "Ended"; break; + case 3: result = "Paused"; break; + } + this.connection?.send(result); + }); + } + private writeWith(action: (timer: TimerRefMut) => T): T { return this.props.timer.writeWith(action); } diff --git a/src/util/TimeUtil.ts b/src/util/TimeUtil.ts index bfc302c22..24345916d 100644 --- a/src/util/TimeUtil.ts +++ b/src/util/TimeUtil.ts @@ -27,3 +27,13 @@ export function formatLeaderboardTime(totalSeconds: number, hideMilliseconds: bo }`; } } + +export function formatTimeForServer(totalSeconds: number, hideMilliseconds: boolean): string { + let t = formatLeaderboardTime(totalSeconds, hideMilliseconds); + let parts = t.split(":"); + if (parts[0].length < 2) { + return "0" + parts[0] + ":" + parts[1].slice(0, parts[1].length - 1); + } else { + return parts[0] + ":" + parts[1].slice(0, parts[1].length - 1); + } +} From 9232b5e8c348a6c4903cce9739d0ff10d5aaa9d6 Mon Sep 17 00:00:00 2001 From: etopiei Date: Wed, 29 Jul 2020 21:26:58 +1000 Subject: [PATCH 2/5] Splitting web socket specific functions off --- src/ui/TimerView.tsx | 32 +++++++++++--------------------- src/util/TimeUtil.ts | 10 ---------- src/util/WebSocket.ts | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 src/util/WebSocket.ts diff --git a/src/ui/TimerView.tsx b/src/ui/TimerView.tsx index 5cb05316b..f7182cb96 100644 --- a/src/ui/TimerView.tsx +++ b/src/ui/TimerView.tsx @@ -5,7 +5,6 @@ import { TimingMethod, TimeSpan, LayoutStateRefMut, } from "../livesplit-core"; import { Option } from "../util/OptionUtil"; -import { formatTimeForServer } from "../util/TimeUtil"; import DragUpload from "./DragUpload"; import AutoRefresh from "../util/AutoRefresh"; import AutoRefreshLayout from "../layout/AutoRefreshLayout"; @@ -13,6 +12,7 @@ import AutoRefreshLayout from "../layout/AutoRefreshLayout"; import LiveSplitIcon from "../assets/icon_small.png"; import "../css/TimerView.scss"; +import { mapPhaseEnumToString, formatTimeForServer } from "../util/WebSocket"; export interface Props { isDesktop: boolean, @@ -254,13 +254,14 @@ export class TimerView extends React.Component { const [command, ...args] = e.data.split(" "); switch (command) { case "starttimer": this.start(); break; - case "getcurrenttime": this.getTime(); break; - case "getcurrenttimerphase": this.getTimerPhase(); break; + case "getcurrenttime": this.sendTime(); break; + case "getcurrenttimerphase": this.sendTimerPhase(); break; case "split": this.split(); break; case "splitorstart": this.splitOrStart(); break; case "reset": this.reset(); break; - case "pause": this.togglePauseOrStart(); break; - case "resume": this.togglePauseOrStart(); break; + case "pause": + case "resume": + case "togglepause": this.togglePauseOrStart(); break; // These are different aliases for the same command case "unsplit": this.undoSplit(); break; case "skipsplit": this.skipSplit(); break; case "initgametime": this.initializeGameTime(); break; @@ -280,25 +281,14 @@ export class TimerView extends React.Component { }; } - private getTime() { - console.log(`Fetching game time`); + private sendTime() { this.readWith((t) => { - console.log(`Read time: ${formatTimeForServer(t.currentTime().realTime()!.totalSeconds(), false)}`); - this.connection?.send(formatTimeForServer(t.currentTime().realTime()!.totalSeconds(), false)); + this.connection?.send(formatTimeForServer(t.currentTime().realTime()!.totalSeconds())); }); } - private getTimerPhase() { - this.readWith((t) => { - let result = ""; - switch (t.currentPhase()) { - case 0: result = "NotRunning"; break; - case 1: result = "Running"; break; - case 2: result = "Ended"; break; - case 3: result = "Paused"; break; - } - this.connection?.send(result); - }); + private sendTimerPhase() { + this.readWith((t) => this.connection?.send(mapPhaseEnumToString(t.currentPhase()))); } private writeWith(action: (timer: TimerRefMut) => T): T { @@ -378,4 +368,4 @@ export class TimerView extends React.Component { private resumeGameTime() { this.writeWith((t) => t.resumeGameTime()); } -} +} \ No newline at end of file diff --git a/src/util/TimeUtil.ts b/src/util/TimeUtil.ts index 24345916d..bfc302c22 100644 --- a/src/util/TimeUtil.ts +++ b/src/util/TimeUtil.ts @@ -27,13 +27,3 @@ export function formatLeaderboardTime(totalSeconds: number, hideMilliseconds: bo }`; } } - -export function formatTimeForServer(totalSeconds: number, hideMilliseconds: boolean): string { - let t = formatLeaderboardTime(totalSeconds, hideMilliseconds); - let parts = t.split(":"); - if (parts[0].length < 2) { - return "0" + parts[0] + ":" + parts[1].slice(0, parts[1].length - 1); - } else { - return parts[0] + ":" + parts[1].slice(0, parts[1].length - 1); - } -} diff --git a/src/util/WebSocket.ts b/src/util/WebSocket.ts new file mode 100644 index 000000000..98931cab5 --- /dev/null +++ b/src/util/WebSocket.ts @@ -0,0 +1,20 @@ +import { formatLeaderboardTime } from './TimeUtil'; + +export function mapPhaseEnumToString(phase: number) : string { + const phases = ["NotRunning", "Running", "Ended", "Paused"]; + if (phase > 0 && phase < phases.length) { + return phases[phase]; + } else { + return ""; + } +} + +export function formatTimeForServer(totalSeconds: number): string { + const t = formatLeaderboardTime(totalSeconds, false); + const parts = t.split(":"); + if (parts[0].length < 2) { + return "0" + parts[0] + ":" + parts[1].slice(0, parts[1].length - 1); + } else { + return parts[0] + ":" + parts[1].slice(0, parts[1].length - 1); + } +} \ No newline at end of file From fd5917c357c8ea09b2923df106820ecca9f45bce Mon Sep 17 00:00:00 2001 From: etopiei Date: Tue, 11 Aug 2020 11:12:48 +1000 Subject: [PATCH 3/5] Moved websocket functionality to a manager class --- src/ui/TimerView.tsx | 95 +++++++++------------------ src/util/WebSocket.ts | 20 ------ src/util/WebSocketManager.ts | 122 +++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 86 deletions(-) delete mode 100644 src/util/WebSocket.ts create mode 100644 src/util/WebSocketManager.ts diff --git a/src/ui/TimerView.tsx b/src/ui/TimerView.tsx index f7182cb96..b16ff097e 100644 --- a/src/ui/TimerView.tsx +++ b/src/ui/TimerView.tsx @@ -12,7 +12,7 @@ import AutoRefreshLayout from "../layout/AutoRefreshLayout"; import LiveSplitIcon from "../assets/icon_small.png"; import "../css/TimerView.scss"; -import { mapPhaseEnumToString, formatTimeForServer } from "../util/WebSocket"; +import { WebSocketManager } from "../util/WebSocketManager"; export interface Props { isDesktop: boolean, @@ -41,11 +41,31 @@ interface Callbacks { } export class TimerView extends React.Component { - private connection: Option; + private connection: WebSocketManager; constructor(props: Props) { super(props); + this.connection = new WebSocketManager({ + start: () => this.start(), + split: () => this.split(), + splitOrStart: () => this.splitOrStart(), + reset: () => this.reset(), + undoSplit: () => this.undoSplit(), + skip: () => this.skipSplit(), + initGameTime: () => this.initializeGameTime(), + setGameTime: (time: string) => this.setGameTime(time), + setLoadingTimes: (loadTime: string) => this.setLoadingTimes(loadTime), + pauseGameTime: () => this.pauseGameTime(), + resumeGameTime: () => this.resumeGameTime(), + getCurrentTime: (cb: (totalSeconds: number) => void) => this.getTime(cb), + getCurrentPhase: (cb: (currentPhase: number) => void) => this.getCurrentPhase(cb), + togglePause: () => this.togglePauseOrStart(), + }, + { + info: toast.info, + error: toast.error + }); this.state = { comparison: null, timingMethod: null, @@ -169,7 +189,7 @@ export class TimerView extends React.Component {