Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2394fdf
空壳播放器:可配置音源的音乐播放器(网页 / 桌面 / 安卓)
Makima667 Oct 26, 2026
ab34ffa
Release 工作流在 PR 上也打包,便于验证
Makima667 Oct 26, 2026
45e2cc3
CI:安卓改用 runner 自带的 Android SDK,升级 actions 版本
Makima667 Oct 26, 2026
1386cbe
安卓插件:升级 androidx.core(ServiceCompat.startForeground 需要 1.12+);构建失败时输出…
Makima667 Oct 26, 2026
70f1048
安卓插件:compileSdk 升到 36,满足 tauri-android 依赖的 AAR 要求
Makima667 Oct 26, 2026
5e05f90
体验打磨:上手引导、日常功能、手机与桌面适配、动效
Makima667 Oct 26, 2026
2b34609
安装包整理:Windows 装完带桌面快捷方式,精简产物并写清下载指引
Makima667 Oct 26, 2026
7fb7e75
Windows 安装程序:去掉自定义安装钩子,改用自带的桌面快捷方式选项;版权信息改为纯 ASCII
Makima667 Oct 26, 2026
a658103
CI:桌面打包失败时把关键报错输出成注解
Makima667 Oct 26, 2026
46624c9
Windows 安装程序:去掉简体中文界面设置
Makima667 Oct 26, 2026
38bce96
CI:PR 上只打包验证,不再往草稿 Release 里上传安装包
Makima667 Oct 26, 2026
418861a
CI:打标签时自动清理旧草稿、建 Release、传完各平台安装包后发布
Makima667 Oct 27, 2026
b63bffe
CI:手动运行可填版本标签直接发版,发布时自动建标签
Makima667 Oct 27, 2026
40fb78d
v0.2.0:本地音乐扫描、导入歌单、音源健康度与自动更新、歌词微调、应用内更新;发版不再打 Linux 包
Makima667 Oct 27, 2026
634c6e5
本地歌曲读标签(歌名、歌手、封面、内嵌歌词)、没歌词时借联网音源的歌词和封面;随机播放入口;安卓悬浮歌词、通知栏滚动歌词和媒体卡片封面
Makima667 Oct 27, 2026
866a2bf
界面改成平整简洁:内容铺满、播放条贴底、颜色收回中性,主题色只留给播放和正在播放;封面占位换成音符
Makima667 Oct 27, 2026
cd20b7f
换成新图标(律动三柱):桌面、安卓自适应图标、网页图标和侧栏标志;安卓打包时用仓库里的图标
Makima667 Oct 28, 2026
4c9c235
没有自动更新包时,桌面版改为查 GitHub 最新版本并打开下载页;自动更新装不上时也打开下载页;发布说明补充安卓签名不一致的处理
Makima667 Oct 28, 2026
3238f08
feat: 内置音源包,装好即可搜索播放
Makima667 Oct 28, 2026
885825d
chore(release): 发布说明改为「装好就有音源」
Makima667 Oct 28, 2026
0632f61
导入音源:认出只有接口名的专用线路列表(lines/searchApi),直接说明为什么导入不了
Makima667 Oct 29, 2026
5c295b0
修复:安卓通知栏和耳机按键的播放、切歌没反应(插件缺少事件监听权限);桌面版加全局快捷键(Ctrl+Alt+P / ← / → 等,可在设…
Makima667 Oct 29, 2026
77a0a85
feat(0.2.1): 内置音源只留体检通过的,撤掉已失效的元力系
Makima667 Oct 29, 2026
56ab3ca
fix: 在 5c295b0 之上重做内置音源替换(上一次推送覆盖了该提交的改动)
Makima667 Oct 29, 2026
7ab36f7
feat(0.2.2): 内置酷狗搜索源,配合洛雪源直接出无损
Makima667 Oct 29, 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
45 changes: 45 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CI

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

jobs:
web:
name: 测试 + 网页构建
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: web-dist
path: dist

rust:
name: 桌面端编译检查(Linux)
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v5
- name: 安装系统依赖
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libssl-dev
- uses: dtolnay/rust-toolchain@stable
- uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- run: npm ci && npm run build
- run: cargo check --manifest-path src-tauri/Cargo.toml
37 changes: 37 additions & 0 deletions .github/workflows/deploy-web.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: 部署网页版到 Cloudflare Pages

# 需要在仓库 Settings → Secrets and variables → Actions 里配置:
# CLOUDFLARE_API_TOKEN(权限:Cloudflare Pages 编辑)
# CLOUDFLARE_ACCOUNT_ID
# 先手动运行验证;确认没问题后可以把下面的 push 触发打开,合并到 main 自动部署
on:
workflow_dispatch:
# push:
# branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test
- run: npm run build
- name: 创建 Pages 项目(已存在会跳过)
uses: cloudflare/wrangler-action@v3
continue-on-error: true
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages project create shell-player --production-branch main
- name: 部署
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy dist --project-name shell-player --branch main
213 changes: 213 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
name: 打包发布(桌面 + 安卓)

# 发版:推送 v* 标签(例如 v0.1.0),或手动运行并填写版本标签。
# 先清掉同名的旧草稿,建一个新草稿,各平台安装包传完后自动发布(还没有标签时,发布时自动创建)
# Pull Request / 手动运行不填标签:只打包,安装包在本次运行的 Artifacts 里下载,用来验证
on:
push:
tags: ['v*']
pull_request:
workflow_dispatch:
inputs:
tag:
description: '要发布的版本标签,例如 v0.1.0;留空只打包验证'
required: false
default: ''

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: write

jobs:
prepare:
name: 准备 Release
if: github.ref_type == 'tag' || inputs.tag != ''
runs-on: ubuntu-latest
outputs:
release_id: ${{ steps.create.outputs.id }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
TAG: ${{ github.ref_type == 'tag' && github.ref_name || inputs.tag }}
steps:
- name: 删除同名的旧草稿
run: |
gh api "repos/$REPO/releases" --paginate --jq ".[] | select(.draft and .tag_name == \"$TAG\") | .id" | while read -r id; do
gh api -X DELETE "repos/$REPO/releases/$id" && echo "已删除旧草稿 $id"
done
- name: 新建草稿
id: create
run: |
cat > body.md <<'BODY'
下载对应系统的一个文件就行:

| 系统 | 下载 | 说明 |
|---|---|---|
| Windows | `ShellPlayer_*_x64-setup.exe` | 双击安装,不需要管理员权限;装完开始菜单里有快捷方式,最后一步勾选创建桌面快捷方式即可。首次可能弹 SmartScreen,点「更多信息 → 仍要运行」 |
| macOS | `ShellPlayer_*_universal.dmg` | 拖进「应用程序」。没有苹果签名,第一次打开要右键图标选「打开」 |
| 安卓 | `ShellPlayer-android.apk` | 需要允许「安装未知来源应用」 |

以后有新版本时,应用里会提示,并打开下载页(配好签名密钥后桌面版可以一键更新)。

安卓提示「签名不一致」或「与已安装的应用冲突」时,先卸载旧版再装(收藏和歌单会清空,可以先在设置里导出备份)。

装好就有音源:内置 9 个实测能出声的源(5 个洛雪源 + 网易云官方直连、QQ音乐官方直连、腾讯音乐、酷狗官方搜索),首次启动自动装进「音源」页,不用自己找。VIP 曲目可在插件设置里填自己的 MUSIC_U / QQ_UIN / QQ_KEY。
BODY
id=$(gh api "repos/$REPO/releases" -f tag_name="$TAG" -f target_commitish="$GITHUB_SHA" -f name="空壳播放器 $TAG" -F draft=true -F body=@body.md --jq .id)
echo "id=$id" >> "$GITHUB_OUTPUT"

desktop:
name: 桌面版 ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Windows
platform: windows-latest
args: ''
- name: macOS
platform: macos-latest
args: '--target universal-apple-darwin'
needs: prepare
if: ${{ !failure() && !cancelled() }}
runs-on: ${{ matrix.platform }}
env:
# 自动更新包的签名密钥。没配置时照常打包,只是不生成更新包
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
- uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri
- run: npm ci
- name: 生成自动更新包
if: env.TAURI_SIGNING_PRIVATE_KEY != ''
shell: bash
run: node -e "const f='src-tauri/tauri.conf.json',fs=require('fs'),c=JSON.parse(fs.readFileSync(f));c.bundle.createUpdaterArtifacts=true;fs.writeFileSync(f,JSON.stringify(c,null,2))"
# 不发版时只打包验证,不碰 Release
- name: 打包(验证)
if: needs.prepare.outputs.release_id == ''
run: npx tauri build ${{ matrix.args }}
- uses: tauri-apps/tauri-action@v0
if: needs.prepare.outputs.release_id != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
releaseId: ${{ needs.prepare.outputs.release_id }}
args: ${{ matrix.args }}
- name: 打包失败时输出错误
if: failure()
shell: bash
run: |
# 重跑一次打包(编译有缓存,很快),把关键报错写成注解,不用下载完整日志也能看到原因
npx tauri build ${{ matrix.args }} 2>&1 | tee bundle.log || true
grep -iE "error|warning|failed|abort|!include|invalid" bundle.log | grep -v "^\s*Compiling" | tail -40 | while IFS= read -r l; do echo "::error::$l"; done
- uses: actions/upload-artifact@v4
with:
name: desktop-${{ matrix.name }}
path: |
src-tauri/target/**/release/bundle/**/*-setup.exe
src-tauri/target/**/release/bundle/**/*.dmg
if-no-files-found: warn

android:
name: 安卓版
needs: prepare
if: ${{ !failure() && !cancelled() }}
# ubuntu-24.04 镜像自带 Android SDK
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
- name: 安装 NDK
run: |
echo "ANDROID_HOME=$ANDROID_HOME"
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install "ndk;27.0.12077973" "platforms;android-36" "build-tools;34.0.0" > /dev/null
echo "NDK_HOME=$ANDROID_HOME/ndk/27.0.12077973" >> $GITHUB_ENV
echo "ANDROID_SDK_ROOT=$ANDROID_HOME" >> $GITHUB_ENV
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android,armv7-linux-androideabi,x86_64-linux-android
- uses: swatinem/rust-cache@v2
with:
workspaces: src-tauri
- run: npm ci
- name: 生成安卓工程
run: |
npx tauri android init --ci
# 用仓库里的图标(自适应图标前景 + 深色底)覆盖模板自带的
cp -r src-tauri/icons/android/. src-tauri/gen/android/app/src/main/res/
# 很多音频地址是 http,正式版也需要允许明文流量
sed -i 's/manifestPlaceholders\["usesCleartextTraffic"\] = "false"/manifestPlaceholders["usesCleartextTraffic"] = "true"/' src-tauri/gen/android/app/build.gradle.kts
- name: 构建 APK
run: |
set -o pipefail
npx tauri android build --apk --target aarch64 --target armv7 --target x86_64 2>&1 | tee build.log || {
# 把关键错误写成注解,方便不打开完整日志也能看到原因
grep -E "^e: |error:|ERROR|FAILURE|What went wrong" -A3 build.log | head -60 | while IFS= read -r l; do echo "::error::$l"; done
exit 1
}
- name: 签名
env:
KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
run: |
APK=$(find src-tauri/gen/android/app/build/outputs/apk -name '*-unsigned.apk' | head -1)
echo "未签名 APK:$APK"
if [ -n "$KEYSTORE_B64" ]; then
echo "$KEYSTORE_B64" | base64 -d > release.jks
ALIAS="$KEY_ALIAS"; PASS="$KEYSTORE_PASSWORD"
else
echo "::warning::没有配置签名密钥,使用临时密钥签名(可以安装测试,但以后无法覆盖升级)"
keytool -genkeypair -v -keystore release.jks -alias shellplayer -keyalg RSA -keysize 2048 -validity 10000 -storepass shellplayer -keypass shellplayer -dname "CN=ShellPlayer"
ALIAS=shellplayer; PASS=shellplayer
fi
BT=$ANDROID_HOME/build-tools/34.0.0
$BT/zipalign -f -p 4 "$APK" aligned.apk
$BT/apksigner sign --ks release.jks --ks-key-alias "$ALIAS" --ks-pass pass:"$PASS" --key-pass pass:"$PASS" --out ShellPlayer-android.apk aligned.apk
$BT/apksigner verify ShellPlayer-android.apk
- uses: actions/upload-artifact@v4
with:
name: android-apk
path: ShellPlayer-android.apk

publish:
name: 发布 Release
needs: [prepare, desktop, android]
if: needs.prepare.outputs.release_id != ''
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
ID: ${{ needs.prepare.outputs.release_id }}
steps:
- uses: actions/download-artifact@v4
with:
name: android-apk
- name: 上传安卓 APK
run: |
url=$(gh api "repos/$REPO/releases/$ID" --jq .upload_url | sed 's/{.*}//')
gh api -X POST "$url?name=ShellPlayer-android.apk" -H "Content-Type: application/vnd.android.package-archive" --input ShellPlayer-android.apk --jq .name
- name: 发布
run: |
gh api -X PATCH "repos/$REPO/releases/$ID" -F draft=false -f make_latest=true --jq .html_url
gh api "repos/$REPO/releases/$ID" --jq '.assets[] | "\(.name) \(.size)"'
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
dist/
src-tauri/target/
src-tauri/gen/schemas/
plugins/*/target/
*.log
.DS_Store
Loading
Loading