[F] Fix settings persistence
This commit is contained in:
@@ -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 })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,19 +6,15 @@
|
|||||||
import ProgressList from "$lib/ui/ProgressList.svelte"
|
import ProgressList from "$lib/ui/ProgressList.svelte"
|
||||||
import { goto } from "$app/navigation"
|
import { goto } from "$app/navigation"
|
||||||
import { getI18n, useMsg } from "$lib/i18n"
|
import { getI18n, useMsg } from "$lib/i18n"
|
||||||
import { typingSettingsDefault } from "$lib/types"
|
|
||||||
import { getNextSong } from "$lib/ui/player/SongSwitching.js"
|
import { getNextSong } from "$lib/ui/player/SongSwitching.js"
|
||||||
|
import { UserDataSync } from "$lib/ui/player/state.svelte"
|
||||||
|
|
||||||
const t = getI18n().song.mode
|
const t = getI18n().song.mode
|
||||||
const getMsg = useMsg()
|
const getMsg = useMsg()
|
||||||
|
|
||||||
let { data } = $props()
|
let { data } = $props()
|
||||||
|
|
||||||
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
|
const ud = new UserDataSync(data)
|
||||||
$effect(() => { API.saveUserData({ typingSettings: settings }) })
|
|
||||||
|
|
||||||
let loc = $state(data.user.data.loc)
|
|
||||||
$effect(() => { API.saveUserData({ loc }) })
|
|
||||||
|
|
||||||
let taskStatus = $state({
|
let taskStatus = $state({
|
||||||
lyrics: false,
|
lyrics: false,
|
||||||
@@ -89,7 +85,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</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} />
|
<ProgressList percentage={progressPercentage} items={progressItems} />
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PageProps } from "./$types"
|
import type { PageProps } from "./$types"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { typingSettingsDefault } from "$lib/types"
|
|
||||||
import { processLrcLine, dedupLines, type ProcLrcLine } from "$lib/ui/player/IMEHelper"
|
import { processLrcLine, dedupLines, type ProcLrcLine } from "$lib/ui/player/IMEHelper"
|
||||||
import "$lib/ext.ts"
|
import "$lib/ext.ts"
|
||||||
import { API } from "$lib/client"
|
import { API } from "$lib/client"
|
||||||
import { MusicControl } from "$lib/ui/player/MusicControl"
|
import { MusicControl } from "$lib/ui/player/MusicControl"
|
||||||
import Lyrics from "$lib/ui/player/Lyrics.svelte"
|
import Lyrics from "$lib/ui/player/Lyrics.svelte"
|
||||||
import PlayerAppBar from "$lib/ui/player/PlayerAppBar.svelte"
|
import PlayerAppBar from "$lib/ui/player/PlayerAppBar.svelte"
|
||||||
|
import { UserDataSync } from "$lib/ui/player/state.svelte"
|
||||||
import { getI18n } from "$lib/i18n"
|
import { getI18n } from "$lib/i18n"
|
||||||
import { Layer } from "m3-svelte";
|
import { Layer } from "m3-svelte";
|
||||||
|
|
||||||
@@ -16,11 +16,7 @@
|
|||||||
let { data }: PageProps = $props()
|
let { data }: PageProps = $props()
|
||||||
|
|
||||||
let li = $state(0)
|
let li = $state(0)
|
||||||
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
|
const ud = new UserDataSync(data)
|
||||||
$effect(() => { API.saveUserData({ typingSettings: settings }) })
|
|
||||||
|
|
||||||
let loc = $state(data.user.data.loc)
|
|
||||||
$effect(() => { API.saveUserData({ loc }) })
|
|
||||||
|
|
||||||
let vocalsVolume = $state(data.user.data.vocalsVolume ?? 100)
|
let vocalsVolume = $state(data.user.data.vocalsVolume ?? 100)
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -31,7 +27,7 @@
|
|||||||
let isPlaying = $state(false)
|
let isPlaying = $state(false)
|
||||||
|
|
||||||
// Process lyrics
|
// Process lyrics
|
||||||
const isHideRepeated = $derived(settings.hideRepeated)
|
const isHideRepeated = $derived(ud.settings.hideRepeated)
|
||||||
let deduplicatedLyrics = $derived(dedupLines(data.lrc, isHideRepeated))
|
let deduplicatedLyrics = $derived(dedupLines(data.lrc, isHideRepeated))
|
||||||
let processedLrc: ProcLrcLine[] = $derived(deduplicatedLyrics.map(line => processLrcLine(line.lyric)))
|
let processedLrc: ProcLrcLine[] = $derived(deduplicatedLyrics.map(line => processLrcLine(line.lyric)))
|
||||||
|
|
||||||
@@ -91,7 +87,7 @@
|
|||||||
|
|
||||||
<svelte:window onclick={() => musicControl?.ready()} onkeydown={() => musicControl?.ready()}/>
|
<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">
|
<div class="vbox p-content py-4 gap-2 mfg-on-surface-variant">
|
||||||
{#if data.audioData.vocalsUrl}
|
{#if data.audioData.vocalsUrl}
|
||||||
@@ -113,7 +109,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Lyrics lines={processedLrc} currentLineIndex={li} {settings} {states} />
|
<Lyrics lines={processedLrc} currentLineIndex={li} settings={ud.settings} {states} />
|
||||||
|
|
||||||
<button
|
<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"
|
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"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import Lyrics from "$lib/ui/player/Lyrics.svelte"
|
import Lyrics from "$lib/ui/player/Lyrics.svelte"
|
||||||
import PlayerAppBar from "$lib/ui/player/PlayerAppBar.svelte"
|
import PlayerAppBar from "$lib/ui/player/PlayerAppBar.svelte"
|
||||||
import { getI18n } from "$lib/i18n"
|
import { getI18n } from "$lib/i18n"
|
||||||
|
import { UserDataSync } from "$lib/ui/player/state.svelte"
|
||||||
|
|
||||||
const t = getI18n().song.play
|
const t = getI18n().song.play
|
||||||
|
|
||||||
@@ -25,15 +26,10 @@
|
|||||||
let inp = $state("")
|
let inp = $state("")
|
||||||
|
|
||||||
// Settings stored in user data
|
// Settings stored in user data
|
||||||
let settings = $state(data.user.data?.typingSettings ?? typingSettingsDefault)
|
const ud = new UserDataSync(data)
|
||||||
$effect(() => { API.saveUserData({ typingSettings: settings }) })
|
|
||||||
|
|
||||||
// Playlist location state
|
|
||||||
let loc = $state(data.user.data.loc)
|
|
||||||
$effect(() => { API.saveUserData({ loc }) })
|
|
||||||
|
|
||||||
// Process each line into segments with swi (start word index) and kanji/kana
|
// 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 deduplicatedLyrics = $derived(dedupLines(data.lrc, isHideRepeated))
|
||||||
let processedLrc: ProcLrcLine[] = $derived(deduplicatedLyrics.map(line => processLrcLine(line.lyric)))
|
let processedLrc: ProcLrcLine[] = $derived(deduplicatedLyrics.map(line => processLrcLine(line.lyric)))
|
||||||
// State tracking for each kana character: UNSEEN, RIGHT, WRONG
|
// State tracking for each kana character: UNSEEN, RIGHT, WRONG
|
||||||
@@ -146,10 +142,10 @@
|
|||||||
totalTyped, totalRight, startTime, statsHistory
|
totalTyped, totalRight, startTime, statsHistory
|
||||||
})
|
})
|
||||||
|
|
||||||
if (loc?.currentPlaylistId) {
|
if (ud.loc) {
|
||||||
loc.isFinished = true
|
ud.loc.isFinished = true
|
||||||
loc.lastResultId = res.id
|
ud.loc.lastResultId = res.id
|
||||||
await API.saveUserData({ loc })
|
await API.saveUserData({ loc: ud.loc })
|
||||||
}
|
}
|
||||||
|
|
||||||
goto(`/results/${res.id}`, { replaceState: true })
|
goto(`/results/${res.id}`, { replaceState: true })
|
||||||
@@ -158,7 +154,7 @@
|
|||||||
|
|
||||||
<svelte:window onclick={() => musicControl?.ready()} onkeydown={() => musicControl?.ready()}/>
|
<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} />
|
<LinearProgress percent={progress} />
|
||||||
|
|
||||||
@@ -180,4 +176,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Lines -->
|
<!-- 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()} />
|
||||||
Reference in New Issue
Block a user