Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default defineConfig(
"**/.vitepress/",
"native/*/index.d.ts",
".github/scripts/",
"plugins/",
]),
tseslint.configs.recommended,
{ languageOptions: { globals: autoImports.globals } },
Expand Down
16 changes: 9 additions & 7 deletions src/components/settings/custom/PluginList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ onMounted(() => {
if (!loaded.value) void pluginsStore.load();
});

/** 控制类插件 ready 时声明的设置 schema(配置弹窗用) */
const controlSettings = (info: PluginInfo) => {
/** 插件 ready 时声明的设置 schema(配置弹窗用) */
const pluginSettings = (info: PluginInfo) => {
if (info.status.state !== "ready") return [];
return info.status.settings ?? [];
};
Expand Down Expand Up @@ -132,13 +132,15 @@ const onSettingChange = async (pluginId: string, key: string, value: unknown): P
await pluginsStore.setSetting(pluginId, key, value);
};

/** 当前打开配置弹窗的控制类插件 */
const settingsDialogInfo = computed(
() => controlPlugins.value.find((info) => info.manifest.id === settingsDialogId.value) ?? null,
);
/** 当前打开配置弹窗的插件(支持音源类与控制类) */
const settingsDialogInfo = computed(() => {
if (!settingsDialogId.value) return null;
const allPlugins = [...sourcePlugins.value, ...controlPlugins.value];
return allPlugins.find((info) => info.manifest.id === settingsDialogId.value) ?? null;
});
/** 弹窗内设置表单的 schema 与当前值 */
const settingsDialogSchema = computed(() =>
settingsDialogInfo.value ? controlSettings(settingsDialogInfo.value) : [],
settingsDialogInfo.value ? pluginSettings(settingsDialogInfo.value) : [],
);
const settingsDialogValues = computed(() => settingsDialogInfo.value?.settingsValues ?? {});

Expand Down
4 changes: 4 additions & 0 deletions src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@
"label": "Auto-Upgrade Lyric Format",
"description": "Fetch a higher-ranked format from other platforms when the current one is low"
},
"preferPluginLyric": {
"label": "Prefer Plugin Lyrics",
"description": "Query plugins first and fall back to built-in platforms on a miss; when off, plugins are only a last resort"
},
"detectBackgroundLyrics": {
"label": "Auto-Detect Background Lyrics",
"description": "Detect backing vocals from brackets. Disable this if lyrics are misdetected"
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,10 @@
"label": "自动升级歌词格式",
"description": "当前歌词格式较低时,从其他平台获取更高级的格式覆盖"
},
"preferPluginLyric": {
"label": "优先使用插件歌词",
"description": "开启后先向插件请求歌词,未命中再回落到内置平台;关闭时插件仅作为兜底"
},
"detectBackgroundLyrics": {
"label": "自动识别背景歌词",
"description": "根据括号识别背景人声,误判时可关闭"
Expand Down
4 changes: 4 additions & 0 deletions src/services/download/lyric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
resolveLocalRepoLyric,
resolveOnlineByPreference,
resolvePluginLyric,
resolvePreferredPluginLyric,
resolveStreamingByPreference,
resolveTTMLOverlay,
type OnlineResult,
Expand Down Expand Up @@ -60,6 +61,9 @@ const resolveOnlineDownloadLyric = async (
export const resolveDownloadLyric = async (track: Track): Promise<DownloadLyric | null> => {
const local = toUsableDownloadLyric(await resolveLocalRepoLyric(track));
if (local) return local;
// 插件首选
const preferredPlugin = toUsableDownloadLyric(await resolvePreferredPluginLyric(track));
Comment thread
kid141252010 marked this conversation as resolved.
Outdated
if (preferredPlugin) return preferredPlugin;
// 流媒体
if (track.source === "streaming") {
return (
Expand Down
21 changes: 21 additions & 0 deletions src/services/lyric/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
resolveLocalRepoLyric,
resolveOnlineByPreference,
resolvePluginLyric,
resolvePreferredPluginLyric,
resolveStreamingByPreference,
resolveTTMLOverlay,
type LocalLyric,
Expand Down Expand Up @@ -136,6 +137,19 @@ const tryPluginFallback = async (token: number, track: Track): Promise<boolean>
return resolved ? commitResolvedAndHasParsed(token, resolved) : false;
};

/**
* 插件歌词作为首选来源:开启偏好时在所有网络来源之前尝试
* 关闭时不发起请求,插件仍按原有顺序兜底
* @param token - 竞态 token
* @param track - 歌曲信息
* @returns 是否已提交有效歌词
*/
const tryPreferredPlugin = async (token: number, track: Track): Promise<boolean> => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

按照新方案,该函数需要删除;在现有的 loader.ts 中,若插件优选开启,则改为:在线平台和插件同时请求,先到先 commit

const resolved = await resolvePreferredPluginLyric(track);
if (token !== currentToken) return false;
return resolved ? commitResolvedAndHasParsed(token, resolved) : false;
};

/**
* 流媒体歌词加载:按来源偏好解析,失败后使用插件和内嵌歌词兜底
* @param token - 竞态 token
Expand Down Expand Up @@ -213,6 +227,9 @@ export const loadForTrack = async (detail: TrackDetail | null): Promise<void> =>
// 本地 TTML 歌词库最高优先
if (await tryLocalRepo(token, track)) return;
if (token !== currentToken) return;
// 插件首选:仅在开启偏好时先于所有网络来源
if (await tryPreferredPlugin(token, track)) return;
if (token !== currentToken) return;
// 在线歌曲(任一在线平台)
if (isPlatform(track.source)) {
await loadPlatformLyric(token, track);
Expand Down Expand Up @@ -262,6 +279,9 @@ const refreshPreference = async (): Promise<void> => {
// 本地 TTML 歌词库最高优先
if (await tryLocalRepo(token, track)) return;
if (token !== currentToken) return;
// 插件首选
if (await tryPreferredPlugin(token, track)) return;
if (token !== currentToken) return;
if (track.source === "streaming") {
await loadStreamingLyric(token, track, media.detail);
return;
Expand Down Expand Up @@ -302,6 +322,7 @@ export const watchLyricPreference = (): void => {
() => [
settings.lyric.lyricSourcePreference,
settings.lyric.smartPreferOnline,
settings.lyric.preferPluginLyric,
settings.lyric.detectBackgroundLyrics,
settings.system.lyric.enableOnlineTTMLLyric,
settings.system.localLyric.enableLocalTTMLOverride,
Expand Down
1 change: 1 addition & 0 deletions src/services/lyric/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const buildContextKey = (): string => {
settings.lyric.lyricSourceOrder,
settings.lyric.lyricFormatOrder,
settings.lyric.smartPreferOnline,
settings.lyric.preferPluginLyric,
settings.system.lyric.enableOnlineTTMLLyric,
settings.system.localLyric.enableLocalTTMLOverride,
settings.system.localLyric.repoDir,
Expand Down
19 changes: 19 additions & 0 deletions src/services/lyric/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,21 @@ export const resolvePluginLyric = async (track: Track): Promise<ResolvedLyric |
return null;
};

/** 插件歌词是否作为首选来源(本地 TTML 仓库仍最高) */
export const isPluginLyricPreferred = (): boolean =>
useSettingsStore().lyric.preferPluginLyric === true;

/**
* 插件歌词作为首选时的前置尝试
* 关闭该偏好时不发起任何插件请求,保持原有兜底语义
* @param track - 歌曲信息
* @returns 命中的插件歌词,未开启或未命中返回 null
*/
export const resolvePreferredPluginLyric = async (track: Track): Promise<ResolvedLyric | null> => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

按照新方案,该函数需要删除

if (!isPluginLyricPreferred()) return null;
return resolvePluginLyric(track);
};

/**
* 为下一首歌曲解析最终歌词结果
* 本地歌曲依赖实际加载后的 TrackDetail,不在此处提前解析
Expand All @@ -311,6 +326,10 @@ export const resolveLyricForPreload = async (
if (!shouldContinue()) return null;
if (localRepo) return localRepo;

const preferredPlugin = await resolvePreferredPluginLyric(track);
if (!shouldContinue()) return null;
if (preferredPlugin) return preferredPlugin;

if (track.source === "streaming") {
const streaming = await resolveStreamingByPreference(track, shouldContinue);
if (!shouldContinue()) return null;
Expand Down
1 change: 1 addition & 0 deletions src/services/nextTrackPreloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ export const installNextTrackPreloadWatchers = (): void => {
settings.lyric.lyricSourceOrder.join(","),
settings.lyric.lyricFormatOrder.join(","),
settings.lyric.smartPreferOnline,
settings.lyric.preferPluginLyric,
settings.system.lyric.enableOnlineTTMLLyric,
settings.system.localLyric.enableLocalTTMLOverride,
settings.system.localLyric.repoDir,
Expand Down
6 changes: 6 additions & 0 deletions src/settings/categories/lyric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ const lyricCategory: SettingCategory = {
},
],
},
{
key: "preferPluginLyric",
type: "switch",
binding: { store: "settings", path: "lyric.preferPluginLyric" },
defaultValue: false,
},
{
key: "lyricSourceOrder",
type: "custom",
Expand Down
1 change: 1 addition & 0 deletions src/stores/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const useSettingsStore = defineStore(
lyricSourceOrder: [...DEFAULT_LYRIC_SOURCE_ORDER],
lyricFormatOrder: [...DEFAULT_LYRIC_FORMAT_ORDER],
smartPreferOnline: false,
preferPluginLyric: false,
detectBackgroundLyrics: true,
cjkTransform: "none",
adaptiveFontSize: true,
Expand Down
2 changes: 2 additions & 0 deletions src/types/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ export interface LyricSettings {
lyricFormatOrder: LyricFormatOrder;
/** 智能选择是否优先在线 */
smartPreferOnline: boolean;
/** 插件歌词优先于内置来源(仅次于本地 TTML 歌词库) */
preferPluginLyric: boolean;
/** 自动识别背景歌词 */
detectBackgroundLyrics: boolean;
/** 中文繁简转换模式(基于 OpenCC) */
Expand Down
Loading