From e6e83aed5ba4e6614115c85d432f3bffe7eef5de Mon Sep 17 00:00:00 2001 From: maogeddd Date: Thu, 15 Jan 2026 00:37:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(solara):=20=E6=B7=BB=E5=8A=A0Solara(?= =?UTF-8?q?=E5=85=89=E5=9F=9F)=E9=9F=B3=E4=B9=90=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=20(#3437)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加Solara(光域)音乐播放器 * 📝 docs(solara): optimize project documentation and add multilingual support - add init.sh script for automatic SESSION_SECRET generation - rewrite and simplify main README.md content for clarity - add new README_en.md file with full English translation - update data.yml with multilingual descriptions (zh-Hant, ja, ms, pt-br, ru, ko) - change app type from 'tool' to 'website' in metadata - remove deprecated _env.sample file - update latest/data.yml with multilingual form field labels and descriptions - simplify docker-compose.yml and add pull_policy - compress application logo image --------- Co-authored-by: pooneyy <85266337+pooneyy@users.noreply.github.com> --- apps/solara/README.md | 18 +++++++++++ apps/solara/README_en.md | 18 +++++++++++ apps/solara/data.yml | 30 ++++++++++++++++++ apps/solara/latest/data.yml | 42 ++++++++++++++++++++++++++ apps/solara/latest/docker-compose.yml | 20 ++++++++++++ apps/solara/latest/scripts/init.sh | 14 +++++++++ apps/solara/logo.png | Bin 0 -> 7551 bytes 7 files changed, 142 insertions(+) create mode 100644 apps/solara/README.md create mode 100644 apps/solara/README_en.md create mode 100644 apps/solara/data.yml create mode 100644 apps/solara/latest/data.yml create mode 100644 apps/solara/latest/docker-compose.yml create mode 100644 apps/solara/latest/scripts/init.sh create mode 100644 apps/solara/logo.png diff --git a/apps/solara/README.md b/apps/solara/README.md new file mode 100644 index 000000000..e6addd4f8 --- /dev/null +++ b/apps/solara/README.md @@ -0,0 +1,18 @@ +## 产品介绍 + +由轻量后端服务支撑的现代化网页音乐播放器,整合多种音乐聚合接口,覆盖搜索、播放与音频下载全流程。 + +## 主要功能 + +- **主题美学**:内置亮/暗模式与玻璃拟态界面,根据当前曲目封面自动取色渲染沉浸式背景,具备沉浸体验。 +- **竖屏移动端**:全新竖屏布局匹配移动端手势与屏幕比例,按钮、列表与歌词均针对单手操作优化。 +- **跨站曲库检索**:一键切换数据源,支持分页浏览并批量导入播放队列。 +- **队列管理灵活**:新增、删除、清空操作即时生效,并自动持久化到浏览器 localStorage。 +- **收藏列表**:搜索结果与播放列表均可一键收藏,收藏列表拥有独立的播放进度、播放模式与批量操作面板。 +- **丰富的播放模式**:列表循环、单曲循环与随机播放随手切换,记忆上次偏好。 +- **动态歌词视图**:逐行滚动高亮,当前行自动聚焦,手动滚动后短暂锁定视图。 +- **列表导入导出**:支持播放队列与收藏列表统一导入/导出,可一键迁移或恢复收藏歌曲并同步到播放队列。 +- **多码率下载**:可挑选 128K / 192K / 320K / FLAC 等品质并直接获取音频文件。 +- **轻量后端代理**:通过 Cloudflare Pages Functions 统一聚合各数据源并处理音频跨域。 +- **锁屏播放控制**:锁屏界面自动显示专辑封面与播放控件,无需解锁即可进行播放控制。 +- **调试控制台**:按下 Ctrl + D 呼出实时日志面板,便于排查接口或交互异常。 \ No newline at end of file diff --git a/apps/solara/README_en.md b/apps/solara/README_en.md new file mode 100644 index 000000000..851081a14 --- /dev/null +++ b/apps/solara/README_en.md @@ -0,0 +1,18 @@ +## Introduction + +A modern web music player powered by lightweight backend services, integrating multiple music aggregation interfaces, covering the entire process from search and playback to audio download. + +## Features + +- **Thematic Aesthetics**: Built-in light/dark modes and a glass morphism interface automatically extract colors from the current track's cover to render immersive backgrounds, delivering an engaging experience. +- **Vertical Mobile Interface**: A new vertical screen layout matches mobile gestures and screen proportions, with buttons, lists, and lyrics optimized for one-handed operation. +- **Cross-Site Music Library Search**: Switch data sources with one click, supporting paginated browsing and batch import to the playback queue. +- **Flexible Queue Management**: Add, delete, and clear operations take effect immediately and are automatically persisted to the browser's localStorage. +- **Favorites List**: Search results and playlists can be added to favorites with one click. The Favorites List features independent playback progress, playback modes, and a batch operation panel. +- **Rich Playback Modes**: Seamlessly switch between list loop, single-track loop, and shuffle play, with preferences remembered from the last session. +- **Dynamic Lyrics View**: Scrolling highlight line-by-line, auto-focus on the current line, with view temporarily locked after manual scrolling. +- **List Import/Export**: Supports unified import/export of playback queue and favorites list, enabling seamless migration or restoration of favorite songs and synchronization to the playback queue. +- **Multi-bitrate Downloads**: Select from 128K / 192K / 320K / FLAC quality options and directly obtain audio files. +- **Lightweight Backend Proxy**: Unifies and aggregates various data sources via Cloudflare Pages Functions while handling audio cross-origin requests. +- **Lock Screen Playback Controls**: Automatically displays album art and playback controls on the lock screen, allowing playback control without unlocking the device. +- **Debug Console**: Press Ctrl + D to summon a real-time log panel, making it easier to troubleshoot interface or interaction issues. \ No newline at end of file diff --git a/apps/solara/data.yml b/apps/solara/data.yml new file mode 100644 index 000000000..6c1d3fde7 --- /dev/null +++ b/apps/solara/data.yml @@ -0,0 +1,30 @@ +name: Solara(光域) +tags: + - 多媒体 +title: 基于免费API的极简风格音乐播放器 +description: 基于免费API的极简风格音乐播放器 +additionalProperties: + key: solara + name: Solara(光域) + tags: + - Media + shortDescZh: 基于免费API的极简风格音乐播放器 + shortDescEn: A minimalist style music player based on free API + description: + en: A minimalist style music player based on free API + zh: 基于免费API的极简风格音乐播放器 + zh-Hant: 基於免費API的極簡風格音樂播放器 + ja: 無料APIを基にしたミニマリストスタイルの音楽プレーヤー + ms: Pemain muzik gaya minimalis berdasarkan API percuma + pt-br: Um player de música estilo minimalista baseado em API gratuita + ru: Минималистичный музыкальный плеер на основе бесплатного API + ko: 무료 API 기반의 미니멀리스트 스타일 음악 플레이어 + type: website + crossVersionUpdate: true + limit: 0 + website: https://github.com/akudamatata/Solara + github: https://github.com/akudamatata/Solara + document: https://github.com/akudamatata/Solara + architectures: + - amd64 + - arm64 diff --git a/apps/solara/latest/data.yml b/apps/solara/latest/data.yml new file mode 100644 index 000000000..5be8ab86f --- /dev/null +++ b/apps/solara/latest/data.yml @@ -0,0 +1,42 @@ +additionalProperties: + formFields: + - default: 8080 + envKey: PANEL_APP_PORT_HTTP + labelZh: HTTP 端口 + labelEn: HTTP Port + label: + zh: HTTP 端口 + zh-Hant: HTTP 連接埠 + en: HTTP Port + ja: HTTP ポート + ko: HTTP 포트 + ms: Port HTTP + pt-br: Porta HTTP + ru: HTTP Порт + tr: HTTP Portu + description: + zh: "设置应用的 HTTP 访问端口,有效范围: 1-65535" + zh-Hant: "設定應用程式的 HTTP 存取連接埠,有效範圍: 1-65535" + en: "Set the HTTP access port for the application, valid range: 1-65535" + ja: "アプリケーションのHTTPアクセスポートを設定します。有効範囲: 1-65535" + ko: "애플리케이션의 HTTP 접근 포트를 설정합니다. 유효 범위: 1-65535" + ms: "Tetapkan port akses HTTP untuk aplikasi, julat sah: 1-65535" + pt-br: "Defina a porta de acesso HTTP para o aplicativo, intervalo válido: 1-65535" + ru: "Установите порт доступа HTTP для приложения, допустимый диапазон: 1-65535" + tr: "Uygulama için HTTP erişim portunu ayarlayın, geçerli aralık: 1-65535" + required: true + type: number + edit: true + rule: paramPort + - default: solara + envKey: SOLARA_PASSWORD + labelZh: 登录密码 + labelEn: Login Password + label: + zh: 登录密码 + en: Login Password + required: true + type: password + edit: true + rule: paramComplexity + random: true diff --git a/apps/solara/latest/docker-compose.yml b/apps/solara/latest/docker-compose.yml new file mode 100644 index 000000000..174f11f17 --- /dev/null +++ b/apps/solara/latest/docker-compose.yml @@ -0,0 +1,20 @@ +services: + solara-music: + image: aexus/solara-music:latest + container_name: ${CONTAINER_NAME} + restart: always + pull_policy: always + networks: + - 1panel-network + ports: + - ${PANEL_APP_PORT_HTTP}:3001 + environment: + - NODE_ENV=production + - PORT=3001 + - SOLARA_PASSWORD=${SOLARA_PASSWORD} + - SESSION_SECRET=${SESSION_SECRET} + labels: + createdBy: Apps +networks: + 1panel-network: + external: true diff --git a/apps/solara/latest/scripts/init.sh b/apps/solara/latest/scripts/init.sh new file mode 100644 index 000000000..fc41220f0 --- /dev/null +++ b/apps/solara/latest/scripts/init.sh @@ -0,0 +1,14 @@ +#!/bin/bash +if [[ ! -f ".env" ]]; then + exit 1 +fi +NEW_SECRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 32) +if grep -q "SESSION_SECRET=" .env; then + if [[ "$(uname)" == "Darwin" ]]; then + sed -i '' "s/SESSION_SECRET=.*/SESSION_SECRET=$NEW_SECRET/" .env + else + sed -i "s/SESSION_SECRET=.*/SESSION_SECRET=$NEW_SECRET/" .env + fi +else + echo "SESSION_SECRET=$NEW_SECRET" >> .env +fi diff --git a/apps/solara/logo.png b/apps/solara/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fddfdcf5cc3986f88fed6eb6f0ba201d39a76b31 GIT binary patch literal 7551 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 literal 0 HcmV?d00001