Skip to content

Releases: NereaFantasia/foo_ui_webview2

v1.11.0

Choose a tag to compare

@NereaFantasia NereaFantasia released this 27 Jul 16:05

foo_ui_webview2 v1.11.0

Added

  • TrayMenuItem.playbackAction ('play-pause' | 'previous' | 'next' | 'stop') lets a custom tray item declare a playback action the plugin runs natively. Appearance stays caller-controlled; declared items do not emit tray:menuItemClicked. Valid only on a type:'normal' leaf; 'exit' is not accepted. Prefer this (or built-in showPlaybackControls) for background-reliable tray playback while the page is hidden.
  • dsp.* and output.* now actually work. Eleven handlers (dsp.getChain / getPresets / getAvailable / addDsp / removeDsp / moveDsp / applyPreset / setChain, output.getDevices / getEntries / getSettings) were documented but their source files had never been added to the build, so every call failed as an unregistered method. They are compiled and registered from this release on.
  • menu.getMainMenu accepts locale (default 'auto'), i18n, and withAvailability (default true). The SDK signature is now getMainMenu(root?, opts?).
  • Discovery entries gain path, isDynamic, isDynamicParent, subGuid, and flags; getMainMenuCommands echoes expandDynamic and dynamicCount, and discovery.getAllServices adds mainMenuDynamicCommands. discovery.executeMainMenuCommand accepts an optional subGuid for commands expanded from a dynamic submenu.
  • metadata.read and metadata.readByPath accept cueIndex to address a track explicitly, matching metadata.readRaw. It takes precedence over a |subsong:N path suffix.
  • SDK-only additive binary adapters: fb.file.readBinary(), fb.file.writeBinary(), fb.file.writeDataUrl(), fb.metadata.embedArtworkBytes(), and fb.metadata.embedArtworkFromDataUrl(), plus FileBinaryWriteOptions and MetadataArtworkBytesOptions. They add no new Bridge endpoints.
  • Optional trailing opts arguments on five wrappers whose host handlers already read the corresponding keys: fb.file.delete(path, opts?) (moveToTrash), fb.file.copy(source, destination, opts?) (overwrite), and fb.metadata.write(path, tags, opts?) / removeField(path, field, opts?) / removeTag(path, tags, opts?) (cueIndex). metadata.write gaining cueIndex closes a real gap: this release wired cueIndex into the metadata read path only, so writing a tag to a single track inside a CUE sheet or image file was not expressible through the SDK. Every new argument is optional.
  • Advanced-preferences option Deep-suspend WebView when hidden (TrySuspend; frees renderer memory) (default on) freezes renderer timers and animations while minimized, covered, locked, or tray-hidden.
  • Advanced-preferences option Keep WebView active in background while CDP remote debugging is on (default on), so screenshot and timing automation over the DevTools Protocol stays stable.
  • windowId parameter typings for window.getBackdropPolicy and window.setBackdropPolicy.

Fixed

  • Fixed a crash in output.getDevices. Some output backends report a device name with a "length unknown" sentinel instead of a real length; the handler used that value verbatim and read far past the end of the string, terminating foobar2000.
  • Fixed dsp.moveDsp moving items to the wrong slot. Upward moves landed one position short, so moving an item up by one did nothing and no item could reach the end of the chain. The returned to now reports the real final index.
  • Fixed metadata.read, metadata.readByPath, and metadata.readBatch ignoring the track index inside a container. A |subsong:N suffix was neither stripped nor honored, so reading a single track out of a CUE sheet, ISO image, or multi-track file either failed outright or returned the first track's tags. This is why such files could be read in the foobar2000 UI but not through the API.
  • dsp.getPresets reports selectedIndex: -1 when no preset is selected, instead of the internal sentinel 18446744073709551615, which is not representable as a JavaScript number.
  • dsp.getChain always includes activePreset and activePresetIndex, using null / -1 when no preset is selected. The keys were previously absent in those cases.
  • Fixed UTF-8 serialization and context-mode selection for custom menus.
  • Hardened recovery after a WebView2 crash: a failed render process no longer leaves an unresponsive blank window.
  • Improved album-art delivery: fixed cache entries that could serve another track's image, tightened request and parameter validation, and moved image decoding off the interface thread. artwork.* request and response shapes are unchanged.
  • Breaking type fix — the published response types for ui.isMinimized() and ui.isAlwaysOnTop() were wrong and now match the wire contract: isMinimized resolves with { minimized } (there is no isMinimized alias), and isAlwaysOnTop resolves with { enabled, isAlwaysOnTop }. Runtime behavior is unchanged; TypeScript code written against the old declarations must be updated.
  • Corrected two published type declarations that did not match the host contract: dsp.setChain takes a required dsps array of { guid } objects (it was typed dsps?: string[]), and the playlist:created / playlist:renamed payloads keep name: string.
  • fb.metadata.readByPath() now resolves with MetadataReadByPathResponse instead of a bare JsonObject.
  • fb.http.request() now dispatches through the documented http.get endpoint; a stale internal parameter could previously forward a mismatched method name.
  • fb.playcount.set() no longer sends the count key, which the host never read.

Changed

  • dsp.setChain rejects a call that contains any unusable entry instead of silently skipping it. Previously a chain built from three entries could apply only two and still report success: true. Each per-entry failure now returns an index-tagged reason (dsps[0] must be an object, dsps[0]: guid is required, dsps[0]: Invalid GUID format: …, dsps[0]: DSP not found or no default preset: …). The chain is left untouched whenever a call is rejected.
  • discovery.getMainMenuCommands and discovery.searchCommands now expand components that build their submenu at runtime (mainmenu_commands_v2, e.g. ESLyric), so results include child commands in addition to the parent slot. Pass { expandDynamic: false } for the previous static-registry-only result.
  • While the page is hidden (minimized, covered, tray-hidden, or locked), high-rate regenerable streams stop at the source: audio:spectrum, playback:time, and playback:timeHighRes are not produced, and resume on the next tick once the page is visible again. Every other event is delivered reliably and in order — nothing is dropped or merged — including async replies such as http:response, library:getAllResult, and audio:fullWaveformReady. Themes that draw a spectrum or a seek position should read a gap as "page hidden", not as "playback stopped".
  • tray:menuItemClicked covers ordinary user items and rich value controls only. Built-in playback / system injections and items declaring playbackAction execute natively without the click event; reflect button state from playback:*.

1.11.0 中文说明

新增功能

  • 新增 TrayMenuItem.playbackAction'play-pause' | 'previous' | 'next' | 'stop'):自定义托盘项可声明由插件原生执行的播放动作。外观仍由调用方控制;声明项不发 tray:menuItemClicked。仅可用于 type:'normal' 的叶子项,不接受 'exit'。主页面深挂起时要后台可靠的托盘播放控制,请用本字段或内置 showPlaybackControls
  • dsp.*output.* 现在真正可用。 这 11 个处理器(dsp.getChain / getPresets / getAvailable / addDsp / removeDsp / moveDsp / applyPreset / setChainoutput.getDevices / getEntries / getSettings)此前虽有文档,但其源文件从未被加入编译,所以任何调用都会因方法未注册而失败。自本版起已编译并注册。
  • menu.getMainMenu 新增 locale(默认 'auto')、i18nwithAvailability(默认 true)三个选项,SDK 侧签名变为 getMainMenu(root?, opts?)
  • Discovery 命令条目新增 pathisDynamicisDynamicParentsubGuidflags;响应新增 expandDynamicdynamicCountdiscovery.getAllServices 新增 mainMenuDynamicCommandsdiscovery.executeMainMenuCommand 新增可选参数 subGuid,用于执行由动态子菜单展开出的命令。
  • metadata.readmetadata.readByPath 新增 cueIndex 参数,可显式指定轨道,与 metadata.readRaw 一致,优先级高于路径中的 |subsong:N 后缀。
  • 新增仅 SDK 层的 additive 二进制适配 helper:fb.file.readBinary()fb.file.writeBinary()fb.file.writeDataUrl()fb.metadata.embedArtworkBytes()fb.metadata.embedArtworkFromDataUrl(),以及公开类型 FileBinaryWriteOptionsMetadataArtworkBytesOptions。不新增 Bridge endpoint。
  • 为五个 wrapper 补上可选的末位 opts 参数,对应的键宿主 handler 早已读取:fb.file.delete(path, opts?)moveToTrash)、fb.file.copy(source, destination, opts?)overwrite),以及 fb.metadata.write(path, tags, opts?) / removeField(path, field, opts?) / removeTag(path, tags, opts?)cueIndex)。其中 metadata.write 支持 cueIndex 补上了一处真实缺口:本版只把 cueIndex 接进了元数据读取侧,因此此前无法通过 SDK 向 CUE 或镜像文件中的单曲写标签。所有新增参数均为可选,既有调用点不受影响。
  • 新增高级设置项 Deep-suspend WebView when hidden (TrySuspend; frees renderer memory)(默认开启):最小化 / 被遮挡 / 锁屏 / 托盘隐藏时冻结渲染进程计时器与动画,便于系统回收内存。
  • 新增高级设置项 Keep WebView active in background while CDP remote debugging is on(默认开启):开启 CDP 远程调试时保持 WebView 后台活跃,保证截图与时序类自动化工具稳定。
  • window.getBackdropPolicy / window.setBackdropPolicy 补齐 windowId 参数类型声明。

Bug 修复

  • 修复 output.getDevices 崩溃。部分输出后端在回调里用「长度未知」哨兵值代替真实长度,原实现直接采用该值,导致读取远超字符串末尾并使 foobar2000 终止。
  • 修复 dsp.moveDsp 移动到错误位置。升序移动会少一格,因此向上移动一位等于无操作,且任何项都无法移到链尾。返回的 to 现在是真实的最终索引。
  • 修复 metadata.readmetadata.readByPathmetadata.readBatch 忽略容器内轨道编号的问题。路径里的 |subsong:N 后缀既没有被剥离也没有被采用,因此从 CUE、ISO 镜像或多轨文件里读取单条轨道时,要么直接失败,要么返回首轨的标签。这正是这类文件在 foobar2000 界面里能读、经 API 读不到的原因。
  • dsp.getPresets 在无选中预设时返回 selectedIndex: -1,不再返回无法用 JavaScript number 表示的内部哨兵值 18446744073709551615
  • dsp.getChain 始终包含 activePresetactivePresetIndex,无选中预设时为 null / -1。此前这两个键完全缺失。
  • 修复自定义菜单的 UTF-8 序列化与上下文模式选择。
  • 收敛 WebView2 崩溃后的僵尸态:进程失败后按重载次数上限决定重载或重建,不再停留在无响应页面。
  • 改进封面获取:修正了换曲或改标签后可能返回上一首封面的缓存问题,并把解码移出 UI 线程。artwork.* 的请求与响应结构未变。
  • 破坏性类型修正 —— 修...
Read more

v1.10.0

Choose a tag to compare

@NereaFantasia NereaFantasia released this 16 Jul 16:53

foo_ui_webview2 v1.10.0

WebView2-based UI host for foobar2000 — build the player UI with HTML/CSS/JS.

This release rounds out the self-drawn (WebView-rendered) tray/popup menu — layout modes, vertical sliders, keyboard & accessibility — plus a security hardening pass. The documentation site is now bilingual, and starting with this release every release ships an offline docs package.

Added

  • TrayMenuItem.orientation for type:'slider': 'horizontal' (default) or 'vertical' (min at bottom / max at top, arrow + Home/End keys)
  • TrayMenuConfig.layoutMode: 'flat' (default) or 'zones', wrapping non-empty top / playback / bottom sections in .fb-zone[data-zone] containers
  • Both new fields are ignored by native menus and older runtimes; probe config.getVersionInfo().plugin.version if your theme depends on them
  • Bilingual documentation site: English is now the default, with a complete Chinese mirror under /zh/
  • Offline documentation package (foo_ui_webview2-docs-x.y.z.zip) attached to every release from now on

Improved

  • Custom-menu keyboard model: roving-tabindex navigation plus rich-control editing, with ARIA roles (menuitem, menuitemcheckbox, slider, segmented radiogroup)
  • Entrance/exit menu animations are disabled under prefers-reduced-motion: reduce
  • Themes can now lay out the menu root or zones with flex/grid: protected CSS no longer forces display:block !important on the visible menu (and display:* !important can no longer reveal a hidden menu)
  • segmented value changes now keep the menu open, consistent with rating / slider; each change emits tray:menuItemClicked with { id, value }

Security

  • ⚠️ New transactional resource limits on tray.setContextMenu / tray.appendMenuItems / menu.show: items ≤ 512, menu.show depth ≤ 8, segmented options ≤ 64, CSS ≤ 256 KiB, total SVG ≤ 256 KiB. Oversized or invalid input is now rejected with INVALID_PARAMS (field / limit / actual in details) — themes that previously passed such input must trim it
  • Menu SVG icons are parsed with DOMParser plus an element/attribute allowlist instead of raw innerHTML; invalid or oversized icons are dropped while the menu keeps rendering
  • Built-in action routing now relies on trusted internal provenance and one-shot tokens instead of public id prefixes (sole compatibility exception: _sys_exit); internal menu IPC verifies the calling window and current menu id

Fixed

  • Fixed reserved space for unopened submenu panels showing as a blank acrylic/mica area and silently disabling the configured backdrop
  • Fixed leading/trailing separators left behind when an entire menu section is hidden via visible:false
  • Corrected docs for TrayMenuItem.icon: base64 ICO is reserved and not rendered by either backend — use iconSvg

1.10.0 中文说明

基于 WebView2 的 foobar2000 界面宿主 —— 用 HTML/CSS/JS 构建播放器界面。

本版完善自绘(WebView 渲染)托盘/弹出菜单:布局模式、垂直滑块、键盘与无障碍,并完成一轮安全加固。文档站全面双语化,且从本版起每个 release 附带离线文档包。

新增功能

  • 滑块菜单项新增 orientation:'horizontal'(默认)或 'vertical'(min 在底/max 在顶,方向键与 Home/End 可用)
  • 新增 TrayMenuConfig.layoutMode:'flat'(默认)或 'zones',为非空的顶部/播放/底部分区生成 .fb-zone[data-zone] 容器
  • 两个新字段在 native 菜单与旧版运行时中被忽略;依赖它们的主题请用 config.getVersionInfo().plugin.version 探测
  • 文档站双语化:英文为默认语言,/zh/ 提供完整中文镜像
  • 从本版起每个 release 附带离线文档包(foo_ui_webview2-docs-x.y.z.zip)

优化改进

  • 自绘菜单键盘模型:roving-tabindex 导航 + 富控件编辑两态,配套 ARIA 角色(menuitemmenuitemcheckbox、slider、segmented radiogroup)
  • 系统开启"减弱动态效果"时禁用菜单出入场动画
  • 主题可对菜单根/分区使用 flex/grid 布局:保护性 CSS 不再对可见菜单强制 display:block !important(同时 display:* !important 不再能显示隐藏菜单)
  • segmented 改值不再关闭菜单,与 rating / slider 一致;每次改值发出 tray:menuItemClicked(载荷 { id, value })

安全加固

  • ⚠️ tray.setContextMenu / tray.appendMenuItems / menu.show 新增事务化资源上限:菜单项 ≤ 512、menu.show 深度 ≤ 8、segmented 选项 ≤ 64、CSS ≤ 256 KiB、SVG 总量 ≤ 256 KiB。超限或非法输入现在返回 INVALID_PARAMS(detailsfield / limit / actual)—— 以前能通过的超限菜单需要精简
  • 菜单 SVG 图标改用 DOMParser + 元素/属性白名单解析,替代裸 innerHTML;非法或超大图标被安全丢弃,菜单继续渲染
  • 内建动作路由改用可信内部来源 + 一次性 token,不再依赖公开 id 前缀(唯一兼容例外:_sys_exit);内部菜单 IPC 校验调用窗口与当前菜单 id

Bug 修复

  • 修复为未展开子菜单预留的空间显示为空白亚克力/云母区域、并悄悄禁用所配置背景效果的问题
  • 修复整段菜单项经 visible:false 隐藏后残留首/尾分隔符的问题
  • 更正 TrayMenuItem.icon 文档:base64 ICO 为保留字段、两种后端均不渲染 —— 请使用 iconSvg

📥 Installation · 安装

Download foo_ui_webview2-1.10.0.fb2k-component below (x86 + x64 bundled), double-click it (or Preferences → Components → Install…), then restart foobar2000.
下载下方 foo_ui_webview2-1.10.0.fb2k-component(含 x86/x64),双击安装(或 选项 → Components → Install…),重启 foobar2000。

SDK (npm): npm install foo-webview-sdk@1.10.0

📚 Documentation · 文档

v1.9.0

Choose a tag to compare

@NereaFantasia NereaFantasia released this 23 Jun 07:55

foo_ui_webview2 v1.9.0

First public release — a WebView2-based UI host for foobar2000 (build the player
UI with HTML/CSS/JS). Features, requirements and theme setup: see the README.
首个公开发布 —— 基于 WebView2 的 foobar2000 界面宿主(用 HTML/CSS/JS 构建播放器
界面)。特性、运行环境与主题放置方式见 README。

What's new in 1.9.0 · 1.9.0 新增

Added · 新增

  • Tray menu inline SVG icons — TrayMenuItem.iconSvg (render: 'webview')
    · 托盘菜单内联 SVG 图标
  • TrayMenuConfig.autoNowPlaying — auto-fills now-playing cover / title /
    subtitle on right-click · 右键自动填充当前曲目封面 / 标题 / 副标题

Changed · 变更

  • Tray menu cover now also accepts an http(s):// URL
    · 托盘菜单 cover 现在也接受 http(s):// URL

Install · 安装

Download foo_ui_webview2-1.9.0.fb2k-component below (x86 + x64 bundled),
double-click it (or Preferences → Components → Install…), then restart foobar2000.
下载下方的 foo_ui_webview2-1.9.0.fb2k-component(含 x86 / x64),双击安装
(或 选项 → Components → Install…),然后重启 foobar2000。


README: https://github.com/NereaFantasia/foo_ui_webview2#readme ·
Docs/文档: https://nereafantasia.github.io/foo_ui_webview2/