Skip to content

Commit b11c0ab

Browse files
committed
refactor(synced-lyrics): extract helpers for provider switching and word rendering
1 parent 749d65a commit b11c0ab

File tree

2 files changed

+60
-72
lines changed

2 files changed

+60
-72
lines changed

src/plugins/synced-lyrics/renderer/components/LyricsPicker.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export const providerIdx = createMemo(() =>
3535
providerNames.indexOf(lyricsStore.provider),
3636
);
3737

38+
const FAST_SWITCH_MS = 2500;
39+
3840
const shouldSwitchProvider = (providerData: ProviderState) => {
3941
if (providerData.state === 'error') return true;
4042
if (providerData.state === 'fetching') return true;
@@ -80,7 +82,7 @@ export const LyricsPicker = (props: {
8082
createSignal<ProviderName | null>(null);
8183

8284
const favoriteProviderKey = (id: string) => `ytmd-sl-starred-${id}`;
83-
const switchProvider = (provider: ProviderName, fastMs = 2500) => {
85+
const switchProvider = (provider: ProviderName, fastMs = FAST_SWITCH_MS) => {
8486
requestFastScroll(fastMs);
8587
setLyricsStore('provider', provider);
8688
};
@@ -99,7 +101,13 @@ export const LyricsPicker = (props: {
99101
return;
100102
}
101103

102-
const parseResult = LocalStorageSchema.safeParse(JSON.parse(value));
104+
let parsed: unknown = null;
105+
try {
106+
parsed = JSON.parse(value);
107+
} catch {
108+
parsed = null;
109+
}
110+
const parseResult = LocalStorageSchema.safeParse(parsed);
103111
if (parseResult.success) {
104112
setLyricsStore('provider', parseResult.data.provider);
105113
setStarredProvider(parseResult.data.provider);
@@ -147,7 +155,7 @@ export const LyricsPicker = (props: {
147155
if (!hasManuallySwitchedProvider()) {
148156
const starred = starredProvider();
149157
if (starred !== null) {
150-
switchProvider(starred, 2500);
158+
switchProvider(starred);
151159
return;
152160
}
153161

@@ -161,30 +169,25 @@ export const LyricsPicker = (props: {
161169
force ||
162170
providerBias(lyricsStore.provider) < providerBias(provider)
163171
) {
164-
switchProvider(provider, 2500);
172+
switchProvider(provider);
165173
}
166174
}
167175
});
168176

169177
const next = () => {
170178
setHasManuallySwitchedProvider(true);
171-
setLyricsStore('provider', (prevProvider) => {
172-
const idx = providerNames.indexOf(prevProvider);
173-
const nextProvider = providerNames[(idx + 1) % providerNames.length];
174-
switchProvider(nextProvider, 2500);
175-
return nextProvider;
176-
});
179+
const nextProvider =
180+
providerNames[(providerIdx() + 1) % providerNames.length];
181+
switchProvider(nextProvider);
177182
};
178183

179184
const previous = () => {
180185
setHasManuallySwitchedProvider(true);
181-
setLyricsStore('provider', (prevProvider) => {
182-
const idx = providerNames.indexOf(prevProvider);
183-
const prev =
184-
providerNames[(idx + providerNames.length - 1) % providerNames.length];
185-
switchProvider(prev, 2500);
186-
return prev;
187-
});
186+
const prev =
187+
providerNames[
188+
(providerIdx() + providerNames.length - 1) % providerNames.length
189+
];
190+
switchProvider(prev);
188191
};
189192

190193
const chevronLeft: YtIcons = 'yt-icons:chevron_left';
@@ -322,7 +325,7 @@ export const LyricsPicker = (props: {
322325
class="lyrics-picker-dot"
323326
onClick={() => {
324327
setHasManuallySwitchedProvider(true);
325-
switchProvider(providerNames[idx()], 2500);
328+
switchProvider(providerNames[idx()]);
326329
}}
327330
style={{
328331
background: idx() === providerIdx() ? 'white' : 'black',

src/plugins/synced-lyrics/renderer/components/SyncedLine.tsx

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,31 @@ interface SyncedLineProps {
2626
isFirstEmptyLine?: boolean;
2727
}
2828

29+
// small helpers
30+
const WORD_ANIM_DELAY_STEP = 0.05; // seconds per word index
31+
32+
const seekToMs = (ms: number) => {
33+
const precise = config()?.preciseTiming ?? false;
34+
_ytAPI?.seekTo(getSeekTime(ms, precise));
35+
};
36+
37+
const renderWordSpans = (input: string) => (
38+
<span>
39+
<For each={input.split(' ')}>
40+
{(word, index) => (
41+
<span
42+
style={{
43+
'transition-delay': `${index() * WORD_ANIM_DELAY_STEP}s`,
44+
'animation-delay': `${index() * WORD_ANIM_DELAY_STEP}s`,
45+
}}
46+
>
47+
<yt-formatted-string text={{ runs: [{ text: `${word} ` }] }} />
48+
</span>
49+
)}
50+
</For>
51+
</span>
52+
);
53+
2954
const EmptyLine = (props: SyncedLineProps) => {
3055
const states = createMemo(() => {
3156
const defaultText = config()?.defaultTextString ?? '';
@@ -40,16 +65,16 @@ const EmptyLine = (props: SyncedLineProps) => {
4065

4166
if (stepCount === 1) return 0;
4267

43-
let earlyCut: number;
44-
if (total > 3000) {
45-
earlyCut = 1000;
46-
} else if (total >= 1000) {
47-
const ratio = (total - 1000) / 2000;
48-
const addend = ratio * 500;
49-
earlyCut = 500 + addend;
50-
} else {
51-
earlyCut = Math.min(total * 0.8, total - 150);
52-
}
68+
const computeEarlyCut = (t: number) => {
69+
if (t > 3000) return 1000;
70+
if (t >= 1000) {
71+
const ratio = (t - 1000) / 2000;
72+
const addend = ratio * 500;
73+
return 500 + addend;
74+
}
75+
return Math.min(t * 0.8, t - 150);
76+
};
77+
const earlyCut = computeEarlyCut(total);
5378

5479
const effectiveTotal =
5580
total <= 1000
@@ -94,8 +119,7 @@ const EmptyLine = (props: SyncedLineProps) => {
94119
<div
95120
class={`synced-emptyline ${props.status} ${isFinalEmpty() ? 'final-empty' : ''} ${shouldRemovePadding() ? 'no-padding' : ''}`}
96121
onClick={() => {
97-
const precise = config()?.preciseTiming ?? false;
98-
_ytAPI?.seekTo(getSeekTime(props.line.timeInMs, precise));
122+
seekToMs(props.line.timeInMs);
99123
}}
100124
>
101125
<div class="description ytmusic-description-shelf-renderer" dir="auto">
@@ -162,8 +186,7 @@ export const SyncedLine = (props: SyncedLineProps) => {
162186
<div
163187
class={`synced-line ${props.status}`}
164188
onClick={() => {
165-
const precise = config()?.preciseTiming ?? false;
166-
_ytAPI?.seekTo(getSeekTime(props.line.timeInMs, precise));
189+
seekToMs(props.line.timeInMs);
167190
}}
168191
>
169192
<div class="description ytmusic-description-shelf-renderer" dir="auto">
@@ -193,53 +216,15 @@ export const SyncedLine = (props: SyncedLineProps) => {
193216
}}
194217
style={{ 'display': 'flex', 'flex-direction': 'column' }}
195218
>
196-
<span>
197-
<For each={text().split(' ')}>
198-
{(word, index) => {
199-
return (
200-
<span
201-
style={{
202-
'transition-delay': `${index() * 0.05}s`,
203-
'animation-delay': `${index() * 0.05}s`,
204-
}}
205-
>
206-
<yt-formatted-string
207-
text={{
208-
runs: [{ text: `${word} ` }],
209-
}}
210-
/>
211-
</span>
212-
);
213-
}}
214-
</For>
215-
</span>
219+
{renderWordSpans(text())}
216220

217221
<Show
218222
when={
219223
config()?.romanization &&
220224
simplifyUnicode(text()) !== simplifyUnicode(romanization())
221225
}
222226
>
223-
<span class="romaji">
224-
<For each={romanization().split(' ')}>
225-
{(word, index) => {
226-
return (
227-
<span
228-
style={{
229-
'transition-delay': `${index() * 0.05}s`,
230-
'animation-delay': `${index() * 0.05}s`,
231-
}}
232-
>
233-
<yt-formatted-string
234-
text={{
235-
runs: [{ text: `${word} ` }],
236-
}}
237-
/>
238-
</span>
239-
);
240-
}}
241-
</For>
242-
</span>
227+
<span class="romaji">{renderWordSpans(romanization())}</span>
243228
</Show>
244229
</div>
245230
</div>

0 commit comments

Comments
 (0)