Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
32 changes: 32 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab

[*.{md,markdown}]
trim_trailing_whitespace = false

[*.{yml,yaml,json}]
indent_style = space
indent_size = 2

[*.py]
indent_style = space
indent_size = 4

[*.{nsi,nsh}]
indent_style = tab
# NSIS compiles on Windows toolchains; CRLF avoids diff noise there.
end_of_line = crlf

# JSplitter loads panel scripts as UTF-8 *with BOM*.
# Dropping the BOM produces mojibake for all Chinese strings in foobar2000.
# Do not "normalise" this away.
[amber/**.js]
charset = utf-8-bom
end_of_line = lf
indent_style = tab
34 changes: 34 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Default: let git normalise text files in the repo, check out per-platform.
* text=auto

# Source files always stored with LF.
*.js text eol=lf
*.py text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.txt text eol=lf
.editorconfig text eol=lf

# NSIS sources are consumed by makensis on Windows runners.
*.nsi text eol=crlf
*.nsh text eol=crlf

# Binary payloads - never touch these.
*.fth binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.bmp binary
*.dll binary
*.exe binary
*.zip binary
*.7z binary
*.ttf binary
*.otf binary

# Keep screenshots out of language statistics.
docs/** linguist-documentation
80 changes: 80 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: CI

# Validation runs on Linux — every check in validate-release.py is
# platform-independent (BOM, line endings, JS syntax, path scanning).
# Only the NSIS compile needs Windows, and that lives in release.yml.

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'

# validate-release.py shells out to `node --check` for JS syntax.
- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Validate release rules
run: python3 scripts/validate-release.py

- name: Stage release artefacts
run: python3 scripts/stage-release.py --clean

# Catches drift between manifest.json and the installer: if the NSI
# stops matching the generated defines, the release build would fail
# at tag time instead of here.
- name: Check installer references generated version
run: |
grep -q 'dist\\version.nsh' installer/Amber.nsi \
|| (echo "Amber.nsi no longer includes the generated version.nsh" && exit 1)
grep -q 'PRODUCT_VERSION' dist/version.nsh \
|| (echo "version.nsh is missing PRODUCT_VERSION" && exit 1)

- name: Upload theme-only zip
uses: actions/upload-artifact@v4
with:
name: Amber-ThemeOnly
path: dist/*.zip
if-no-files-found: error

# Compiles the installer on every push so packaging breakage surfaces
# immediately, rather than at tag time when it blocks a release.
build-installer:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Stage release artefacts
run: python scripts/stage-release.py --clean

- name: Generate installer assets
run: python installer/assets/make-assets.py

- name: Install NSIS
run: choco install nsis -y

- name: Compile installer
run: makensis installer/Amber.nsi

- name: Upload installer
uses: actions/upload-artifact@v4
with:
name: Amber-Setup
path: dist/*.exe
if-no-files-found: error
115 changes: 115 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Release

# Publishes a GitHub Release when a tag is pushed. The tag name (vX.Y.Z) must
# match the version in manifest.json, or the build fails.

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (e.g., v1.3.0)'
required: true

jobs:
build-and-release:
runs-on: windows-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Extract version from tag
shell: bash
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.tag }}"
else
TAG="${{ github.ref_name }}"
fi
VERSION="${TAG#v}"
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "TAG=$TAG" >> $GITHUB_ENV

- name: Validate release rules
run: python scripts/validate-release.py

- name: Check version matches tag
shell: bash
run: |
MANIFEST_VERSION=$(python -c "import json; print(json.load(open('manifest.json'))['version'])")
if [ "$MANIFEST_VERSION" != "$VERSION" ]; then
echo "Version mismatch: tag is $VERSION, manifest.json is $MANIFEST_VERSION"
exit 1
fi
echo "Version $VERSION matches tag $TAG"

- name: Stage release artefacts
run: python scripts/stage-release.py --clean

- name: Generate installer assets
run: python installer/assets/make-assets.py

- name: Compile installer
run: makensis installer/Amber.nsi

# The installer only exists now, so checksums must be recomputed to
# cover it — staging ran before makensis and saw only the zip.
- name: Recompute checksums
run: python scripts/stage-release.py --checksums-only

- name: Verify artefacts and collect checksums
shell: bash
run: |
ls -lh dist/*.zip dist/*.exe dist/SHA256SUMS.txt
test -s dist/SHA256SUMS.txt || (echo "SHA256SUMS.txt is empty" && exit 1)
grep -q '\.exe$' dist/SHA256SUMS.txt \
|| (echo "SHA256SUMS.txt does not cover the installer" && exit 1)
# Expose the file for the release body via a heredoc-delimited env var.
{
echo 'SHA256SUMS<<SUMS_EOF'
cat dist/SHA256SUMS.txt
echo 'SUMS_EOF'
} >> "$GITHUB_ENV"

- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.TAG }}
name: Amber ${{ env.VERSION }}
body: |
## Installation

**Installer** (recommended):
Download `Amber-Setup-x64-${{ env.VERSION }}.exe` and run it. It detects your foobar2000 installation, checks for JSplitter, and installs Amber's scripts + layout into your profile.

**Manual** (theme-only zip):
Download `Amber-ThemeOnly-v${{ env.VERSION }}.zip`, extract the `amber/` and `amber-layouts/` folders into your foobar2000 profile directory, then import the layout from Preferences → Display → Default User Interface.

Requires foobar2000 v2.0+ (x64) and [JSplitter](https://foobar2000.ru/forum/viewtopic.php?t=6378). See [INSTALL.md](https://github.com/${{ github.repository }}/blob/${{ env.TAG }}/INSTALL.md) for detailed instructions.

## Checksums

```
${{ env.SHA256SUMS }}
```

---

Full changelog: [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ env.TAG }}/CHANGELOG.md)
files: |
dist/*.exe
dist/*.zip
dist/SHA256SUMS.txt
draft: false
prerelease: ${{ contains(env.VERSION, '-') }}
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Build output - published as GitHub Release assets, never committed.
/build/
/dist/
/tmp/

# Packaged artefacts
*.exe
*.zip
*.7z
*.sha256
SHA256SUMS.txt

# Installer branding — deterministically regenerated by
# installer/assets/make-assets.py during every build, so the binaries
# themselves never need to be committed.
/installer/assets/*.ico
/installer/assets/*.bmp

# Logs and scratch
*.log
.venv/
__pycache__/
*.pyc

# Editor / OS noise
.vscode/
.idea/
.DS_Store
Thumbs.db
desktop.ini
24 changes: 22 additions & 2 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,31 @@ foobar2000 独立主题:琥珀暖色 · 封面墙 · 极简播放卡。

## 安装步骤

### 方式一:安装器(推荐)

从 [Releases](https://github.com/ShixSun/foobar2000-amber/releases/latest) 下载
`Amber-Setup-x64-*.exe` 并运行。安装器会:

1. 自动探测 foobar2000 安装位置(注册表 → App Paths → 常见路径),找不到可手动浏览
2. 校验版本 ≥ 2.0、架构为 x64
3. 判断便携版 / 标准版,定位对应 profile 目录
4. 检查 JSplitter 是否就位——缺失则给出下载链接并中止(没有它 Amber 无法运行)
5. 报告可选组件状态(缺失不影响安装)
6. **备份现有 `theme.fth`** 到 `amber-backups\<时间戳>\`,然后写入脚本与布局

> 安装器**不会**自动覆盖你的 `theme.fth`。布局导入是 foobar2000 里的一次点击,
> 而自动覆盖一旦出错会毁掉你可能调了几小时的布局——所以这一步留给你自己决定。

装完后按结束页提示导入布局即可(见下方第 3 步)。卸载可通过「程序和功能」或
profile 下的 `amber\Uninstall-Amber.exe`;备份目录不会被删除。

### 方式二:手动安装

1. 安装上述组件,重启 foobar2000
2. 把 `amber` 整个文件夹放进 foobar2000 的 **profile 目录**
(便携版 = 安装目录下的 `profile\`;标准版 = `%appdata%\foobar2000-v2\`)
3. 关闭 foobar2000,用本仓库的 `theme.fth` 覆盖 profile 下的 `theme.fth`
(或在 参数选择 → 显示 → 默认用户界面 里导入主题)
3. 参数选择 → 显示 → 默认用户界面 → **导入主题**,选择
`amber-layouts\amber-standard.fth`
4. 配色:参数选择 → 显示 → **颜色和字体** → 深色方案 → 自定义:
- 背景 `32, 27, 20`(暖炭)
- 高亮 `235, 165, 70`(琥珀)
Expand Down
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,24 @@

**foobar2000 琥珀主题 / An amber-toned, coverflow-centric theme for foobar2000 v2 (x64)**

> 墙负责"看",卡负责"读" —— 封面墙浏览 + 极简播放卡 + 全局琥珀暖色体系。
[![GitHub release](https://img.shields.io/github/v/release/ShixSun/foobar2000-amber?include_prereleases&label=latest)](https://github.com/ShixSun/foobar2000-amber/releases/latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![foobar2000](https://img.shields.io/badge/foobar2000-v2.0%2B%20(x64)-orange)](https://www.foobar2000.org/)

> 墙负责"看",卡负责"读" —— 封面墙浏览 + 极简播放卡 + 全局琥珀暖色体系。
> 全部面板为原创 JSplitter 脚本,由 [ShixSun](https://github.com/ShixSun) 与 Claude 共同设计打造。

![预览图](docs/screenshot-main.png)

## 下载安装 / Download

**[→ 最新版下载 / Latest Release](https://github.com/ShixSun/foobar2000-amber/releases/latest)**

- **推荐:安装器** `Amber-Setup-x64-*.exe` — 自动探测 foobar2000、检查组件、一键安装
- **手动:主题包** `Amber-ThemeOnly-v*.zip` — 解压到 profile 目录,手动导入布局

详细步骤见 **[INSTALL.md](INSTALL.md)**

## 特性

- **封面墙**:伪 3D 轮播(倒影/缓动动画/高质量插值),滚轮翻页、双击播放,
Expand All @@ -24,7 +37,8 @@

## 快速开始

见 [INSTALL.md](INSTALL.md)。核心三步:装 JSplitter → `amber\` 放进 profile → 导入 `theme.fth`。
见 [INSTALL.md](INSTALL.md)。安装器会自动完成全部步骤;手动安装的核心三步:
装 JSplitter → `amber\` 放进 profile → 导入 `amber-layouts\amber-standard.fth`。

## 定制

Expand All @@ -34,6 +48,7 @@
## License

[MIT](LICENSE) · 灵感致谢 [foobox](https://github.com/dream7180/foobox-cn),运行时依赖 JSplitter(请从官方渠道获取)。
第三方组件说明见 [THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md)。

---

Expand All @@ -47,5 +62,10 @@ codec/bitrate info and queue badges), and a **playlist sidebar** with a global s
results panel. All panels are hand-written JSplitter scripts — no third-party
theme dependencies. Colors follow foobar2000's own "Colors and Fonts" settings
(suggested dark base `32,27,20` + highlight `235,165,70`), with amber accents layered
by the scripts. See [INSTALL.md](INSTALL.md) for setup. MIT licensed.
Designed by [ShixSun](https://github.com/ShixSun) & Claude, 2026.
by the scripts.

**Install:** grab the installer from [Releases](https://github.com/ShixSun/foobar2000-amber/releases/latest),
or see [INSTALL.md](INSTALL.md) for the manual route. Requires foobar2000 v2.0+ (x64)
and [JSplitter](https://foobar2000.ru/forum/viewtopic.php?t=6378).

MIT licensed. Designed by [ShixSun](https://github.com/ShixSun) & Claude, 2026.
Loading
Loading