Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
60afdda
fix(ui): calibrate VU meter reference and dynamic ballistics to preve…
Oct 29, 2026
b3dc308
feat(vu-meter): per-profile dial and pointer designs
Oct 29, 2026
34d05f5
feat(vu-meter): retro moving-coil physics, paper grain and machined b…
Oct 29, 2026
4826324
feat(vu-meter): redesign dial faces per color profile
Oct 29, 2026
2d29156
feat(vu-meter): hi-fi backlit dials and critically damped needle
Oct 29, 2026
0d299aa
feat(vu-meter): refine profile scales and analog ballistics
Oct 29, 2026
47fb04c
feat(vu-meter): add Nocturne, Heritage, Atelier, Riviera and Cobalt d…
Nov 3, 2026
d9b18cc
feat(vu-meter): replace legacy dials with ported design-study renderer
Nov 4, 2026
3c27be4
build(deps): bump module-alias from 2.3.4 to 2.3.5
dependabot[bot] Nov 5, 2026
409972a
build(deps-dev): bump electron from 43.8.3 to 43.8.6
dependabot[bot] Nov 5, 2026
e3b5fb7
refactor(vu-meter): remove legacy theme migration
XCQ0607 Nov 5, 2026
a30ec55
fix(vu-meter): resolve dev conflicts and preserve player behavior
XCQ0607 Nov 5, 2026
7dea7b7
Merge pull request #495 from pokemonred06-creator/feat/vu-design-study
XCQ0607 Nov 5, 2026
9e51bcd
Merge pull request #505 from XCQ0607/dependabot/npm_and_yarn/dev/elec…
XCQ0607 Nov 5, 2026
09d1aa8
Merge pull request #504 from XCQ0607/dependabot/npm_and_yarn/dev/modu…
XCQ0607 Nov 5, 2026
3c362d6
fix(webdav): improve connection diagnostics and resolve #474
XCQ0607 Nov 5, 2026
a36666e
fix(player): 修复详情导航、批量高亮及播放队列问题
XCQ0607 Nov 5, 2026
be90464
feat: 备份快照类型/筛选、不喜欢回滚、回滚缓存失效(对齐上游 v2.1.4)
pyss56 Nov 5, 2026
3468ddb
fix(player): preserve native AirPlay after Web Audio capture
Nov 6, 2026
f58ee19
feat(backup): 统一备份管理、OpenList 播放来源与内容校验
XCQ0607 Nov 7, 2026
06d0b29
Merge pull request #512 from XCQ0607/pr-508
XCQ0607 Nov 7, 2026
02232c6
fix(player): harden native AirPlay recovery and effect preview
XCQ0607 Nov 7, 2026
a04dad3
fix(player): restore native audio without reload and polish UI states
XCQ0607 Nov 7, 2026
e26d7ff
chore: merge dev and resolve changelog conflicts
XCQ0607 Nov 7, 2026
43143c5
Merge pull request #511 from pokemonred06-creator/codex/airplay-nativ…
XCQ0607 Nov 7, 2026
e77fa00
feat(music): 更新音源 SDK 与聚合搜索体验
XCQ0607 Nov 7, 2026
2effa20
feat: 同步 fork 通用功能改动至上游(自动排除 fork 私有代码)
pyss56 Nov 9, 2026
b239c07
feat(rating): 统一 Web 与 Subsonic 评分及不喜欢联动
XCQ0607 Nov 10, 2026
7944d61
Merge pull request #508 from pyss56/upstream-pr
XCQ0607 Nov 10, 2026
4b0117f
fix(openlist): improve outage recovery and safeguard backup deletion
XCQ0607 Nov 10, 2026
a08d483
fix(download): 修复下载进度误报并完善歌词嵌入与音质筛选 (#485)
XCQ0607 Nov 10, 2026
dcbe880
fix(cache): 修复自动清理范围与并发索引问题 (#489)
XCQ0607 Nov 10, 2026
f01c67d
fix(player): reset progress when switching tracks (fixes #494)
XCQ0607 Nov 10, 2026
48903a7
perf(music): 优化自定义目录加载与索引同步 (#475)
XCQ0607 Nov 10, 2026
d63f5cd
fix(music): stop playback retries when no sources are available
XCQ0607 Nov 10, 2026
fca351b
fix(music): prefer completed cache when playing prefetched songs
XCQ0607 Nov 10, 2026
ba187a7
feat(subsonic): 增加可选 cache 歌曲返回 (#493)
XCQ0607 Nov 10, 2026
e4a6add
feat(subsonic): 增加可选 cache 歌曲返回 (#493)
XCQ0607 Nov 10, 2026
e68184a
Merge branch 'dev' of https://github.com/XCQ0607/lxserver into dev
XCQ0607 Nov 10, 2026
15fdef8
Merge branch 'dev' of https://github.com/XCQ0607/lxserver into dev
XCQ0607 Nov 10, 2026
517bbc5
Merge branch 'dev' of https://github.com/XCQ0607/lxserver into dev
XCQ0607 Nov 10, 2026
0702cd1
Merge branch 'dev' of https://github.com/XCQ0607/lxserver into dev
XCQ0607 Nov 10, 2026
e899f27
fix(download): 修复 PWA 下载认证会话失效问题 (#496)
XCQ0607 Nov 10, 2026
11ffc20
Merge remote-tracking branch 'origin/dev' into dev
XCQ0607 Nov 10, 2026
078c4f0
feat(admin): add dashboard overview and initial theme support
XCQ0607 Nov 10, 2026
f572dc8
feat(admin): 重构后台仪表盘与明暗主题, 更新 v2.2.0 changelog 与更新通知
XCQ0607 Nov 10, 2026
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
32 changes: 32 additions & 0 deletions .github/workflows/player-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Player validation

on:
pull_request:
branches: [dev]
paths:
- 'public/music/**'
- 'test/**'
- 'src/**'
- 'package*.json'
- 'tsconfig.json'
- '.github/workflows/player-validation.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
player:
runs-on: ubuntu-latest
strategy:
matrix:
node: [22, 24]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci --ignore-scripts --no-audit --no-fund
- run: npm test
- run: npm run build --ignore-scripts
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ docker build -t lxserver:local .

### Subsonic 客户端

支持使用音流、Feishin、Symfonium 等客户端访问已实现的 Subsonic/OpenSubsonic 接口。各客户端支持的功能不同,接口范围和已知限制见 [Subsonic 状态](docs/subsonic-status.md)。
支持使用音流、Feishin、Symfonium 等客户端访问已实现的 Subsonic/OpenSubsonic 接口。各客户端支持的功能不同,接口范围和已知限制见 [Subsonic 协议支持](docs/api/subsonic.md)。

默认连接信息:

Expand All @@ -238,7 +238,7 @@ docker build -t lxserver:local .

Subsonic 本地曲库按当前账号的持久化存储设置读取音乐和缓存,并加入该账号已启用的自定义目录。网页中临时切换浏览目录,不会改变 Subsonic 的曲库范围。

默认返回只读的“本地歌曲”歌单;自定义目录可以单独显示。纯本地歌单保存在服务端,不进入 LX 官方客户端同步;混合歌单中的在线歌曲和本地成员分别保存。详情见 [Subsonic 本地音乐库](docs/subsonic-local-library.md)。
默认返回只读的“本地歌曲”歌单;自定义目录可以单独显示。纯本地歌单保存在服务端,不进入 LX 官方客户端同步;混合歌单中的在线歌曲和本地成员分别保存。详情见 [Subsonic 本地音乐库](docs/guide/subsonic-local-library.md)。

<p align="center">
<img src="md/subsonic.png" width="500" alt="Subsonic 客户端连接">
Expand Down Expand Up @@ -383,7 +383,7 @@ Subsonic 用户目录中的 `subsonic-local-registry.json` 和 `subsonic-local-s

配置备份默认开启,保留 7 天;默认位置为数据目录的 `backups/`。可以用 `CONFIG_BACKUP_DIR` 和 `SNAPSHOT_BACKUP_PATH` 自定义配置备份、歌单快照的存储位置。

在「系统设置 → 云端备份范围」中,可分别选择 WebDAV 和 OpenList 备份的数据类型。两端默认都选中以下五类,但仍需单独启用对应服务并配置连接信息;同时启用会保存两份副本,不会在两个云端之间同步。
在「备份管理 → 云端备份 → 备份范围」中,可分别选择 WebDAV 和 OpenList 备份的数据类型。两端默认都选中以下五类,但仍需单独启用对应服务并配置连接信息;同时启用会保存两份副本,不会在两个云端之间同步。

| 类型 | 备份内容 |
| --- | --- |
Expand All @@ -404,9 +404,13 @@ Subsonic 用户目录中的 `subsonic-local-registry.json` 和 `subsonic-local-s

类型数组为空表示该端不备份任何数据类型。普通数据备份始终排除缓存、日志、临时文件、运行数据库和本地备份包;程序根目录的音乐和自定义外部音乐库需要另行备份。OpenList 的「永久播放缓存」单独配置,勾选歌曲文件不会自动开启缓存上传或删除本地歌曲。

新增配置项 `configBackup.intervalHours`(默认 24)、`configBackup.scheduleTime`(默认 `00:00`)、`webdav.retentionCount`(默认 5)和 `webdav.retentionDays`(默认 0,不限天数)通过后台或 `config.js` 设置。OpenList 连接、历史保留和播放来源选项也使用配置键,目前没有 `OPENLIST_*` 等对应环境变量;不要把配置键自动改写成大写变量。完整默认值见 [备份配置参考](docs/guide/configuration.md#备份配置项-后台或-config-js)。

WebDAV 增量文件与 ZIP 备份采用相同范围,默认分别每 60 分钟、24 小时执行;OpenList 数据备份保存在其根目录的 `_data/` 下,默认每 60 分钟检查。普通备份保留本地文件。WebDAV 默认也保留云端已有文件,只有显式开启 `backup.webdav.mirrorDeletes` 才会向增量目录传播本地删除,历史 ZIP 不受影响。

WebDAV 默认不在启动时恢复,需显式开启 `backup.webdav.restoreOnStartup`。手动恢复按该端当前勾选范围下载,覆盖本地同名文件并保留本地独有文件,不会反向上传。恢复不是整个目录的原子替换,完成后应重启服务,使配置、账号、歌单和音乐索引完整重新加载。部署新实例前确认云端目录和备份范围,具体步骤见 [备份与恢复](docs/guide/backup-recovery.md)。
普通 OpenList 上传只检查响应、存在与大小,不下载正文;需要核对内容时,在「备份管理 → 记录与校验 → OpenList → 内容校验」先查看预计流量再手动启动。上传后删除本地缓存仍需完整内容校验。

WebDAV 默认不在启动时恢复,需显式开启 `backup.webdav.restoreOnStartup`。WebDAV 手动恢复先预览,支持仅补缺失或覆盖同名文件,保留本地独有文件,不反向上传;所有所选文件暂存校验后才写入,写入失败尝试回滚,默认保留恢复前副本。恢复不是整个目录的原子替换,完成后应重启服务,使配置、账号、歌单和音乐索引完整重新加载。部署新实例前确认云端目录和备份范围,具体步骤见 [备份与恢复](docs/guide/backup-recovery.md)。

### 更新与迁移

Expand All @@ -424,7 +428,7 @@ docker compose logs --tail=100

系统默认使用 `data/config.js`;`DATA_PATH` 改变数据目录,`CONFIG_PATH` 指定独立配置文件。首次启动时,若目标配置文件不存在,会尝试从程序根目录的旧配置初始化。

普通启动按默认值、配置文件、环境变量的顺序合并配置。显式启用 WebDAV 启动恢复时,恢复过程还会重新加载远端配置和账号数据;手动恢复后需要重启服务。当前生效值和配置路径可在管理后台查看。
普通启动按默认值、配置文件、环境变量的顺序合并配置。显式开启 WebDAV 启动恢复后,还会重新加载备份中的配置和账号;手动恢复后需要重启服务。当前生效值和配置路径可在管理后台查看。

环境变量在进程启动时读取。修改 Compose 中的环境变量后需要重建容器;后台配置是否即时生效取决于具体选项,监听端口和路径调整后应按提示重新连接或重启。

Expand Down
14 changes: 9 additions & 5 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Do not use `/admin`, `/rest` or the player access password for LX sync. Review m

### Subsonic clients

Compatible clients include Yinliu, Feishin and Symfonium. The server implements Subsonic/OpenSubsonic endpoints for library browsing, search, playback and related features; the UI and available features vary by client.
Compatible clients include Yinliu, Feishin and Symfonium. The server implements Subsonic/OpenSubsonic endpoints for library browsing, search, playback and related features; the UI and available features vary by client. See [Subsonic protocol support](docs/en/api/subsonic.md) for coverage and limits.

| Field | Value |
| --- | --- |
Expand All @@ -220,7 +220,7 @@ By default Subsonic shares the main port. Separate listening requires `subsonic.

Online search uses `subsonic.onlineSearch` and `subsonic.onlineSearchMode`: `fallback` supplements insufficient local results; `merge` combines local and online results; `local_only` stays local. Query prefixes include `wy:`, `tx:`, `kw:`, `kg:`, `mg:`, `online:` and `local:`. Online playback still needs a working custom source.

Local library selection follows the account's saved storage location plus its enabled custom directory. A temporary browsing switch in the web UI does not change that library. Read-only local/custom playlists can be exposed separately. Pure local playlists stay on the server; only the online portion of mixed playlists enters LX native sync.
Local library selection follows the account's saved storage location plus its enabled custom directory. A temporary browsing switch in the web UI does not change that library. Read-only local/custom playlists can be exposed separately. Pure local playlists stay on the server; only the online portion of mixed playlists enters LX native sync. See [Subsonic local music library](docs/en/guide/subsonic-local-library.md).

<p align="center">
<img src="md/subsonic.png" width="500" alt="Subsonic connection">
Expand Down Expand Up @@ -340,7 +340,7 @@ Keep `subsonic-local-registry.json` and `subsonic-local-state.json` with user da

Playlist snapshots restore playlists; configuration backups restore configuration. Neither substitutes for audio backups. Configuration backups default to a seven-day retention period under the data directory's `backups/` folder.

In **System settings → Cloud backup scope**, select data types independently for WebDAV and OpenList. Both default to all five types below, but each provider must also be enabled and configured. Enabling both creates two copies; it does not synchronize the providers with each other.
In **Backup management → Cloud backup → Backup scope**, select data types independently for WebDAV and OpenList. Both default to all five types below, but each provider must also be enabled and configured. Enabling both creates two copies; it does not synchronize the providers with each other.

| Type | Contents |
| --- | --- |
Expand All @@ -361,9 +361,13 @@ These system settings are saved in the active `config.js` and have no correspond

An empty type array selects no data for that provider. Ordinary data backups always exclude caches, logs, temporary files, runtime databases and local backup archives. Back up root-directory music and custom external libraries separately. OpenList's **permanent playback cache** is configured separately; selecting music files does not enable cache uploads or local song deletion.

Set `configBackup.intervalHours` (default 24), `configBackup.scheduleTime` (default `00:00`), `webdav.retentionCount` (default 5) and `webdav.retentionDays` (default 0, no age limit) in the admin UI or `config.js`. OpenList connection/history/playback settings also use configuration keys; there are currently no corresponding `OPENLIST_*` environment mappings. See the [configuration reference](docs/en/guide/configuration.md#backup-configuration-keys-admin-ui-or-config-js) for defaults.

WebDAV incremental files and ZIP backups use the same scope, running every 60 minutes and 24 hours by default. OpenList stores data backups under `_data/` within its root and checks every 60 minutes by default. Ordinary backups retain local files. WebDAV also retains existing cloud files by default; explicitly enabling `backup.webdav.mirrorDeletes` propagates local deletions to the incremental directory, without changing historical ZIPs.

WebDAV startup restore is disabled by default and requires `backup.webdav.restoreOnStartup`. Manual restore downloads the provider's currently selected types, overwrites matching local files and preserves local-only files, without uploading local data. Restore is not an atomic replacement of the entire directory. Restart the service afterward to fully reload configuration, accounts, playlists and music indexes. Confirm the cloud namespace and selected scope before connecting a new installation. See [Backup and recovery](docs/en/guide/backup-recovery.md) for procedures.
Ordinary OpenList uploads check existence and size without downloading the body. Use **Backup management → Records and verification → OpenList → Content verification** for manual SHA-256 checks and preview the maximum body-read estimate before starting. Upload-and-delete cache mode still requires full verification.

WebDAV startup restore is disabled by default and requires `backup.webdav.restoreOnStartup`. WebDAV manual restore previews the selected scope, supports missing-only or overwrite, and preserves local-only files without uploads. Required files are staged and checked before replacement; commit failure attempts rollback, with pre-restore copies kept by default. Restore is not an atomic replacement of the entire directory. Restart the service afterward to fully reload configuration, accounts, playlists and music indexes. Confirm the cloud namespace and selected scope before connecting a new installation. See [Backup and recovery](docs/en/guide/backup-recovery.md) for procedures.

For container updates:

Expand Down Expand Up @@ -427,7 +431,7 @@ Defaults below refer to code defaults. Bundled configuration, saved values and i
| `ENABLE_LOGIN_USER_CACHE_RESTRICTION` | `user.enableLoginCacheRestriction` | Enable cache settings restriction for logged-in non-admin users | `false` |
| `ENABLE_CACHE_SIZE_LIMIT` | `user.enableCacheSizeLimit` | Enable cache size limit (auto-cleanup via LRU) | `false` |
| `CACHE_SIZE_LIMIT` | `user.cacheSizeLimit` | Cache size limit in MB | `2000` |
| `CONFIG_BACKUP_ENABLE` | `configBackup.enable` | Enable automatic config.js backup (creates daily backup copy) | `true` |
| `CONFIG_BACKUP_ENABLE` | `configBackup.enable` | Enable automatic config.js backup (default: every 24 hours) | `true` |
| `CONFIG_BACKUP_RETENTION_DAYS` | `configBackup.retentionDays` | Config backup retention period in days (auto cleans up expired backups) | `7` |
| `CONFIG_BACKUP_DIR` | `configBackup.dir` | Backup directory, relative to data; empty uses data/backups | `empty` |
| `SNAPSHOT_BACKUP_PATH` | `snapshot.backupPath` | Custom storage path for playlist snapshots (absolute or relative to `./data`) | - |
Expand Down
Loading
Loading