From 1dee3a6089ff5aa3a5806c28a5b8ea5f1d430709 Mon Sep 17 00:00:00 2001 From: wooferzfg Date: Mon, 11 May 2020 22:08:06 -0500 Subject: [PATCH] Update how splits are loaded from the leaderboard --- src/ui/LiveSplit.tsx | 26 +++++++++++++++++++------- src/ui/RunEditor.tsx | 27 ++++++++++++++++++++++----- src/ui/SplitsSelection.tsx | 15 ++++++++++++--- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/ui/LiveSplit.tsx b/src/ui/LiveSplit.tsx index a8b821455..38051c6b6 100644 --- a/src/ui/LiveSplit.tsx +++ b/src/ui/LiveSplit.tsx @@ -34,7 +34,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 } | @@ -365,13 +365,25 @@ export class LiveSplit extends React.Component { 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({ + menu: { + kind: MenuKind.RunEditor, + editor, + splitsKey: undefined, + persistChanges: true, + }, sidebarOpen: false, }); } @@ -380,16 +392,16 @@ export class LiveSplit extends React.Component { 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(); diff --git a/src/ui/RunEditor.tsx b/src/ui/RunEditor.tsx index e2a79f84a..73dd33155 100644 --- a/src/ui/RunEditor.tsx +++ b/src/ui/RunEditor.tsx @@ -37,6 +37,7 @@ export interface State { interface Callbacks { renderViewWithSidebar(renderedView: JSX.Element, sidebarContent: JSX.Element): JSX.Element, + replaceRunEditor(editor: LiveSplit.RunEditor): void, closeRunEditor(save: boolean): void, } @@ -1871,6 +1872,18 @@ export class RunEditor extends React.Component { } private async downloadSplits(apiRun: Run, apiUri: string) { + // TODO: 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); @@ -1881,11 +1894,12 @@ export class RunEditor extends React.Component { const platformListDownload = downloadPlatformList(); const regionListDownload = downloadRegionList(); const gameInfoDownload = downloadGameInfo(gameName); + await gameInfoDownload; await platformListDownload; await regionListDownload; const run = await runDownload; - // TODO Race Condition with the Run Editor closing (and probably others) + run.with((run) => { const newEditor = LiveSplit.RunEditor.new(run); if (newEditor !== null) { @@ -1896,10 +1910,7 @@ export class RunEditor extends React.Component { 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."); @@ -1908,6 +1919,12 @@ export class RunEditor extends React.Component { } catch (_) { toast.error("Failed to download the splits."); } + + this.setState({ + ...this.state, + isLoading: false, + }); + this.update(Tab.RealTime); } private toggleExpandLeaderboardRow(rowIndex: number) { diff --git a/src/ui/SplitsSelection.tsx b/src/ui/SplitsSelection.tsx index e4b6ffa9b..7ad46bbdd 100644 --- a/src/ui/SplitsSelection.tsx +++ b/src/ui/SplitsSelection.tsx @@ -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, } @@ -179,7 +180,11 @@ export class SplitsSelection extends React.Component { } }); 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."); } @@ -265,7 +270,11 @@ export class SplitsSelection extends React.Component { 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) {