Repository navigation
feat: 插件系统新增控制类插件(control) - #52
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
本 PR 为插件系统新增「控制类插件(@type control)」能力:主进程向控制插件扇出高层播放事件(曲目/歌词/行/播放态),并允许插件反向控制播放与声明可配置设置项;同时调整插件管理 UI 与文档结构,以支持按类型分区与控制插件配置弹窗。
Changes:
- 插件契约与沙箱通信扩展:新增
control类型、播放事件/反控 API、设置项 schema 与设置变更推送链路。 - 主进程新增
playbackBridge与playerControl:惰性订阅 nowPlaying 并按订阅扇出事件,外部控制入口统一收敛。 - 渲染端插件管理 UI 升级:按「音源/控制」分区展示,新增控制插件配置弹窗表单与设置写入。
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/stores/plugins.ts | 插件列表按类型分组;启用逻辑区分 source 互斥与 control 可并行;新增 setSetting 写回。 |
| src/i18n/locales/zh-CN.json | 插件管理新增分区与配置弹窗副标题文案。 |
| src/i18n/locales/en-US.json | 同上(英文)。 |
| src/components/settings/custom/PluginSettingsForm.vue | 新增控制插件设置 schema 的表单渲染组件。 |
| src/components/settings/custom/PluginManager.vue | 插件管理页改为音源/控制分区 + 控制插件配置弹窗。 |
| src/components/settings/custom/PluginCard.vue | 抽卡片组件,统一状态展示/启停/卸载/(可选)配置入口。 |
| shared/types/plugin.ts | 扩展插件类型、控制事件载荷、设置项 schema、Host API(player/onSettingChange)与沙箱消息协议。 |
| shared/types/nowPlaying.ts | nowPlaying 快照/同步结构补充完整 state(区分 paused/stopped)。 |
| shared/defaults/plugin-api.ts | HOST_API_LEVEL 升级到 2。 |
| electron/preload/index.ts | 预加载新增 window.api.plugins.setSetting IPC 暴露。 |
| electron/main/services/playerControl.ts | 新增播放控制聚合入口,供 WS/REST/插件 hostCall 复用。 |
| electron/main/services/nowPlaying.ts | nowPlaying 增补 PlayerState 同步;订阅方法改为返回取消订阅函数。 |
| electron/main/server/ws.ts | WS 控制命令改走 playerControl。 |
| electron/main/server/routes.ts | REST 控制路由改走 playerControl。 |
| electron/main/plugins/sandbox.worker.ts | 沙箱侧注入 splayer.player、事件回调注册与 onSettingChange;上报 control 注册信息。 |
| electron/main/plugins/sandbox.ts | 主→worker 投递增加 clone 失败兜底;新增 event/settingsUpdate 下发方法。 |
| electron/main/plugins/registry.ts | registry 记录 control 注册信息与 per-plugin settingsValues;新增 setSetting;新增控制事件扇出。 |
| electron/main/plugins/playbackBridge.ts | 新增播放事件桥:从 nowPlaying 聚合语义变化并扇出给订阅的控制插件,支持就绪补发快照。 |
| electron/main/plugins/loader.ts | 解析 @type 并校验类型清单;对 control+低 apiLevel 给出告警。 |
| electron/main/plugins/host.ts | hostCall 新增 player.* 分发到 playerControl。 |
| electron/main/ipc/plugin.ts | 新增 plugin:setSetting IPC 处理。 |
| electron/main/ipc/player.ts | 引擎 stateChanged 透传完整 PlayerState 到 nowPlaying。 |
| electron/main/core/index.ts | 启动/退出时 init/dispose playbackBridge。 |
| docs/streaming.md | 文案微调(“网易云音源”→“在线音源”)。 |
| docs/plugins/source.md | 新增音源插件文档(工作原理、source key、示例、约定)。 |
| docs/plugins/index.md | 新增插件总览与架构文档(类型、API 级别、通用 API、约束)。 |
| docs/plugins/control.md | 新增控制插件文档(事件、反控、设置项、ClassIsland 示例)。 |
| docs/plugins-usage.md | 用户指南更新:补充控制插件并行启用与配置入口。 |
| docs/plugins-development.md | 删除旧“插件开发指南”(由新的三篇文档取代)。 |
| docs/native.md | 补充 taskbar-thumbnail 模块说明与别名列表更新。 |
| docs/guide.md | 更新插件文档链接指向新目录。 |
| docs/.vitepress/config.ts | 文档导航更新:插件开发改为多级菜单(总览/音源/控制)。 |
| components.d.ts | 自动注册声明更新:新增 PluginCard / PluginSettingsForm。 |
Comment on lines
354
to
359
| onSourcesUpdate: (sources) => { | ||
| // 异步 lx.send('inited') / splayer.register 触发 | ||
| if (rt.status.state !== "ready") return; | ||
| const merged = { ...rt.status.sources, ...sources }; | ||
| this.setStatus(rt, { state: "ready", sources: merged }); | ||
| }, |
Comment on lines
+521
to
+526
| async setSetting(id: string, key: string, value: unknown): Promise<void> { | ||
| const rt = this.runtimes.get(id); | ||
| if (!rt) return; | ||
| const item = rt.settings.find((setting) => setting.key === key); | ||
| const sanitized = sanitizeSettingValue(item, value); | ||
| const all = { |
Comment on lines
+24
to
+28
| play: (): void => | ||
| void getPlayer() | ||
| .play() | ||
| .catch(() => {}), | ||
| pause: (): void => getPlayer().pause(), |
Comment on lines
+133
to
+137
| if (rawType === "control" && apiLevel < 2) { | ||
| pluginLog.warn( | ||
| `插件 "${name}" 声明 type=control 但 apiLevel=${apiLevel}(需 >= 2),控制类功能将在运行时受限`, | ||
| ); | ||
| } |
roarrabbit
pushed a commit
to roarrabbit/SPlayer-Next
that referenced
this pull request
Aug 27, 2026
…n-type feat: 插件系统新增控制类插件(control)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
本 PR 为插件系统新增控制类插件(
@type control)。在原有「音源插件」(解析播放地址)之外,插件现在可以:playing/paused/stopped);play/pause/next/prev/seek/setVolume/getPosition;switch/number/text/select,渲染到插件管理的设置弹窗,用户改动实时下发到插件。与音源插件一致,每个控制插件运行在独立隔离进程中,崩溃 / 卡死自动恢复,互不影响。
与 #49 的关系(可用插件解决)
#49(ClassIsland 联动)把「订阅播放/歌词事件并 POST 到本地 HTTP 服务」的逻辑硬编码进主进程(新增
lyricsIsland.ts+ 专属设置 / i18n / logger)。这正是控制类插件要解决的一类需求——这类「把播放状态推送到外部服务」的集成,现在可以写成一个控制插件,无需改动应用本体。事实上,控制插件文档里的完整示例就是一个 ClassIsland 联动插件:订阅
trackChange/lyricChange/lineChange,按用户设置(端口 / 是否翻译 / 无翻译回退下一行)POST 到http://127.0.0.1:50063/component/lyrics/lyrics/,与 #49 行为一致,但以插件形态分发,不进主仓库。这样带来的好处:
因此建议 #49 改以控制插件形态提供(示例已在文档中给出),主仓库不再内置 ClassIsland 专属服务。
主要改动
插件运行时
@type头部,插件类型以PLUGIN_TYPES清单为唯一来源;playbackBridge:聚合nowPlaying事件,仅在语义变化时推送给订阅插件(5Hz 的position-sync只在主进程消费,仅行索引 / 播放态变化才下发,避免高频 IPC 外泄);playerControl:把「系统媒体 / HTTP / WS / 控制插件」四个外部播放控制入口收敛到一处;hostCall支持player.*;新增plugin:setSettingIPC 与预加载暴露。界面
修复(本轮 review 后定点修复)
playStateChange补回stopped,与paused区分;getPosition明确为偶发查询用途(持续进度请读事件载荷里的position)。文档
LyricLine/PluginSettingItem字段、音源插件的调用机制与 source key 约定,以及 ClassIsland 完整示例。测试
pnpm typecheck通过;eslint/prettier通过;pnpm docs:build通过。