Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update how splits are loaded from the leaderboard #363

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
15 changes: 15 additions & 0 deletions src/css/Loading.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@import 'variables';

$loading-text-font-size: 45px;

@mixin loading {
.loading {
display: flex;
width: fit-content;
font-size: $loading-text-font-size;

.loading-text {
margin-left: $ui-margin;
}
}
}
2 changes: 2 additions & 0 deletions src/css/RunEditor.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@use 'sass:math';

@import "ContextMenu";
@import "Loading";
@import "Markdown";
@import "mobile";
@import "Table";
Expand All @@ -19,6 +20,7 @@ $small-button-padding: 1px 3px 1px 3px;

.run-editor {
@include context-menu;
@include loading;
@include markdown;
@include table;
@include toggle;
Expand Down
12 changes: 2 additions & 10 deletions src/css/SplitsSelection.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,15 @@

@import 'mobile';
@import 'variables';
@import 'Loading';
@import 'Table';
@import 'ContextMenu';

$loading-text-font-size: 40px;
$splits-row-width: 500px;
$splits-row-height: 40px;

.splits-selection {
.loading {
display: flex;
width: fit-content;
font-size: $loading-text-font-size;

.loading-text {
margin-left: $ui-margin;
}
}
@include loading;

.splits-selection-container {
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/css/Title.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "variables";
@import 'variables';

$game-icon-size: $two-row-height - $vertical-padding * 2;

Expand Down
6 changes: 2 additions & 4 deletions src/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

@import 'browser_source';
@import 'variables';
@import 'Loading';

@font-face {
font-family: timer;
Expand Down Expand Up @@ -132,9 +133,6 @@ button.disabled:active {
display: flex;
justify-content: center;
align-items: center;
font-size: 50px;

.initial-load-text {
margin-left: 10px;
}
@include loading;
}
6 changes: 4 additions & 2 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
<body>
<div id="base">
<div class="initial-load">
<div class="fa fa-spinner fa-spin"></div>
<div class="initial-load-text">Loading...</div>
<div class="loading">
<div class="fa fa-spinner fa-spin"></div>
<div class="loading-text">Loading...</div>
</div>
</div>
</div>
</body>
Expand Down
26 changes: 19 additions & 7 deletions src/ui/LiveSplit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export enum MenuKind {
type Menu =
{ kind: MenuKind.Timer } |
{ kind: MenuKind.Splits } |
{ kind: MenuKind.RunEditor, editor: RunEditor, splitsKey?: number } |
{ kind: MenuKind.RunEditor, editor: RunEditor, splitsKey?: number, persistChanges: boolean } |
{ kind: MenuKind.Layout } |
{ kind: MenuKind.LayoutEditor, editor: LayoutEditor } |
{ kind: MenuKind.SettingsEditor, config: HotkeyConfig } |
Expand Down Expand Up @@ -382,13 +382,25 @@ export class LiveSplit extends React.Component<Props, State> {
this.setLayout(layout);
}

public openRunEditor({ splitsKey, run }: EditingInfo) {
public openRunEditor({ splitsKey, persistChanges, run }: EditingInfo) {
const editor = expect(
RunEditor.new(run),
"The Run Editor should always be able to be opened.",
);
this.setState({
menu: { kind: MenuKind.RunEditor, editor, splitsKey },
menu: { kind: MenuKind.RunEditor, editor, splitsKey, persistChanges },
sidebarOpen: false,
});
}

public replaceRunEditor(editor: RunEditor) {
this.setState({
wooferzfg marked this conversation as resolved.
Show resolved Hide resolved
menu: {
kind: MenuKind.RunEditor,
editor,
splitsKey: undefined,
persistChanges: true,
},
sidebarOpen: false,
});
}
Expand All @@ -397,16 +409,16 @@ export class LiveSplit extends React.Component<Props, State> {
if (this.state.menu.kind !== MenuKind.RunEditor) {
panic("No Run Editor to close");
}
const { editor, splitsKey } = this.state.menu;
const { editor, persistChanges, splitsKey } = this.state.menu;
const run = editor.close();
if (save) {
if (splitsKey == null) {
if (persistChanges) {
Storage.storeRunAndDispose(run, splitsKey);
} else {
assertNull(
this.writeWith((t) => t.setRun(run)),
"The Run Editor should always return a valid Run.",
);
} else {
Storage.storeRunAndDispose(run, splitsKey);
}
} else {
run.dispose();
Expand Down
38 changes: 34 additions & 4 deletions src/ui/RunEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface Props {
}
export interface State {
editor: LiveSplit.RunEditorStateJson,
isLoading: boolean,
offsetIsValid: boolean,
attemptCountIsValid: boolean,
rowState: RowState,
Expand All @@ -38,6 +39,7 @@ export interface State {

interface Callbacks {
renderViewWithSidebar(renderedView: JSX.Element, sidebarContent: JSX.Element): JSX.Element,
replaceRunEditor(editor: LiveSplit.RunEditor): void,
closeRunEditor(save: boolean): void,
}

Expand Down Expand Up @@ -83,6 +85,7 @@ export class RunEditor extends React.Component<Props, State> {
this.state = {
attemptCountIsValid: true,
editor: state,
isLoading: false,
offsetIsValid: true,
rowState: {
bestSegmentTime: "",
Expand Down Expand Up @@ -113,6 +116,17 @@ export class RunEditor extends React.Component<Props, State> {
}

private renderView() {
if (this.state.isLoading) {
return (
<div className="run-editor">
<div className="loading">
<div className="fa fa-spinner fa-spin"></div>
<div className="loading-text">Loading...</div>
</div>
</div>
);
}

const gameIcon = this.getGameIcon();

let gameIconContextTrigger: any = null;
Expand Down Expand Up @@ -1864,6 +1878,18 @@ export class RunEditor extends React.Component<Props, State> {
}

private async downloadSplits<T>(apiRun: Run<T>, apiUri: string) {
// FIXME: Determine whether there are any unsaved changes in the Run Editor
if (!confirm(
"Are you sure you want to load these splits? Any unsaved changes will be lost.",
)) {
return;
}

this.setState({
...this.state,
isLoading: true,
});

const baseUri = "https://splits.io/api/v3/runs/";
assert(apiUri.startsWith(baseUri), "Unexpected Splits.io URL");
const splitsId = apiUri.slice(baseUri.length);
Expand All @@ -1874,6 +1900,7 @@ export class RunEditor extends React.Component<Props, State> {
const platformListDownload = downloadPlatformList();
const regionListDownload = downloadRegionList();
const gameInfoDownload = downloadGameInfo(gameName);

await gameInfoDownload;
await platformListDownload;
await regionListDownload;
Expand All @@ -1888,10 +1915,7 @@ export class RunEditor extends React.Component<Props, State> {
apiRun,
);

// TODO Oh no, not internal pointer stuff
this.props.editor.dispose();
this.props.editor.ptr = newEditor.ptr;

this.props.callbacks.replaceRunEditor(newEditor);
this.update();
} else {
toast.error("The downloaded splits are not suitable for being edited.");
Expand All @@ -1900,6 +1924,12 @@ export class RunEditor extends React.Component<Props, State> {
} catch (_) {
toast.error("Failed to download the splits.");
}

this.setState({
...this.state,
isLoading: false,
});
this.update(Tab.RealTime);
}

private toggleExpandLeaderboardRow(rowIndex: number) {
Expand Down
15 changes: 12 additions & 3 deletions src/ui/SplitsSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import DragUpload from "./DragUpload";
import { ContextMenuTrigger, ContextMenu, MenuItem } from "react-contextmenu";

export interface EditingInfo {
splitsKey?: number,
splitsKey: number | undefined,
persistChanges: boolean,
run: Run,
}

Expand Down Expand Up @@ -179,7 +180,11 @@ export class SplitsSelection extends React.Component<Props, State> {
}
});
if (run !== null) {
this.props.callbacks.openRunEditor({ run });
this.props.callbacks.openRunEditor({
run,
splitsKey: this.props.openedSplitsKey,
persistChanges: false,
});
} else {
toast.error("You can't edit your run while the timer is running.");
}
Expand Down Expand Up @@ -265,7 +270,11 @@ export class SplitsSelection extends React.Component<Props, State> {

private async editSplits(splitsKey: number) {
const run = await this.getRunFromKey(splitsKey);
this.props.callbacks.openRunEditor({ splitsKey, run });
this.props.callbacks.openRunEditor({
splitsKey,
persistChanges: true,
run,
});
}

private async copySplits(key: number) {
Expand Down
Loading