UI 插槽
宿主界面上可被插件替换的组件位置。声明在
mod.json的ui_extensions里。
槽位清单
✅ 已消费(可替换)
| 槽位 | 位置 | 互斥 |
|---|---|---|
overlay_background | 字幕悬浮窗底板 | ✅ |
caption_view | 字幕内容视图 | ✅ |
audio_level | 右下角音柱 / 波形条 | ✅ |
alert_capsule | 悬浮提示胶囊 | ✅ |
overlay_decorations | 悬浮窗装饰层 | ✅ |
style_bar_actions | 字幕条控制栏的自定义动作按钮 | ❌ |
settings_background | 设置中心底板 | ✅ |
history_background | 历史记录窗底板 | ✅ |
dialog_background | 通用弹窗底板 | ✅ |
window_background | 通用窗口底板 | ✅ |
copilot_window | AI 助手顶层浮窗 | ✅ |
settings_view | 插件独立设置表单(特殊,不在标准列表里,不互斥) | ❌ |
❌ 声明了但当前无 Loader 消费(勿依赖)
overlay_rootstyle_bar
互斥规则
- 上表标记 ✅ 的槽位同级互斥:同一槽位同时只能有一个插件生效。
- 全量主题(
style_layer=full)与局部 UI 插槽扩展可以并存 —— 启用波形条插件不会把用户的主题踢下线。 - 同类局部挂件的互斥只在同为局部(两边都不是 full 主题)时发生。
settings_view永不互斥。
级联回退:窗体会按 专用槽 → window_background → overlay_background 顺序找可用的插件背景, 找不到就用官方原生底座。具体链:
| 窗口 | 回退链 |
|---|---|
| AI 助手浮窗 | copilot_background → window_background → overlay_background |
| 对话框 / 模态 | dialog_background → window_background → overlay_background |
| 设置中心 / 历史窗 | window_background → overlay_background |
因此只写 overlay_background 时,其它窗口也可能复用你的底板风格—— 反过来说,写了专用槽就不必再担心别的窗口忘了改。
插槽决议优先级
同一个插槽同时有多个候选时,按下面顺序决议:
- 局部专用 UI 扩展(如已启用的独立波形条插件)优先接管该插槽;
- 未声明局部扩展 → 回退到当前活跃全量主题自带的插槽组件;
- 都没有 → 回退到官方原生默认组件(停用局部扩展后自动无感回退)。
声明
{
"type": "theme",
"style_layer": "effects",
"ui_extensions": {
"audio_level": "CustomWaveform.qml",
"overlay_background": "MyBackground.qml"
}
}路径是相对插件目录。
背景插槽准则
声明了 overlay_background / settings_background / history_background / dialog_background / window_background 任一,必须遵守:
1) 边框绘制责任(必须自绘)
宿主加载插件背景时,会自动隐去官方原生的 1px 晶体高光外边框(防双重叠线)。 所以插件背景必须自己画窗口外边缘 / 边框 / 外发光(双色霓虹渐变框、金属倒角、高光描边…)。 只填纯色不画边框 → 窗口会变成光秃秃的无边框矩形。
2) 圆角自适应
宿主通过 customRadius 注入目标窗口的原生圆角(设置中心 16、历史窗 16、通用弹窗 12…)。 组件应声明 property bool enforceCustomRadius: false,并在 customRadius 变化时自适应; 不要硬编码极小圆角(如 customRadius: 2)——会出现突兀生硬的直角切边。
3) 上下文属性透传
| 属性 | 内容 |
|---|---|
window / targetWindow | 目标窗体实例(可探测 window.activeFocus / window.hovered) |
appState | 全局应用状态(appState.bgColor / bgOpacity / neonBorderColor…) |
hostContext | 悬浮窗专用上下文(style / subtitle / audio / invoke) |
hovered | 悬浮窗当前是否鼠标悬停 |
4) 配置项热响应(最容易踩的坑)
⚠️
bridge.getPluginConfig(pluginId)是瞬态函数调用,不是 QML 响应式属性。 你在mod.json定义了neon_glow/hud_brackets这种开关,必须监听bridge.pluginConfigChanged,否则用户在设置面板切开关时运行中的窗口毫无反应。
import QtQuick 2.15
Item {
id: root
anchors.fill: parent
readonly property string myPluginId: "community.theme.my_theme"
property var cfg: (typeof bridge !== "undefined" && bridge && bridge.getPluginConfig)
? bridge.getPluginConfig(root.myPluginId) : ({})
readonly property bool enableGlow: (cfg && typeof cfg.neon_glow !== "undefined") ? cfg.neon_glow : true
readonly property bool enableBrackets: (cfg && typeof cfg.hud_brackets !== "undefined") ? cfg.hud_brackets : true
Connections {
target: (typeof bridge !== "undefined") ? bridge : null
function onPluginConfigChanged(pid) {
if (pid === root.myPluginId) {
root.cfg = bridge.getPluginConfig(root.myPluginId) || ({})
}
}
}
Rectangle {
anchors.fill: parent
visible: root.enableGlow
border.color: "#00f0ff"
border.width: 1.5
}
}窗口材质 window_backdrop
仅 theme.json 顶层(写进 mod.json 会被忽略):acrylic | mica | mica_alt | blur | none。 见 theme。
参考实现
| 目录 | 演示 |
|---|---|
extensions/example_theme_cyberpunk/ | full 主题 + 5 个插槽(含 decorations) |
extensions/community_theme_glassmorphism/ | 玻璃质感全套背景 |
extensions/example_custom_waveform_ui/ | 只换 audio_level 的局部扩展(style_layer: effects) |
相关
- theme
- UI 扩展(QML)
- 插件浮窗 — 功能型常驻窗(多开/定位)用这个
- config_schema — 背景组件的配置开关
