diff --git a/livesplit-core b/livesplit-core index 3c3762be..51775324 160000 --- a/livesplit-core +++ b/livesplit-core @@ -1 +1 @@ -Subproject commit 3c3762bec27c1774e28384216281c7ed2d760250 +Subproject commit 517753242561fd51ab86fae3304c860e64b2c44d diff --git a/src/storage/index.tsx b/src/storage/index.tsx index e857c7b3..5ff57859 100644 --- a/src/storage/index.tsx +++ b/src/storage/index.tsx @@ -1,7 +1,7 @@ import { openDB, IDBPDatabase } from "idb"; import { Option, assert } from "../util/OptionUtil"; import { RunRef, Run, TimingMethod } from "../livesplit-core"; -import { GeneralSettings } from "../ui/MainSettings"; +import { GeneralSettings, MANUAL_GAME_TIME_SETTINGS_DEFAULT } from "../ui/MainSettings"; import { FRAME_RATE_AUTOMATIC } from "../util/FrameRate"; export type HotkeyConfigSettings = unknown; @@ -249,6 +249,10 @@ export async function loadGeneralSettings(): Promise { const isTauri = window.__TAURI__ != null; + if (generalSettings.showManualGameTime === true) { + generalSettings.showManualGameTime = MANUAL_GAME_TIME_SETTINGS_DEFAULT; + } + return { frameRate: generalSettings.frameRate ?? FRAME_RATE_AUTOMATIC, showControlButtons: generalSettings.showControlButtons ?? !isTauri, diff --git a/src/ui/MainSettings.tsx b/src/ui/MainSettings.tsx index c8418478..5fad1abd 100644 --- a/src/ui/MainSettings.tsx +++ b/src/ui/MainSettings.tsx @@ -14,7 +14,7 @@ import "../css/SettingsEditor.scss"; export interface GeneralSettings { frameRate: FrameRateSetting, showControlButtons: boolean, - showManualGameTime: boolean, + showManualGameTime: ManualGameTimeSettings | false, saveOnReset: boolean, speedrunComIntegration: boolean, splitsIoIntegration: boolean, @@ -22,6 +22,16 @@ export interface GeneralSettings { alwaysOnTop?: boolean, } +export interface ManualGameTimeSettings { + mode: string, +} + +export const MANUAL_GAME_TIME_MODE_SEGMENT_TIMES = "Segment Times"; +export const MANUAL_GAME_TIME_MODE_SPLIT_TIMES = "Split Times"; +export const MANUAL_GAME_TIME_SETTINGS_DEFAULT: ManualGameTimeSettings = { + mode: MANUAL_GAME_TIME_MODE_SEGMENT_TIMES, +}; + export interface Props { generalSettings: GeneralSettings, hotkeyConfig: HotkeyConfig, @@ -62,6 +72,63 @@ export class MainSettings extends React.Component { } private renderView() { + const generalFields = [ + { + text: "Frame Rate", + tooltip: "Determines the frame rate at which to display the timer. \"Battery Aware\" tries determining the type of device and charging status to select a good frame rate. \"Match Screen\" makes the timer match the screen's refresh rate.", + value: { + CustomCombobox: { + value: this.state.generalSettings.frameRate === FRAME_RATE_MATCH_SCREEN ? FRAME_RATE_MATCH_SCREEN : this.state.generalSettings.frameRate === FRAME_RATE_BATTERY_AWARE ? FRAME_RATE_BATTERY_AWARE : this.state.generalSettings.frameRate.toString() + " FPS", + list: [FRAME_RATE_BATTERY_AWARE, "30 FPS", "60 FPS", "120 FPS", FRAME_RATE_MATCH_SCREEN], + mandatory: true, + } + }, + }, + { + text: "Save On Reset", + tooltip: "Determines whether to automatically save the splits when resetting the timer.", + value: { + Bool: this.state.generalSettings.saveOnReset, + }, + }, + { + text: "Show Control Buttons", + tooltip: "Determines whether to show buttons beneath the timer that allow controlling it. When disabled, you have to use the hotkeys instead.", + value: { Bool: this.state.generalSettings.showControlButtons }, + }, + { + text: "Show Manual Game Time Input", + tooltip: "Shows a text box beneath the timer that allows you to manually input the game time. You start the timer and do splits by pressing the Enter key in the text box. Make sure to compare against \"Game Time\".", + value: { Bool: this.state.generalSettings.showManualGameTime !== false }, + }, + ]; + + let manualGameTimeModeIndex = 0; + if (this.state.generalSettings.showManualGameTime) { + manualGameTimeModeIndex = generalFields.length; + generalFields.push({ + text: "Manual Game Time Mode", + tooltip: "Determines whether to input the manual game time as segment times or split times.", + value: { + CustomCombobox: { + value: this.state.generalSettings.showManualGameTime.mode, + list: [MANUAL_GAME_TIME_MODE_SEGMENT_TIMES, MANUAL_GAME_TIME_MODE_SPLIT_TIMES], + mandatory: false, + } + }, + }); + } + + let alwaysOnTopIndex = 0; + if (window.__TAURI__ != null) { + alwaysOnTopIndex = generalFields.length; + generalFields.push({ + text: "Always On Top", + tooltip: "Keeps the window always on top of other windows.", + value: { Bool: this.state.generalSettings.alwaysOnTop! }, + }); + } + return (

Hotkeys

@@ -84,41 +151,7 @@ export class MainSettings extends React.Component { context="settings-editor-general" factory={new JsonSettingValueFactory()} state={{ - fields: [ - { - text: "Frame Rate", - tooltip: "Determines the frame rate at which to display the timer. \"Battery Aware\" tries determining the type of device and charging status to select a good frame rate. \"Match Screen\" makes the timer match the screen's refresh rate.", - value: { - CustomCombobox: { - value: this.state.generalSettings.frameRate === FRAME_RATE_MATCH_SCREEN ? FRAME_RATE_MATCH_SCREEN : this.state.generalSettings.frameRate === FRAME_RATE_BATTERY_AWARE ? FRAME_RATE_BATTERY_AWARE : this.state.generalSettings.frameRate.toString() + " FPS", - list: [FRAME_RATE_BATTERY_AWARE, "30 FPS", "60 FPS", "120 FPS", FRAME_RATE_MATCH_SCREEN], - mandatory: true, - } - }, - }, - { - text: "Show Control Buttons", - tooltip: "Determines whether to show buttons beneath the timer that allow controlling it. When disabled, you have to use the hotkeys instead.", - value: { Bool: this.state.generalSettings.showControlButtons }, - }, - { - text: "Show Manual Game Time Input", - tooltip: "Shows a text box beneath the timer that allows you to manually input the game time. You start the timer and do splits by pressing the Enter key in the text box. Make sure to compare against \"Game Time\".", - value: { Bool: this.state.generalSettings.showManualGameTime }, - }, - { - text: "Save On Reset", - tooltip: "Determines whether to automatically save the splits when resetting the timer.", - value: { - Bool: this.state.generalSettings.saveOnReset, - }, - }, - ...((window.__TAURI__ != null) ? [{ - text: "Always On Top", - tooltip: "Keeps the window always on top of other windows.", - value: { Bool: this.state.generalSettings.alwaysOnTop! }, - }] : []), - ], + fields: generalFields, }} editorUrlCache={this.props.urlCache} allComparisons={this.props.allComparisons} @@ -143,7 +176,7 @@ export class MainSettings extends React.Component { this.setState({ generalSettings: { ...this.state.generalSettings, - showControlButtons: value.Bool, + saveOnReset: value.Bool, }, }); } @@ -153,7 +186,7 @@ export class MainSettings extends React.Component { this.setState({ generalSettings: { ...this.state.generalSettings, - showManualGameTime: value.Bool, + showControlButtons: value.Bool, }, }); } @@ -163,19 +196,29 @@ export class MainSettings extends React.Component { this.setState({ generalSettings: { ...this.state.generalSettings, - saveOnReset: value.Bool, + showManualGameTime: value.Bool ? + MANUAL_GAME_TIME_SETTINGS_DEFAULT : false, }, }); } break; - case 4: - if ("Bool" in value) { + default: + if (index === alwaysOnTopIndex && "Bool" in value) { this.setState({ generalSettings: { ...this.state.generalSettings, alwaysOnTop: value.Bool, }, }); + } else if (index === manualGameTimeModeIndex && "String" in value) { + this.setState({ + generalSettings: { + ...this.state.generalSettings, + showManualGameTime: { + mode: value.String, + }, + }, + }); } break; } diff --git a/src/ui/TimerView.tsx b/src/ui/TimerView.tsx index 1ba1c6eb..0b66de57 100644 --- a/src/ui/TimerView.tsx +++ b/src/ui/TimerView.tsx @@ -6,7 +6,7 @@ import DragUpload from "./DragUpload"; import Layout from "../layout/Layout"; import { UrlCache } from "../util/UrlCache"; import { WebRenderer } from "../livesplit-core/livesplit_core"; -import { GeneralSettings } from "./MainSettings"; +import { GeneralSettings, MANUAL_GAME_TIME_MODE_SEGMENT_TIMES } from "./MainSettings"; import { LiveSplitServer } from "../api/LiveSplitServer"; import { LSOCommandSink } from "./LSOCommandSink"; @@ -73,6 +73,8 @@ export class TimerView extends React.Component { } private renderView() { + const showManualGameTime = this.props.generalSettings.showManualGameTime; + return this.props.callbacks.importLayoutFromFile(file)} importSplits={(file) => this.props.callbacks.importSplitsFromFile(file)} @@ -167,7 +169,7 @@ export class TimerView extends React.Component {
} { - this.props.generalSettings.showManualGameTime &&
+ showManualGameTime &&
{ } else { using gameTime = TimeSpan.parse(this.state.manualGameTime); if (gameTime !== null) { + if (showManualGameTime.mode === MANUAL_GAME_TIME_MODE_SEGMENT_TIMES) { + const currentGameTime = timer.currentTime().gameTime(); + if (currentGameTime !== null) { + gameTime.addAssign(currentGameTime); + } + } timer.setGameTimeInner(gameTime); timer.split(); this.setState({ manualGameTime: "" });