Skip to content

Commit 83e2b99

Browse files
committed
Closed #65, #86
1 parent 7f035fe commit 83e2b99

File tree

8 files changed

+78
-27
lines changed

8 files changed

+78
-27
lines changed

Diff for: public/_locales/en/messages.json

+8
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@
124124
"description": "Lyrics use traditional chinese"
125125
},
126126

127+
"optionsLyricsTransform": {
128+
"message": "Lyrics transform"
129+
},
130+
131+
"optionsLyricsTransformDetail": {
132+
"message": "When using simplified Chinese, try to load the translated lyrics"
133+
},
134+
127135
"optionsLyricsPosition": {
128136
"message": "Where the lyrics show",
129137
"description": "Lyrics position option"

Diff for: public/_locales/zh/messages.json

+8
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@
9595
"message": "繁体中文歌词"
9696
},
9797

98+
"optionsLyricsTransform": {
99+
"message": "歌词转换"
100+
},
101+
102+
"optionsLyricsTransformDetail": {
103+
"message": "当使用简体中文时会尝试加载翻译的歌词"
104+
},
105+
98106
"optionsLyricsPosition": {
99107
"message": "歌词显示位置"
100108
},

Diff for: src/common/constants.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export enum ContextItems {
3737
export const LyricsPositions = ['page', 'pip'] as const;
3838
export const LyricsAlign = ['left', 'center'] as const;
3939
export const LyricsFontFamily = ['CircularSp', 'Sans-Serif', 'Serif', 'Cursive'] as const;
40+
export const LyricsTransform = ['Origin', 'Simplified', 'Traditional'] as const;
4041
export interface Options {
4142
cid: string;
4243
'font-size': string;
@@ -48,8 +49,10 @@ export interface Options {
4849
'use-unreviewed-lyrics': SwitchValue;
4950
'show-on': (typeof LyricsPositions)[number];
5051
'lyrics-align': (typeof LyricsAlign)[number];
52+
/**@deprecated */
5153
'traditional-chinese-lyrics': SwitchValue;
52-
// Deprecated
54+
'lyrics-transform': (typeof LyricsTransform)[number];
55+
/**@deprecated */
5356
'lyrics-smooth-scroll'?: SwitchValue;
5457
'strict-mode'?: SwitchValue;
5558
}

Diff for: src/options/app.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { customElement, refobject, RefObject } from '@mantou/gem/lib/decorators';
22
import { GemElement, html } from '@mantou/gem/lib/element';
33

4-
import { Options, LyricsPositions, LyricsAlign, LyricsFontFamily } from '../common/constants';
4+
import {
5+
Options,
6+
LyricsPositions,
7+
LyricsAlign,
8+
LyricsFontFamily,
9+
LyricsTransform,
10+
} from '../common/constants';
511
import { sendEvent, events } from '../common/ga';
612
import { theme } from '../common/theme';
713

@@ -131,11 +137,15 @@ export class OptionsApp extends GemElement<State> {
131137
default-value=${options['clean-lyrics']}
132138
></ele-switch>
133139
</ele-form-item>
134-
<ele-form-item label="${i18n.optionsTraditionalChineseLyrics()} *">
135-
<ele-switch
136-
name=${'traditional-chinese-lyrics' as keyof Options}
137-
default-value=${options['traditional-chinese-lyrics']}
138-
></ele-switch>
140+
<ele-form-item
141+
label="${i18n.optionsLyricsTransform()} *"
142+
description=${i18n.optionsLyricsTransformDetail()}
143+
>
144+
<ele-select
145+
name=${'lyrics-transform' as keyof Options}
146+
default-value=${options['lyrics-transform']}
147+
.options=${LyricsTransform.map((e) => ({ label: e, value: e }))}
148+
></ele-select>
139149
</ele-form-item>
140150
<ele-form-item
141151
?hidden=${!document.pictureInPictureEnabled}

Diff for: src/options/store.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const defaultOptions: Options = {
1717
'use-unreviewed-lyrics': 'on',
1818
'toggle-shortcut': 'l',
1919
'traditional-chinese-lyrics': uiLanguage === 'zh-TW' || uiLanguage === 'zh-HK' ? 'on' : 'off',
20+
'lyrics-transform': 'Origin',
2021
};
2122

2223
export async function getOptions() {

Diff for: src/page/lyrics.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('parse lyrics', () => {
2323
expect(parseLyrics('[02:01]\n')).toEqual<Lyric>(null);
2424
expect(parseLyrics('[02:01]编')).toEqual<Lyric>([{ startTime: 121, text: '编' }]);
2525
expect(parseLyrics('[02:01]编:xx')).toEqual<Lyric>([{ startTime: 121, text: '编: xx' }]);
26-
expect(parseLyrics('[02:01]编:', { useTChinese: true })).toEqual<Lyric>([
26+
expect(parseLyrics('[02:01]编:', { lyricsTransform: 'Traditional' })).toEqual<Lyric>([
2727
{ startTime: 121, text: '編:' },
2828
]);
2929
expect(parseLyrics('[02:01]编:', { cleanLyrics: true })).toEqual<Lyric>(null);

Diff for: src/page/lyrics.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { sify as toSimplified, tify as toTraditional } from 'chinese-conv';
22

3-
import { isProd } from '../common/constants';
3+
import { Options, isProd } from '../common/constants';
44

55
import { configPromise } from './config';
66
import { optionsPromise } from './options';
@@ -47,6 +47,9 @@ interface SongResult {
4747
lrc?: {
4848
lyric?: string;
4949
};
50+
tlyric?: {
51+
lyric?: string;
52+
};
5053
}
5154

5255
// Convert all into English punctuation marks for processing
@@ -378,11 +381,12 @@ export async function matchingLyrics(
378381

379382
export async function fetchLyric(songId: number, fetchOptions?: RequestInit) {
380383
const { API_HOST } = await configPromise;
381-
const { lrc }: SongResult = await request(
384+
const { lrc, tlyric }: SongResult = await request(
382385
`${API_HOST}/lyric?${new URLSearchParams({ id: String(songId) })}`,
383386
fetchOptions,
384387
);
385-
return lrc?.lyric || '';
388+
const options = await optionsPromise;
389+
return (options['lyrics-transform'] === 'Simplified' && tlyric?.lyric) || lrc?.lyric || '';
386390
}
387391

388392
class Line {
@@ -399,7 +403,7 @@ export type Lyric = Line[] | null;
399403

400404
export interface ParseLyricsOptions {
401405
cleanLyrics?: boolean;
402-
useTChinese?: boolean;
406+
lyricsTransform?: Options['lyrics-transform'];
403407
keepPlainText?: boolean;
404408
}
405409

@@ -431,7 +435,7 @@ export function parseLyrics(lyricStr: string, options: ParseLyricsOptions = {})
431435
if (textIndex > -1) {
432436
text = matchResult.splice(textIndex, 1)[0];
433437
text = capitalize(normalize(text, false));
434-
text = toSimplified(text).replace(/\.|,|\?|!|;$/u, '');
438+
text = text.replace(/\.|,|\?|!|;$/u, '');
435439
}
436440
if (!matchResult.length && options.keepPlainText) {
437441
return [new Line(text)];
@@ -444,7 +448,19 @@ export function parseLyrics(lyricStr: string, options: ParseLyricsOptions = {})
444448
if (!isNaN(min)) {
445449
if (!options.cleanLyrics || !otherInfoRegexp.test(text)) {
446450
result.startTime = min * 60 + sec;
447-
result.text = options.useTChinese ? toTraditional(text) : text;
451+
switch (options.lyricsTransform) {
452+
case 'Simplified': {
453+
result.text = toSimplified(text);
454+
break;
455+
}
456+
case 'Traditional': {
457+
result.text = toTraditional(text);
458+
break;
459+
}
460+
default:
461+
result.text = text;
462+
break;
463+
}
448464
}
449465
} else if (!options.cleanLyrics && key && value) {
450466
result.text = `${key.toUpperCase()}: ${value}`;

Diff for: src/page/share-data.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export class SharedData {
136136
} else {
137137
this._lyrics = parseLyrics(lyricsStr, {
138138
cleanLyrics: options['clean-lyrics'] === 'on',
139-
useTChinese: options['traditional-chinese-lyrics'] === 'on',
139+
lyricsTransform: options['lyrics-transform'],
140140
});
141141
}
142142
}
@@ -167,14 +167,17 @@ export class SharedData {
167167
const options = await optionsPromise;
168168
const parseLyricsOptions = {
169169
cleanLyrics: options['clean-lyrics'] === 'on',
170-
useTChinese: options['traditional-chinese-lyrics'] === 'on',
170+
lyricsTransform: options['lyrics-transform'],
171171
};
172-
const { list, id } = await matchingLyrics(this.req, {
173-
getAudioElement: () => audio,
174-
fetchOptions,
175-
});
172+
const [{ list, id }, remoteData] = await Promise.all([
173+
matchingLyrics(this.req, {
174+
getAudioElement: () => audio,
175+
fetchOptions,
176+
}),
177+
getSong(this.req, fetchOptions),
178+
]);
179+
if (id === 0 && (await this._restoreLyrics(true))) return;
176180
this._list = list;
177-
const remoteData = await getSong(this.req, fetchOptions);
178181
const reviewed = options['use-unreviewed-lyrics'] === 'on' || remoteData?.reviewed;
179182
const isSelf = remoteData?.user === options.cid;
180183
if (isSelf && remoteData?.lyric) {
@@ -259,8 +262,7 @@ export class SharedData {
259262
this._name = name;
260263
this._artists = artists;
261264
// case1: spotify metadata API call before of UI update
262-
const succuss = await this._restoreCurrentTrackAndLyrics();
263-
if (!succuss) {
265+
if (!(await this._restoreLyrics())) {
264266
await this._matching({ signal: this._abortController.signal });
265267
}
266268
} catch (e) {
@@ -276,23 +278,26 @@ export class SharedData {
276278
if (getCache(info.name, info.artists)) return;
277279
setCache(info);
278280
// case2: spotify metadata API call after of UI update
281+
// current behavior
279282
if (this.name === info.name && this.artists === info.artists) {
280-
const succuss = await this._restoreCurrentTrackAndLyrics();
281-
if (succuss) {
283+
if (await this._restoreLyrics()) {
282284
this._cancelRequest();
283285
}
284286
}
285287
}
286288

287-
private async _restoreCurrentTrackAndLyrics() {
289+
private async _restoreLyrics(isForce = false) {
288290
const cache = getCache(this.name, this.artists);
289291
if (cache) {
290292
this._duration = cache.duration;
291293
if (cache.lyrics || cache.getLyrics) {
292294
try {
293295
const lyrics = cache.lyrics || (await (cache.promiseLyrics ||= cache.getLyrics?.()));
294296
if (lyrics) {
295-
this._lyrics = cache.lyrics = lyrics;
297+
cache.lyrics = lyrics;
298+
// 如果使用简体歌词,那么只更新缓存
299+
if (!isForce && (await optionsPromise)['lyrics-transform'] === 'Simplified') return;
300+
this._lyrics = lyrics;
296301
return true;
297302
}
298303
} catch {

0 commit comments

Comments
 (0)