[F] Fix settings persistence

This commit is contained in:
2025-11-25 21:17:37 +08:00
parent 02da7827af
commit 5aa29d13db
4 changed files with 41 additions and 29 deletions
+24
View File
@@ -0,0 +1,24 @@
import { API } from "$lib/client"
import { typingSettingsDefault, type TypingSettings, type UserData } from "$lib/types"
export class UserDataSync {
settings = $state<TypingSettings>(typingSettingsDefault)
loc = $state<UserData['loc']>(undefined)
constructor(data: any) {
this.settings = data.user.data?.typingSettings ?? typingSettingsDefault
this.loc = data.user.data.loc
$effect(() => {
data.user.data = data.user.data || {}
data.user.data.typingSettings = this.settings
API.saveUserData({ typingSettings: this.settings })
})
$effect(() => {
data.user.data = data.user.data || {}
data.user.data.loc = this.loc
API.saveUserData({ loc: this.loc })
})
}
}
+3 -7
View File
@@ -6,19 +6,15 @@
import ProgressList from "$lib/ui/ProgressList.svelte"
import { goto } from "$app/navigation"
import { getI18n, useMsg } from "$lib/i18n"
import { typingSettingsDefault } from "$lib/types"
import { getNextSong } from "$lib/ui/player/SongSwitching.js"
import { UserDataSync } from "$lib/ui/player/state.svelte"
const t = getI18n().song.mode
const getMsg = useMsg()
let { data } = $props()
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
$effect(() => { API.saveUserData({ typingSettings: settings }) })
let loc = $state(data.user.data.loc)
$effect(() => { API.saveUserData({ loc }) })
const ud = new UserDataSync(data)
let taskStatus = $state({
lyrics: false,
@@ -89,7 +85,7 @@
}
</script>
<PlayerAppBar song={data.song} bind:settings bind:loc playlist={data.playlist} />
<PlayerAppBar song={data.song} bind:settings={ud.settings} bind:loc={ud.loc} playlist={data.playlist} />
<ProgressList percentage={progressPercentage} items={progressItems} />
+5 -9
View File
@@ -1,13 +1,13 @@
<script lang="ts">
import type { PageProps } from "./$types"
import { onMount } from "svelte"
import { typingSettingsDefault } from "$lib/types"
import { processLrcLine, dedupLines, type ProcLrcLine } from "$lib/ui/player/IMEHelper"
import "$lib/ext.ts"
import { API } from "$lib/client"
import { MusicControl } from "$lib/ui/player/MusicControl"
import Lyrics from "$lib/ui/player/Lyrics.svelte"
import PlayerAppBar from "$lib/ui/player/PlayerAppBar.svelte"
import { UserDataSync } from "$lib/ui/player/state.svelte"
import { getI18n } from "$lib/i18n"
import { Layer } from "m3-svelte";
@@ -16,11 +16,7 @@
let { data }: PageProps = $props()
let li = $state(0)
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
$effect(() => { API.saveUserData({ typingSettings: settings }) })
let loc = $state(data.user.data.loc)
$effect(() => { API.saveUserData({ loc }) })
const ud = new UserDataSync(data)
let vocalsVolume = $state(data.user.data.vocalsVolume ?? 100)
$effect(() => {
@@ -31,7 +27,7 @@
let isPlaying = $state(false)
// Process lyrics
const isHideRepeated = $derived(settings.hideRepeated)
const isHideRepeated = $derived(ud.settings.hideRepeated)
let deduplicatedLyrics = $derived(dedupLines(data.lrc, isHideRepeated))
let processedLrc: ProcLrcLine[] = $derived(deduplicatedLyrics.map(line => processLrcLine(line.lyric)))
@@ -91,7 +87,7 @@
<svelte:window onclick={() => musicControl?.ready()} onkeydown={() => musicControl?.ready()}/>
<PlayerAppBar song={data.song} bind:settings bind:loc showRomajiOnError={false} isKaraoke={true} disableHideRepeated playlist={data.playlist} />
<PlayerAppBar song={data.song} bind:settings={ud.settings} bind:loc={ud.loc} showRomajiOnError={false} isKaraoke={true} disableHideRepeated playlist={data.playlist} />
<div class="vbox p-content py-4 gap-2 mfg-on-surface-variant">
{#if data.audioData.vocalsUrl}
@@ -113,7 +109,7 @@
</div>
</div>
<Lyrics lines={processedLrc} currentLineIndex={li} {settings} {states} />
<Lyrics lines={processedLrc} currentLineIndex={li} settings={ud.settings} {states} />
<button
class="fixed bottom-6 right-6 z-5 size-64px cbox rounded-full surface-variant mbg-surface-container mfg-on-surface-variant shadow-lg hover:shadow-xl transition-all active:scale-90"
+9 -13
View File
@@ -12,6 +12,7 @@
import Lyrics from "$lib/ui/player/Lyrics.svelte"
import PlayerAppBar from "$lib/ui/player/PlayerAppBar.svelte"
import { getI18n } from "$lib/i18n"
import { UserDataSync } from "$lib/ui/player/state.svelte"
const t = getI18n().song.play
@@ -25,15 +26,10 @@
let inp = $state("")
// Settings stored in user data
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
$effect(() => { API.saveUserData({ typingSettings: settings }) })
// Playlist location state
let loc = $state(data.user.data.loc)
$effect(() => { API.saveUserData({ loc }) })
const ud = new UserDataSync(data)
// Process each line into segments with swi (start word index) and kanji/kana
const isHideRepeated = $derived(settings.hideRepeated && !data.audioUrl)
const isHideRepeated = $derived(ud.settings.hideRepeated && !data.audioUrl)
let deduplicatedLyrics = $derived(dedupLines(data.lrc, isHideRepeated))
let processedLrc: ProcLrcLine[] = $derived(deduplicatedLyrics.map(line => processLrcLine(line.lyric)))
// State tracking for each kana character: UNSEEN, RIGHT, WRONG
@@ -146,10 +142,10 @@
totalTyped, totalRight, startTime, statsHistory
})
if (loc?.currentPlaylistId) {
loc.isFinished = true
loc.lastResultId = res.id
await API.saveUserData({ loc })
if (ud.loc) {
ud.loc.isFinished = true
ud.loc.lastResultId = res.id
await API.saveUserData({ loc: ud.loc })
}
goto(`/results/${res.id}`, { replaceState: true })
@@ -158,7 +154,7 @@
<svelte:window onclick={() => musicControl?.ready()} onkeydown={() => musicControl?.ready()}/>
<PlayerAppBar song={data.song} bind:settings bind:loc disableHideRepeated={!!data.audioUrl} playlist={data.playlist} />
<PlayerAppBar song={data.song} bind:settings={ud.settings} bind:loc={ud.loc} disableHideRepeated={!!data.audioUrl} playlist={data.playlist} />
<LinearProgress percent={progress} />
@@ -180,4 +176,4 @@
</div>
<!-- Lines -->
<Lyrics lines={processedLrc} currentLineIndex={li} currentWordIndex={wi} {states} {settings} showCaret={true} onLineClick={() => hiddenInput.focus()} />
<Lyrics lines={processedLrc} currentLineIndex={li} currentWordIndex={wi} {states} settings={ud.settings} showCaret={true} onLineClick={() => hiddenInput.focus()} />