feat: migrate runtime backend to node server

This commit is contained in:
victo
2026-04-08 16:41:29 +08:00
parent 9d2fc9e4b8
commit a83841ff2d
70 changed files with 8239 additions and 1561 deletions

View File

@@ -1,13 +1,64 @@
import {useCallback, useEffect, useState} from 'react';
import {useCallback, useEffect, useRef, useState} from 'react';
import {clampVolume, readSavedSettings, writeSavedSettings} from '../persistence/gameSettingsStorage';
import {
clampVolume,
DEFAULT_MUSIC_VOLUME,
} from '../persistence/gameSettingsStorage';
import { getSettings, putSettings } from '../services/storageService';
export function useGameSettings() {
const [musicVolume, setMusicVolumeState] = useState(() => readSavedSettings().musicVolume);
const [musicVolume, setMusicVolumeState] = useState(DEFAULT_MUSIC_VOLUME);
const [hasHydratedSettings, setHasHydratedSettings] = useState(false);
const lastSyncedVolumeRef = useRef(DEFAULT_MUSIC_VOLUME);
useEffect(() => {
writeSavedSettings({musicVolume});
}, [musicVolume]);
let isActive = true;
void getSettings()
.then((settings) => {
if (!isActive) return;
const nextVolume = clampVolume(settings.musicVolume);
lastSyncedVolumeRef.current = nextVolume;
setMusicVolumeState(nextVolume);
})
.catch((error) => {
console.warn('[useGameSettings] failed to load remote settings', error);
})
.finally(() => {
if (isActive) {
setHasHydratedSettings(true);
}
});
return () => {
isActive = false;
};
}, []);
useEffect(() => {
if (!hasHydratedSettings) {
return;
}
if (lastSyncedVolumeRef.current === musicVolume) {
return;
}
let isActive = true;
void putSettings({musicVolume})
.then((settings) => {
if (!isActive) return;
lastSyncedVolumeRef.current = clampVolume(settings.musicVolume);
})
.catch((error) => {
console.warn('[useGameSettings] failed to persist remote settings', error);
});
return () => {
isActive = false;
};
}, [hasHydratedSettings, musicVolume]);
const setMusicVolume = useCallback((value: number) => {
setMusicVolumeState(clampVolume(value));