diff --git a/src/index.tsx b/src/index.tsx index 854c80a8..435c13a6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -49,9 +49,9 @@ try { generalSettings, } = await LiveSplit.loadStoredData(); - function requestWakeLock() { + async function requestWakeLock() { try { - (navigator as any)?.wakeLock?.request("screen"); + await (navigator as any)?.wakeLock?.request(); } catch { // It's fine if it fails. } diff --git a/src/ui/LSOEventSink.ts b/src/ui/LSOEventSink.ts index adb11aa7..0e102966 100644 --- a/src/ui/LSOEventSink.ts +++ b/src/ui/LSOEventSink.ts @@ -80,6 +80,7 @@ export class LSOEventSink { this.currentPhaseChanged(); this.currentSplitChanged(); + this.splitsModifiedChanged(); } public pause(): void { diff --git a/src/ui/LiveSplit.tsx b/src/ui/LiveSplit.tsx index a95d2d2b..bee2865e 100644 --- a/src/ui/LiveSplit.tsx +++ b/src/ui/LiveSplit.tsx @@ -828,7 +828,13 @@ export class LiveSplit extends React.Component { } catch { // It's fine if this fails. } - document.title = "*LiveSplit One"; + + // It's important that any change is at the end of the title, + // because at least Chrome then recognizes that it's an extension of + // the PWA name. Otherwise it would show: + // LiveSplit One - Window Title + // which would repeat LiveSplit One. + document.title = "LiveSplit One ●"; } else { try { navigator?.clearAppBadge(); diff --git a/src/util/FrameRate.ts b/src/util/FrameRate.ts index 736ec9f4..b27abf39 100644 --- a/src/util/FrameRate.ts +++ b/src/util/FrameRate.ts @@ -20,25 +20,30 @@ switch (navigator.platform) { export let batteryAwareFrameRate: FrameRate = batteryFrameRate; +let computePressure: FrameRate = FRAME_RATE_MATCH_SCREEN; + if ('PressureObserver' in window) { - try { - const observer = new (window as any).PressureObserver((records: any) => { - const state = records[0].state; - switch (state) { - case "serious": - batteryAwareFrameRate = FRAME_RATE_SERIOUS; - break; - case "critical": - batteryAwareFrameRate = FRAME_RATE_CRITICAL; - break; - default: - batteryAwareFrameRate = batteryFrameRate; - } - }); - observer.observe("cpu", { sampleInterval: 2_000 }); - } catch { - // The Compute Pressure API is not supported by the browser. - } + (async () => { + try { + const observer = new (window as any).PressureObserver((records: any) => { + const state = records[0].state; + switch (state) { + case "serious": + computePressure = FRAME_RATE_SERIOUS; + break; + case "critical": + computePressure = FRAME_RATE_CRITICAL; + break; + default: + computePressure = FRAME_RATE_MATCH_SCREEN; + } + updateBatteryAwareFrameRate(); + }); + await observer.observe("cpu", { sampleInterval: 2_000 }); + } catch { + // The Compute Pressure API is not supported by every browser. + } + })(); } (async () => { @@ -48,8 +53,22 @@ if ('PressureObserver' in window) { batteryFrameRate = batteryApi.charging === true ? FRAME_RATE_MATCH_SCREEN : FRAME_RATE_LOW_POWER; + updateBatteryAwareFrameRate(); }; } catch { // The battery API is not supported by every browser. } })(); + +function updateBatteryAwareFrameRate() { + // Choose the lower of the two frame rates. If one of them is a string, it + // is "Match Screen", which has the lowest priority. + + if (typeof batteryFrameRate === "string") { + batteryAwareFrameRate = computePressure; + } else if (typeof computePressure === "string") { + batteryAwareFrameRate = batteryFrameRate; + } else { + batteryAwareFrameRate = Math.min(batteryFrameRate, computePressure); + } +}