Skip to content

Commit

Permalink
Clean up and move server connection to settings
Browse files Browse the repository at this point in the history
This moves the server connection button to the settings and cleans the
entire functionality up in various ways. The server connection no longer
gets closed by navigating around the application. Additionally the
server URL is now being remembered between sessions.
  • Loading branch information
CryZe committed May 27, 2024
1 parent 84c4250 commit 4d6d06c
Show file tree
Hide file tree
Showing 17 changed files with 349 additions and 171 deletions.
96 changes: 96 additions & 0 deletions src/api/LiveSplitServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { toast } from "react-toastify";

interface Callbacks {
start(): void,
split(): void,
splitOrStart(): void,
reset(): void,
togglePauseOrStart(): void,
undoSplit(): void,
skipSplit(): void,
initializeGameTime(): void,
setGameTime(time: string): void,
setLoadingTimes(time: string): void,
pauseGameTime(): void,
resumeGameTime(): void,
forceUpdate(): void,
onServerConnectionClosed(): void;
}

export class LiveSplitServer {
private connection: WebSocket;
private wasIntendingToDisconnect = false;

constructor(
url: string,
private callbacks: Callbacks,
) {
try {
this.connection = new WebSocket(url);
} catch (e: any) {
toast.error(`Failed to connect to the server: ${e.message}`);
throw e;
}

callbacks.forceUpdate();

let wasConnected = false;

this.connection.onopen = (_) => {
wasConnected = true;
toast.info("Connected to the server.");
callbacks.forceUpdate();
};

this.connection.onerror = (e) => {
toast.error(e);
};

this.connection.onmessage = (e) => {
if (typeof e.data === "string") {
const [command, ...args] = e.data.split(" ");
switch (command) {
case "start": callbacks.start(); break;
case "split": callbacks.split(); break;
case "splitorstart": callbacks.splitOrStart(); break;
case "reset": callbacks.reset(); break;
case "togglepause": callbacks.togglePauseOrStart(); break;
case "undo": callbacks.undoSplit(); break;
case "skip": callbacks.skipSplit(); break;
case "initgametime": callbacks.initializeGameTime(); break;
case "setgametime": callbacks.setGameTime(args[0]); break;
case "setloadingtimes": callbacks.setLoadingTimes(args[0]); break;
case "pausegametime": callbacks.pauseGameTime(); break;
case "resumegametime": callbacks.resumeGameTime(); break;
}
}
};

this.connection.onclose = (ev) => {
const reason = ev.reason ? `: ${ev.reason}` : ".";
if (wasConnected) {
if (this.wasIntendingToDisconnect) {
toast.info("Closed the connection to the server.");
} else {
toast.error(`Lost the connection to the server${reason}`);
}
} else {
toast.error(`Failed to connect to the server${reason}`);
}
callbacks.onServerConnectionClosed();
callbacks.forceUpdate();
};
}

close(): void {
if (this.connection.readyState === WebSocket.OPEN) {
this.wasIntendingToDisconnect = true;
this.connection.close();
this.callbacks.forceUpdate();
}
}

getConnectionState(): number {
return this.connection.readyState;
}
}
22 changes: 11 additions & 11 deletions src/css/About.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
$text-width: 400px;
$icon-size: 40px;
$title-font-size: 40px;
$build-version-font-size: 11px;
$build-version-font-size: 12px;
$link-color: #56b0ff;

.about {
Expand All @@ -13,47 +13,47 @@ $link-color: #56b0ff;
padding: $ui-large-margin;
border: 1px solid $border-color;
width: fit-content;

.livesplit-title {
display: flex;
align-items: center;

.livesplit-icon {
height: $icon-size;
margin-right: $ui-margin;

img {
height: 100%;
}
}

.title-text {
font-weight: bold;
font-size: $title-font-size;
}
}

.build-version {
font-size: $build-version-font-size;
}

.contributors-header {
margin-bottom: 0;
}

.contributor {
margin-block-start: 0.5em;
margin-block-end: 0.5em;

&:last-child {
margin-block-end: 0;
}
}

a {
color: $link-color;
}

p {
max-width: $text-width;

Expand Down
6 changes: 6 additions & 0 deletions src/css/LiveSplitServerButton.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.livesplit-server-button {
margin: 0px;
font-size: 16px;
height: 22px;
// TODO: This is the same as the hotkey button.
}
1 change: 1 addition & 0 deletions src/css/Tooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
transition: opacity 0.25s;
transition-delay: 0.25s;
text-wrap: initial;
font-weight: initial;

@include mobile {
left: 0;
Expand Down
15 changes: 10 additions & 5 deletions src/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,21 @@ body {
background: $main-background-color;
}

.toast-class {
border-radius: 2px !important;
min-height: 48px !important;
.Toastify {
.toast-class {
font-family: "fira", sans-serif;
background: $sidebar-background-color !important;
border: 2px solid $border-color !important;
border-radius: 10px !important;
min-height: 48px !important;
}
}

.toast-body {
margin: 10px 5px 10px 5px !important;
margin: 5px 5px 5px 5px !important;
}

.toast-class > button {
.toast-class>button {
margin-bottom: initial;
margin-top: initial;
}
Expand Down
4 changes: 1 addition & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ try {
position={toast.POSITION.BOTTOM_RIGHT}
toastClassName="toast-class"
bodyClassName="toast-body"
style={{
textShadow: "none",
}}
theme="dark"
/>
</div>,
document.getElementById("base"),
Expand Down
1 change: 1 addition & 0 deletions src/storage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,5 +254,6 @@ export async function loadGeneralSettings(): Promise<GeneralSettings> {
showManualGameTime: generalSettings.showManualGameTime ?? false,
speedrunComIntegration: generalSettings.speedrunComIntegration ?? true,
splitsIoIntegration: generalSettings.splitsIoIntegration ?? true,
serverUrl: generalSettings.serverUrl,
};
}
4 changes: 2 additions & 2 deletions src/ui/About.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class About extends React.Component<Props> {
</div>
<p className="build-version">
<a href={`https://github.com/LiveSplit/LiveSplitOne/commit/${COMMIT_HASH}`} target="_blank">
Version: {COMMIT_HASH} ({BUILD_DATE})
Version: {BUILD_DATE}
</a>
</p>
<p>LiveSplit One is a multiplatform version of LiveSplit, the sleek,
Expand All @@ -42,7 +42,7 @@ export class About extends React.Component<Props> {
View Source Code on GitHub
</a>
</p>
<h1 className="contributors-header">Contributors</h1>
<h2 className="contributors-header">Contributors</h2>
{
CONTRIBUTORS_LIST.map((contributor) => (
<p className="contributor">
Expand Down
4 changes: 3 additions & 1 deletion src/ui/HotkeyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ export default class HotkeyButton extends React.Component<Props, State> {
return (
<div className="hotkey-box">
<button
className={`hotkey-button ${this.state.listener != null ? "focused" : ""}`}
className={`hotkey-button tooltip ${this.state.listener != null ? "focused" : ""}`}
onClick={() => this.focusButton()}
>
{buttonText}
<span className="tooltip-text">Click to record a hotkey. You may also use buttons on a gamepad.</span>
</button>
{
map(this.props.value, () => (
Expand Down Expand Up @@ -102,6 +103,7 @@ export default class HotkeyButton extends React.Component<Props, State> {
}
text += ev.code;
this.props.setValue(text);
ev.preventDefault();
}
};

Expand Down
6 changes: 6 additions & 0 deletions src/ui/LayoutView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { TimerView } from "./TimerView";
import { UrlCache } from "../util/UrlCache";
import { WebRenderer } from "../livesplit-core/livesplit_core";
import { GeneralSettings } from "./SettingsEditor";
import { LiveSplitServer } from "../api/LiveSplitServer";
import { Option } from "../util/OptionUtil";

export interface Props {
isDesktop: boolean,
Expand All @@ -17,6 +19,7 @@ export interface Props {
sidebarOpen: boolean,
timer: SharedTimer,
renderer: WebRenderer,
serverConnection: Option<LiveSplitServer>,
callbacks: Callbacks,
}

Expand All @@ -35,6 +38,8 @@ interface Callbacks {
openTimerView(): void,
renderViewWithSidebar(renderedView: JSX.Element, sidebarContent: JSX.Element): JSX.Element,
saveLayout(): void,
onServerConnectionOpened(serverConnection: LiveSplitServer): void,
onServerConnectionClosed(): void,
}

export class LayoutView extends React.Component<Props> {
Expand All @@ -51,6 +56,7 @@ export class LayoutView extends React.Component<Props> {
sidebarOpen={this.props.sidebarOpen}
timer={this.props.timer}
renderer={this.props.renderer}
serverConnection={this.props.serverConnection}
callbacks={this.props.callbacks}
/>;
const sidebarContent = this.renderSidebarContent();
Expand Down
Loading

0 comments on commit 4d6d06c

Please sign in to comment.