diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e6a8ec52..712aa7f47 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -184,31 +184,6 @@ jobs: # 默认不启用 voice feature(包含 whisper-rs,编译很慢) args: --target ${{ matrix.target }} - - name: Build Tauri app (Windows online) - if: matrix.platform == 'windows-2022' - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # 禁用 LTO 加速编译(正式发布可改为 thin) - CARGO_PROFILE_RELEASE_LTO: "off" - # 增加并行编译单元 - CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 32 - CARGO_INCREMENTAL: 0 - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: sccache - with: - tauriScript: npx tauri - projectPath: src-tauri - tagName: ${{ github.event.inputs.version || github.ref_name }} - releaseName: "Lime ${{ github.event.inputs.version || github.ref_name }}" - releaseBody: ${{ env.RELEASE_BODY }} - releaseDraft: false - prerelease: false - # 默认推荐在线小包,安装时按需拉取 WebView2 - releaseAssetNamePattern: "[name]_[version]_[arch]-online[setup][ext]" - # 默认不启用 voice feature(包含 whisper-rs,编译很慢) - args: --target ${{ matrix.target }} --config tauri.windows.online.conf.json - - name: Build Tauri app (Windows offline) if: matrix.platform == 'windows-2022' uses: tauri-apps/tauri-action@v0 @@ -229,11 +204,36 @@ jobs: releaseBody: ${{ env.RELEASE_BODY }} releaseDraft: false prerelease: false - # 离线大包内置 WebView2 离线安装器,适用于无网环境 - releaseAssetNamePattern: "[name]_[version]_[arch]-offline[setup][ext]" + # tauri-action@v0 使用 assetNamePattern,离线包优先上传并保留独立名称 + assetNamePattern: "[name]_[version]_[arch]-offline[setup][ext]" # 默认不启用 voice feature(包含 whisper-rs,编译很慢) args: --target ${{ matrix.target }} --config tauri.windows.conf.json + - name: Build Tauri app (Windows online) + if: matrix.platform == 'windows-2022' + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # 禁用 LTO 加速编译(正式发布可改为 thin) + CARGO_PROFILE_RELEASE_LTO: "off" + # 增加并行编译单元 + CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 32 + CARGO_INCREMENTAL: 0 + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: sccache + with: + tauriScript: npx tauri + projectPath: src-tauri + tagName: ${{ github.event.inputs.version || github.ref_name }} + releaseName: "Lime ${{ github.event.inputs.version || github.ref_name }}" + releaseBody: ${{ env.RELEASE_BODY }} + releaseDraft: false + prerelease: false + # tauri-action@v0 使用 assetNamePattern,在线包作为体积更小的备选 + assetNamePattern: "[name]_[version]_[arch]-online[setup][ext]" + # 默认不启用 voice feature(包含 whisper-rs,编译很慢) + args: --target ${{ matrix.target }} --config tauri.windows.online.conf.json + - name: Build Tauri app (macOS with notarization, attempt 1) id: build_macos_primary if: matrix.platform == 'macos-latest' diff --git a/README.md b/README.md index 20950da7a..adc71c1fa 100644 --- a/README.md +++ b/README.md @@ -126,8 +126,8 @@ brew install --cask lime 从 [Releases](https://github.com/aiclientproxy/lime/releases) 下载对应平台安装包。 -- Windows 用户默认优先下载 `Lime_*_x64-online-setup.exe`(NSIS 在线安装器,体积更小) -- 如果处于离线、内网或受限网络环境,请改用 `Lime_*_x64-offline-setup.exe` +- Windows 用户优先下载 `Lime_*_x64-offline-setup.exe`(NSIS 离线安装器,内置 WebView2,安装更完整) +- 如果只想下载更小的安装器,且当前网络可稳定访问微软下载源,再选择 `Lime_*_x64-online-setup.exe` - 如被 SmartScreen 拦截,属于未签名或签名信誉不足的 Windows 常见提示,不代表安装包必然损坏 --- diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 813992992..22d2e2a87 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -22,8 +22,8 @@ ### 📦 Windows 下载说明 -- `Lime_*_x64-online-setup.exe`:默认推荐,体积更小,安装时按需下载 WebView2 -- `Lime_*_x64-offline-setup.exe`:适用于离线、内网或受限网络环境 +- `Lime_*_x64-offline-setup.exe`:推荐优先使用,内置 WebView2 离线安装器,安装更完整 +- `Lime_*_x64-online-setup.exe`:体积更小,适合网络稳定且可访问微软下载源的环境 - 如果在线安装失败,请改用离线安装包 --- diff --git a/docs/oem/logo.md b/docs/oem/logo.md new file mode 100644 index 000000000..154184d71 --- /dev/null +++ b/docs/oem/logo.md @@ -0,0 +1,204 @@ +# OEM Logo 快速替换指南 + +本文用于未来 OEM / 代理商定制时,快速把 Lime 的品牌图替换为代理商品牌图,并尽量让 AI 一次完成主要资产更新。 + +目标不是讲设计理论,而是提供一条可执行、可复用、低沟通成本的流程。 + +## 适用范围 + +适用于以下两类需求: + +1. 只替换图形 Logo,不改产品名、包名、文案。 +2. 同时替换 Logo 与对外品牌名,例如启动页 slogan、README 下载文案、发布说明。 + +## 当前仓库里的关键 Logo 落点 + +执行 OEM 替换时,优先关注这些位置: + +- 通用前端 Logo:`public/logo.png` +- 启动页专用 Logo:`public/logo-splash.png` +- 桌面端打包图标:`src-tauri/icons/` +- 浏览器页签图标:`index.html` 中引用的 `/logo.png` +- 直接引用前端 Logo 的页面: + - `src/components/AppSidebar.tsx` + - `src/components/SplashScreen.tsx` + - `src/components/onboarding/steps/WelcomeStep.tsx` + - `src/components/settings-v2/system/about/index.tsx` + - `src/components/agent/chat/components/MessageList.tsx` + +注意: + +- `src-tauri/icons/tray/*` 是托盘状态图,不一定适合直接换成 OEM Logo。 +- 如果只是换品牌图,通常不要动 tray 状态图。 + +## 推荐输入物 + +给 AI 或执行者提供以下输入,成功率最高: + +1. 一张高分辨率透明底主 Logo,建议 `2048x2048` 或更高。 +2. 一个简短的品牌定位描述。 + 例如:`偏企业、稳重、科技蓝绿` 或 `轻快、创意、果汁感` +3. 是否需要同步替换 slogan。 +4. 是否需要同步替换产品名。 + +推荐把 OEM 原始图先放到仓库根目录,命名为: + +```text +oem-logo.png +``` + +如果还有启动页专用版本,也可以额外提供: + +```text +oem-logo-splash.png +``` + +## 标准替换流程 + +### 方案 A:只替换 Logo + +1. 把 OEM Logo 放到仓库根目录,例如 `oem-logo.png` +2. 让 AI 先扫描引用点和打包图标目录 +3. 更新 `public/logo.png` +4. 单独生成 `public/logo-splash.png` +5. 同步生成 `src-tauri/icons/` 下的桌面端图标资产 +6. 保持 `src-tauri/icons/tray/*` 不变 +7. 跑 `npm run lint` + +### 方案 B:Logo + 品牌名一起替换 + +在方案 A 基础上,再额外处理: + +1. 启动页 slogan +2. README 下载说明 +3. `RELEASE_NOTES.md` +4. 如果是完整品牌切换,再继续检查: + - `package.json` + - `src-tauri/tauri.conf.json` + - 深链 scheme + - 安装包命名 + - GitHub Release 文案 + +## 推荐给 AI 的单次提示词 + +下面这段可以直接复制给 AI,通常一轮就能完成大部分替换: + +```text +请帮我把当前仓库的品牌图替换为 OEM Logo。 + +输入图片路径: +- 主 Logo:./oem-logo.png + +要求: +1. 先扫描仓库里当前 logo 的引用点和图标资产,不要盲改。 +2. 替换通用前端 logo:public/logo.png +3. 为启动页单独生成一张更适合大尺寸展示的专用图:public/logo-splash.png +4. 同步更新 src-tauri/icons/ 下的桌面端打包图标,包括 png / ico / icns / ios / android 图标集 +5. 不要替换 src-tauri/icons/tray/*,这些是状态图标 +6. 如果启动页当前复用通用 logo,请改成单独引用 logo-splash.png +7. 如果启动页视觉太小,请顺手调整 SplashScreen 的布局和尺寸,让 logo 更显眼 +8. 除非我明确要求,不要改产品名、包名、identifier +9. 修改完成后执行 npm run lint +10. 最后告诉我改了哪些文件、哪些图标已同步、哪些没有动 + +实现约束: +- 修改前先读文件 +- 不要改无关业务逻辑 +- 保持 macOS / Windows / Android / iOS 图标资产一致 +``` + +## 如果还要一起改 slogan + +把上面的提示词补充为: + +```text +另外把启动页改成只保留 logo、slogan、进度动画。 +新的 slogan 是: +“青柠一下,灵感即来。” +``` + +## 如果还要一起改品牌名 + +把上面的提示词再补充为: + +```text +这是一次 OEM 品牌替换,不只是换图。 +请额外扫描并更新对外展示名称、README、RELEASE_NOTES、GitHub Release 文案。 +但先不要擅自修改历史 tag。 +``` + +## AI 执行后的核对清单 + +完成后至少检查以下内容: + +### 视觉核对 + +- 浏览器页签是否已经换成 OEM Logo +- 侧边栏 / About / 欢迎页是否已经换图 +- 启动页是否明显使用了单独的大图,而不是缩小后的通用 logo +- 启动页 Logo 是否居中,是否存在透明留白过大问题 + +### 打包核对 + +- `src-tauri/icons/icon.png` +- `src-tauri/icons/icon.ico` +- `src-tauri/icons/icon.icns` +- `src-tauri/icons/ios/*` +- `src-tauri/icons/android/*` + +### 命令核对 + +```bash +npm run lint +``` + +如果这次同时改了 Tauri 或 Rust 相关资源生成流程,补跑: + +```bash +cargo check --manifest-path "src-tauri/Cargo.toml" --offline +``` + +## 常见问题 + +### 1. 启动页 logo 看起来还是小 + +通常不是图片太小,而是: + +- 启动页复用了 `public/logo.png` +- Logo 外面套了过厚的卡片、边框或内边距 +- 透明边界太大 + +解决方式: + +1. 单独生成 `public/logo-splash.png` +2. 把启动页改成专用引用 +3. 去掉厚重容器,只保留大 logo + slogan + 进度动画 + +### 2. Windows Release 里只看到一个 setup.exe + +这通常不是图标问题,而是 CI 的 Windows 在线包 / 离线包命名或上传逻辑有冲突。 + +重点检查: + +- `.github/workflows/release.yml` +- `assetNamePattern` +- Windows offline / online 构建顺序 + +### 3. tray 图标看起来不适合直接 OEM + +这是正常的。 + +tray 图标承担的是状态表达,不是品牌海报位。除非 OEM 要求非常明确,否则建议保持原状态图逻辑不变。 + +## 建议的资产策略 + +未来长期维护时,建议默认拆成两类资源: + +1. 通用品牌图 + - `public/logo.png` + - `src-tauri/icons/*` + +2. 场景专用品牌图 + - `public/logo-splash.png` + +这样后续即使继续 OEM,也能避免“一个 logo 到处复用,结果某个场景总显得小或不协调”。 diff --git a/public/logo-splash.png b/public/logo-splash.png new file mode 100644 index 000000000..032e89e46 Binary files /dev/null and b/public/logo-splash.png differ diff --git a/public/logo.png b/public/logo.png index b952533b8..cf14b17a7 100644 Binary files a/public/logo.png and b/public/logo.png differ diff --git a/src-tauri/crates/core/src/tool_calling.rs b/src-tauri/crates/core/src/tool_calling.rs index e3366ff7f..8af82423f 100644 --- a/src-tauri/crates/core/src/tool_calling.rs +++ b/src-tauri/crates/core/src/tool_calling.rs @@ -227,9 +227,9 @@ mod tests { } fn clear_tool_calling_envs() { - std::env::remove_var(ENV_TOOLCALL_V2_ENABLED); - std::env::remove_var(ENV_TOOLCALL_V2_DYNAMIC_FILTERING); - std::env::remove_var(ENV_TOOLCALL_V2_NATIVE_INPUT_EXAMPLES); + std::env::remove_var(ENV_TOOLCALL_V2_ENABLED[0]); + std::env::remove_var(ENV_TOOLCALL_V2_DYNAMIC_FILTERING[0]); + std::env::remove_var(ENV_TOOLCALL_V2_NATIVE_INPUT_EXAMPLES[0]); } #[test] @@ -258,9 +258,9 @@ mod tests { native_input_examples: false, }); - std::env::set_var(ENV_TOOLCALL_V2_ENABLED, "true"); - std::env::set_var(ENV_TOOLCALL_V2_DYNAMIC_FILTERING, "1"); - std::env::set_var(ENV_TOOLCALL_V2_NATIVE_INPUT_EXAMPLES, "on"); + std::env::set_var(ENV_TOOLCALL_V2_ENABLED[0], "true"); + std::env::set_var(ENV_TOOLCALL_V2_DYNAMIC_FILTERING[0], "1"); + std::env::set_var(ENV_TOOLCALL_V2_NATIVE_INPUT_EXAMPLES[0], "on"); assert!(tool_calling_v2_enabled()); assert!(tool_calling_dynamic_filtering_enabled()); diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png index 114674938..2a4faff18 100644 Binary files a/src-tauri/icons/128x128.png and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png index 8febe26a6..bda5fda39 100644 Binary files a/src-tauri/icons/128x128@2x.png and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png index 736d21d24..0c8012a14 100644 Binary files a/src-tauri/icons/32x32.png and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/64x64.png b/src-tauri/icons/64x64.png index bca737e29..5efab6a5c 100644 Binary files a/src-tauri/icons/64x64.png and b/src-tauri/icons/64x64.png differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png index d406a657f..0f695699a 100644 Binary files a/src-tauri/icons/Square107x107Logo.png and b/src-tauri/icons/Square107x107Logo.png differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png index 6be3ed731..1e590689e 100644 Binary files a/src-tauri/icons/Square142x142Logo.png and b/src-tauri/icons/Square142x142Logo.png differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png index 755176693..bb51a844a 100644 Binary files a/src-tauri/icons/Square150x150Logo.png and b/src-tauri/icons/Square150x150Logo.png differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png index 6b32de8bd..7d3577aa1 100644 Binary files a/src-tauri/icons/Square284x284Logo.png and b/src-tauri/icons/Square284x284Logo.png differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png index 70f4922a2..2b132f254 100644 Binary files a/src-tauri/icons/Square30x30Logo.png and b/src-tauri/icons/Square30x30Logo.png differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png index f4c36da7b..b6f5d9fd7 100644 Binary files a/src-tauri/icons/Square310x310Logo.png and b/src-tauri/icons/Square310x310Logo.png differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png index 30049b57d..5b64ef61d 100644 Binary files a/src-tauri/icons/Square44x44Logo.png and b/src-tauri/icons/Square44x44Logo.png differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png index 38dddc22e..465b03cce 100644 Binary files a/src-tauri/icons/Square71x71Logo.png and b/src-tauri/icons/Square71x71Logo.png differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png index 6af0ec971..d5dc68250 100644 Binary files a/src-tauri/icons/Square89x89Logo.png and b/src-tauri/icons/Square89x89Logo.png differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png index 7f4a29dfc..724883cc2 100644 Binary files a/src-tauri/icons/StoreLogo.png and b/src-tauri/icons/StoreLogo.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png index 1b5c33661..7e49dc8a3 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png index a14ad35ae..ff64b1920 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png index 57032281a..7e49dc8a3 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png index 9cca52859..e593a85b5 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png index ab2b51006..5422ba007 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png index c17a7d5bf..e593a85b5 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png index 03cb8bc7b..64aa676b7 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png index 7ff594ae9..ae74f98ba 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png index 595a45d57..64aa676b7 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png index 9998fd6fe..785e9e508 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png index 3aa05ea25..54a5726ce 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png index e8873247a..785e9e508 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png index e26985e7c..0e1bdc8e7 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png index a99507cfc..e3527a3a5 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png index 35999b3ae..0e1bdc8e7 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index de778ab63..6dcb21619 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico index 9da4305b2..f3350d6d7 100644 Binary files a/src-tauri/icons/icon.ico and b/src-tauri/icons/icon.ico differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index 78e13f41d..cf14b17a7 100644 Binary files a/src-tauri/icons/icon.png and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@1x.png b/src-tauri/icons/ios/AppIcon-20x20@1x.png index 7ffc8a164..081427459 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@1x.png and b/src-tauri/icons/ios/AppIcon-20x20@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png index fdbd9c8a6..38168805a 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png and b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x.png b/src-tauri/icons/ios/AppIcon-20x20@2x.png index fdbd9c8a6..38168805a 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x.png and b/src-tauri/icons/ios/AppIcon-20x20@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@3x.png b/src-tauri/icons/ios/AppIcon-20x20@3x.png index 5658ed441..f85259367 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@3x.png and b/src-tauri/icons/ios/AppIcon-20x20@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@1x.png b/src-tauri/icons/ios/AppIcon-29x29@1x.png index 72dbdadd5..861f6079d 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@1x.png and b/src-tauri/icons/ios/AppIcon-29x29@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png index ef513fed6..d4310dd0d 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png and b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x.png b/src-tauri/icons/ios/AppIcon-29x29@2x.png index ef513fed6..d4310dd0d 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x.png and b/src-tauri/icons/ios/AppIcon-29x29@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@3x.png b/src-tauri/icons/ios/AppIcon-29x29@3x.png index fb7dffec3..e10149d64 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@3x.png and b/src-tauri/icons/ios/AppIcon-29x29@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@1x.png b/src-tauri/icons/ios/AppIcon-40x40@1x.png index fdbd9c8a6..38168805a 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@1x.png and b/src-tauri/icons/ios/AppIcon-40x40@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png index 3f3c591d5..a1332e36b 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png and b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x.png b/src-tauri/icons/ios/AppIcon-40x40@2x.png index 3f3c591d5..a1332e36b 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x.png and b/src-tauri/icons/ios/AppIcon-40x40@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@3x.png b/src-tauri/icons/ios/AppIcon-40x40@3x.png index 5c7258726..780605a51 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@3x.png and b/src-tauri/icons/ios/AppIcon-40x40@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-512@2x.png b/src-tauri/icons/ios/AppIcon-512@2x.png index a55baed1f..044e5d72e 100644 Binary files a/src-tauri/icons/ios/AppIcon-512@2x.png and b/src-tauri/icons/ios/AppIcon-512@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@2x.png b/src-tauri/icons/ios/AppIcon-60x60@2x.png index 5c7258726..780605a51 100644 Binary files a/src-tauri/icons/ios/AppIcon-60x60@2x.png and b/src-tauri/icons/ios/AppIcon-60x60@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@3x.png b/src-tauri/icons/ios/AppIcon-60x60@3x.png index 690b1e782..022defd24 100644 Binary files a/src-tauri/icons/ios/AppIcon-60x60@3x.png and b/src-tauri/icons/ios/AppIcon-60x60@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@1x.png b/src-tauri/icons/ios/AppIcon-76x76@1x.png index 7cf6aa0aa..b18b2d7bc 100644 Binary files a/src-tauri/icons/ios/AppIcon-76x76@1x.png and b/src-tauri/icons/ios/AppIcon-76x76@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@2x.png b/src-tauri/icons/ios/AppIcon-76x76@2x.png index 54aeeecd5..15be3489d 100644 Binary files a/src-tauri/icons/ios/AppIcon-76x76@2x.png and b/src-tauri/icons/ios/AppIcon-76x76@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png index 2d7686a0b..fa51def78 100644 Binary files a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png and b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png differ diff --git a/src-tauri/src/commands/aster_agent_cmd.rs b/src-tauri/src/commands/aster_agent_cmd.rs index 0d45e27b2..48b1c3692 100644 --- a/src-tauri/src/commands/aster_agent_cmd.rs +++ b/src-tauri/src/commands/aster_agent_cmd.rs @@ -2188,11 +2188,12 @@ impl WorkspaceSandboxedBashTool { config } + #[cfg(not(target_os = "windows"))] fn quote_shell(value: &str) -> String { format!("'{}'", value.replace('\'', "'\"'\"'")) } - fn build_shell_command(&self, command: &str, context: &ToolContext) -> (String, Vec) { + fn build_shell_command(&self, command: &str, _context: &ToolContext) -> (String, Vec) { #[cfg(target_os = "windows")] { return ( @@ -2208,7 +2209,7 @@ impl WorkspaceSandboxedBashTool { #[cfg(not(target_os = "windows"))] { - let working_dir = context.working_directory.to_string_lossy().to_string(); + let working_dir = _context.working_directory.to_string_lossy().to_string(); let wrapped_command = format!("cd {} && {}", Self::quote_shell(&working_dir), command); ("sh".to_string(), vec!["-lc".to_string(), wrapped_command]) } diff --git a/src-tauri/src/commands/skill_cmd.rs b/src-tauri/src/commands/skill_cmd.rs index 9f8fe3c28..031343f17 100644 --- a/src-tauri/src/commands/skill_cmd.rs +++ b/src-tauri/src/commands/skill_cmd.rs @@ -494,6 +494,7 @@ fn get_skill_key(app_type: &AppType, directory: &str) -> String { } /// 解析指定应用的技能列表(供 dispatcher 等非 Tauri command 场景调用) +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn resolve_skills_for_app( db: &DbConnection, skill_service: &Arc, diff --git a/src-tauri/src/commands/webview_cmd.rs b/src-tauri/src/commands/webview_cmd.rs index ef58f9d10..90fa60710 100644 --- a/src-tauri/src/commands/webview_cmd.rs +++ b/src-tauri/src/commands/webview_cmd.rs @@ -936,6 +936,7 @@ pub async fn open_chrome_profile_window( .await } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn open_chrome_profile_window_global( app: AppHandle, app_state: AppState, @@ -1049,6 +1050,7 @@ async fn ensure_managed_chrome_profile_with_manager( Ok(session) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn ensure_managed_chrome_profile_global( profile_key: String, url: Option, @@ -1064,6 +1066,7 @@ pub async fn get_chrome_profile_sessions( Ok(list_alive_profile_sessions(state.0.clone()).await) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn get_chrome_profile_sessions_global() -> Result, String> { Ok(list_alive_profile_sessions(shared_chrome_profile_manager()).await) } @@ -1076,6 +1079,7 @@ pub async fn close_chrome_profile_session( close_chrome_profile_session_with_manager(state.0.clone(), profile_key).await } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn close_chrome_profile_session_global(profile_key: String) -> Result { close_chrome_profile_session_with_manager(shared_chrome_profile_manager(), profile_key).await } @@ -1128,6 +1132,7 @@ pub async fn get_chrome_bridge_endpoint_info( get_chrome_bridge_endpoint_info_with_state(app_state.inner().clone()).await } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn get_chrome_bridge_endpoint_info_global( app_state: AppState, ) -> Result { @@ -1161,6 +1166,7 @@ pub async fn get_chrome_bridge_status() -> Result Result { get_chrome_bridge_status().await } @@ -1181,6 +1187,7 @@ pub async fn get_browser_backend_policy() -> Result Result { get_browser_backend_policy().await } @@ -1198,6 +1205,7 @@ pub async fn set_browser_backend_policy( Ok(normalized) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn set_browser_backend_policy_global( policy: BrowserBackendPolicy, ) -> Result { @@ -1274,6 +1282,7 @@ pub async fn get_browser_backends_status( }) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn get_browser_backends_status_global() -> Result { let policy = BROWSER_BACKEND_POLICY.read().await.clone(); let bridge_status = chrome_bridge::chrome_bridge_hub() @@ -1351,6 +1360,7 @@ pub async fn list_cdp_targets( .await } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn list_cdp_targets_global( request: ListCdpTargetsRequest, ) -> Result, String> { @@ -1379,6 +1389,7 @@ pub async fn open_cdp_session( .await } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn open_cdp_session_global( request: OpenCdpSessionRequest, ) -> Result { @@ -1407,6 +1418,7 @@ pub async fn close_cdp_session(request: BrowserSessionStateRequest) -> Result Result { close_cdp_session(request).await } @@ -1425,6 +1437,7 @@ pub async fn start_browser_stream( Ok(state) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn start_browser_stream_global( app: AppHandle, request: StartBrowserStreamRequest, @@ -1443,6 +1456,7 @@ pub async fn stop_browser_stream( Ok(state) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn stop_browser_stream_global( request: StopBrowserStreamRequest, ) -> Result { @@ -1461,6 +1475,7 @@ pub async fn get_browser_session_state( Ok(state) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn get_browser_session_state_global( db: DbConnection, request: BrowserSessionStateRequest, @@ -1484,6 +1499,7 @@ pub async fn take_over_browser_session( Ok(state) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn take_over_browser_session_global( db: DbConnection, request: UpdateBrowserSessionControlRequest, @@ -1507,6 +1523,7 @@ pub async fn release_browser_session( Ok(state) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn release_browser_session_global( db: DbConnection, request: UpdateBrowserSessionControlRequest, @@ -1530,6 +1547,7 @@ pub async fn resume_browser_session( Ok(state) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn resume_browser_session_global( db: DbConnection, request: UpdateBrowserSessionControlRequest, @@ -1551,6 +1569,7 @@ pub async fn get_browser_event_buffer( Ok(EventBufferSnapshotResponse::from(snapshot)) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn get_browser_event_buffer_global( request: BrowserEventBufferRequest, ) -> Result { @@ -1597,6 +1616,7 @@ pub async fn get_browser_action_audit_logs( Ok(result) } +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn get_browser_action_audit_logs_global( limit: Option, ) -> Result, String> { @@ -1726,6 +1746,7 @@ pub async fn browser_execute_action_with_manager( } /// 使用全局 profile manager 执行动作(供 Agent 工具复用) +#[cfg_attr(any(test, not(debug_assertions)), allow(dead_code))] pub async fn browser_execute_action_global( request: BrowserActionRequest, ) -> Result { diff --git a/src-tauri/src/services/openclaw_service.rs b/src-tauri/src/services/openclaw_service.rs index 57452cfea..4db9f1173 100644 --- a/src-tauri/src/services/openclaw_service.rs +++ b/src-tauri/src/services/openclaw_service.rs @@ -22,8 +22,6 @@ use serde_json::{json, Map, Value}; use std::cmp::Ordering; use std::collections::{HashSet, VecDeque}; use std::ffi::OsString; -#[cfg(target_os = "windows")] -use std::os::windows::process::CommandExt; use std::path::{Path, PathBuf}; use std::process::Stdio; use std::sync::{Arc, Mutex as StdMutex, OnceLock}; @@ -55,6 +53,7 @@ const NPM_MIRROR_CN: &str = "https://registry.npmmirror.com"; const NODE_MIN_VERSION: (u64, u64, u64) = (22, 12, 0); const OPENCLAW_PROGRESS_LOG_LIMIT: usize = 400; const OPENCLAW_INSTALLER_USER_AGENT: &str = "Lime-OpenClaw"; +#[cfg(not(target_os = "windows"))] const OPENCLAW_TEMP_CARGO_CHECK_DIR: &str = "/tmp/lime-cargo-check"; #[cfg(target_os = "windows")] const CREATE_NO_WINDOW: u32 = 0x08000000; @@ -546,7 +545,10 @@ impl OpenClawService { return Ok(result); } - self.ensure_dependency_ready(app, dependency).await + #[cfg(not(target_os = "windows"))] + { + self.ensure_dependency_ready(app, dependency).await + } } pub async fn cleanup_temp_artifacts( @@ -2772,6 +2774,7 @@ async fn trigger_macos_command_line_tools_install() -> Result { } #[cfg(not(target_os = "macos"))] +#[allow(dead_code)] async fn trigger_macos_command_line_tools_install() -> Result { Err("当前平台不支持拉起 macOS 开发者工具安装器。".to_string()) } @@ -3066,6 +3069,7 @@ async fn terminate_sysinfo_processes(system: &mut System, target_pids: &[Pid]) { } } +#[cfg_attr(target_os = "windows", allow(dead_code))] fn parse_lsof_listener_pids(output: &str) -> Vec { let mut pids = output .lines() @@ -3858,6 +3862,7 @@ fn shell_command_escape_for(platform: ShellPlatform, value: &str) -> String { core_shell_command_escape_for(platform, value) } +#[cfg_attr(target_os = "windows", allow(dead_code))] fn shell_command_escape(value: &str) -> String { shell_command_escape_for(current_shell_platform(), value) } @@ -3871,6 +3876,7 @@ fn shell_path_assignment_for(platform: ShellPlatform, binary_path: &str) -> Stri core_shell_path_assignment_for(platform, binary_path) } +#[cfg_attr(target_os = "windows", allow(dead_code))] fn shell_path_assignment(binary_path: &str) -> String { shell_path_assignment_for(current_shell_platform(), binary_path) } @@ -4828,6 +4834,7 @@ async fn read_binary_semver(path: &Path) -> Option<(u64, u64, u64)> { parse_semver(stdout.trim()).or_else(|| parse_semver(stderr.trim())) } +#[cfg_attr(not(test), allow(dead_code))] fn select_best_semver_candidate( candidates: Vec<(PathBuf, Option<(u64, u64, u64)>)>, ) -> Option { @@ -5912,10 +5919,6 @@ mod tests { /// 从 Windows 注册表读取最新的 PATH 环境变量并刷新当前进程 #[cfg(target_os = "windows")] fn refresh_windows_path_from_registry() -> Result<(), String> { - use std::ffi::OsStr; - use std::os::windows::ffi::OsStrExt; - use std::ptr; - unsafe { let mut combined_path = String::new(); diff --git a/src/components/SplashScreen.tsx b/src/components/SplashScreen.tsx index 51d09933b..ac5676eae 100644 --- a/src/components/SplashScreen.tsx +++ b/src/components/SplashScreen.tsx @@ -1,7 +1,7 @@ /** * 启动画面组件 * - * 应用启动时显示 Logo 动画,然后淡出进入主界面 + * 应用启动时显示专用 Logo、Slogan 与进度动画,然后淡出进入主界面。 */ import { useEffect, useState } from "react"; @@ -14,28 +14,28 @@ const sceneEnter = keyframes` const sceneExit = keyframes` from { opacity: 1; transform: scale(1); } - to { opacity: 0; transform: scale(1.015); } + to { opacity: 0; transform: scale(1.02); } `; -const panelFloat = keyframes` - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-4px); } -`; - -const pulse = keyframes` - 0%, 100% { opacity: 0.56; } - 50% { opacity: 1; } -`; - -const progress = keyframes` - 0% { transform: translateX(-42%) scaleX(0.72); opacity: 0.55; } - 50% { transform: translateX(12%) scaleX(1); opacity: 1; } - 100% { transform: translateX(78%) scaleX(0.82); opacity: 0.55; } -`; - -const orbShift = keyframes` +const orbFloat = keyframes` 0%, 100% { transform: translate3d(0, 0, 0) scale(1); } - 50% { transform: translate3d(10px, -12px, 0) scale(1.06); } + 50% { transform: translate3d(0, -16px, 0) scale(1.06); } +`; + +const logoFloat = keyframes` + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-8px); } +`; + +const progressShift = keyframes` + 0% { transform: translateX(-38%) scaleX(0.78); opacity: 0.56; } + 50% { transform: translateX(10%) scaleX(1); opacity: 1; } + 100% { transform: translateX(76%) scaleX(0.82); opacity: 0.56; } +`; + +const glowPulse = keyframes` + 0%, 100% { opacity: 0.58; transform: scale(0.96); } + 50% { opacity: 1; transform: scale(1.04); } `; const Container = styled.div<{ $isExiting: boolean }>` @@ -46,13 +46,13 @@ const Container = styled.div<{ $isExiting: boolean }>` justify-content: center; overflow: hidden; background: - radial-gradient(circle at 16% 18%, rgba(56, 189, 248, 0.12), transparent 32%), - radial-gradient(circle at 84% 12%, rgba(16, 185, 129, 0.1), transparent 30%), - radial-gradient(circle at 72% 82%, rgba(245, 158, 11, 0.08), transparent 26%), + radial-gradient(circle at 20% 18%, rgba(132, 204, 22, 0.18), transparent 30%), + radial-gradient(circle at 78% 12%, rgba(250, 204, 21, 0.14), transparent 28%), + radial-gradient(circle at 50% 84%, rgba(34, 197, 94, 0.1), transparent 28%), linear-gradient( - 135deg, + 180deg, hsl(var(--background)) 0%, - hsl(var(--muted) / 0.84) 48%, + hsl(var(--muted) / 0.72) 48%, hsl(var(--background)) 100% ); z-index: 9999; @@ -78,9 +78,8 @@ const AmbientOrb = styled.div<{ left: ${({ $left }) => $left ?? "auto"}; border-radius: 999px; background: ${({ $color }) => $color}; - filter: blur(26px); - opacity: 0.8; - animation: ${orbShift} 11s ease-in-out infinite; + filter: blur(40px); + animation: ${orbFloat} 10s ease-in-out infinite; animation-delay: ${({ $delay }) => $delay ?? "0s"}; pointer-events: none; `; @@ -88,214 +87,90 @@ const AmbientOrb = styled.div<{ const Stage = styled.div` position: relative; z-index: 1; - width: min(560px, calc(100vw - 32px)); -`; - -const Panel = styled.div` - position: relative; - overflow: hidden; - border: 1px solid hsl(var(--border) / 0.78); - border-radius: 32px; - padding: 32px; - background: - linear-gradient( - 180deg, - hsl(var(--card) / 0.94) 0%, - hsl(var(--card) / 0.84) 100% - ); - backdrop-filter: blur(18px); - box-shadow: - 0 26px 80px rgba(15, 23, 42, 0.08), - inset 0 1px 0 rgba(255, 255, 255, 0.36); - animation: ${panelFloat} 5.5s ease-in-out infinite; - - @media (max-width: 640px) { - padding: 24px 20px; - border-radius: 28px; - } -`; - -const PanelGlow = styled.div` - position: absolute; - inset: auto -120px -120px auto; - width: 240px; - height: 240px; - border-radius: 999px; - background: radial-gradient(circle, rgba(56, 189, 248, 0.12), transparent 66%); - pointer-events: none; -`; - -const HeaderPill = styled.div` - display: inline-flex; - align-items: center; - border-radius: 999px; - border: 1px solid hsl(var(--border) / 0.72); - background: hsl(var(--card) / 0.92); - padding: 6px 12px; - font-size: 11px; - font-weight: 700; - letter-spacing: 0.18em; - color: hsl(var(--muted-foreground)); - box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04); -`; - -const Hero = styled.div` - position: relative; + width: min(720px, calc(100vw - 40px)); display: flex; + flex-direction: column; align-items: center; - gap: 20px; - margin-top: 18px; - - @media (max-width: 640px) { - flex-direction: column; - align-items: flex-start; - } + justify-content: center; + text-align: center; `; -const LogoWrap = styled.div` +const LogoStack = styled.div` + position: relative; display: flex; align-items: center; justify-content: center; - width: 108px; - height: 108px; - border-radius: 28px; - border: 1px solid hsl(var(--border) / 0.75); - background: - linear-gradient( - 180deg, - hsl(var(--card)) 0%, - hsl(var(--muted) / 0.74) 100% - ); - box-shadow: - 0 18px 34px rgba(15, 23, 42, 0.08), - inset 0 1px 0 rgba(255, 255, 255, 0.42); + width: min(360px, 78vw); + height: min(360px, 78vw); +`; - @media (max-width: 640px) { - width: 96px; - height: 96px; - border-radius: 24px; - } +const LogoGlow = styled.div` + position: absolute; + inset: 12% 12% 16%; + border-radius: 999px; + background: + radial-gradient(circle, rgba(163, 230, 53, 0.34) 0%, rgba(163, 230, 53, 0.12) 44%, transparent 72%); + filter: blur(24px); + animation: ${glowPulse} 2.8s ease-in-out infinite; `; const Logo = styled.img` - width: 72px; - height: 72px; + position: relative; + width: clamp(240px, 34vw, 320px); + height: clamp(240px, 34vw, 320px); object-fit: contain; - filter: drop-shadow(0 16px 28px rgba(15, 23, 42, 0.16)); + animation: ${logoFloat} 4.2s ease-in-out infinite; + filter: drop-shadow(0 28px 44px rgba(15, 23, 42, 0.16)); @media (max-width: 640px) { - width: 64px; - height: 64px; + width: min(260px, 72vw); + height: min(260px, 72vw); } `; -const CopyBlock = styled.div` - flex: 1; - min-width: 0; -`; - -const AppName = styled.h1` - margin: 0; - font-size: 38px; +const Slogan = styled.p` + margin: 22px 0 0; + max-width: 18em; + font-size: clamp(28px, 4vw, 38px); + line-height: 1.16; font-weight: 700; - letter-spacing: -0.03em; + letter-spacing: -0.04em; color: hsl(var(--foreground)); - - @media (max-width: 640px) { - font-size: 32px; - } -`; - -const Subtitle = styled.p` - margin: 10px 0 0; - font-size: 14px; - line-height: 1.7; - color: hsl(var(--muted-foreground)); -`; - -const MetaRow = styled.div` - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-top: 24px; -`; - -const MetaPill = styled.div` - display: inline-flex; - align-items: center; - gap: 8px; - border-radius: 999px; - border: 1px solid hsl(var(--border) / 0.72); - background: hsl(var(--card) / 0.88); - padding: 8px 12px; - font-size: 12px; - font-weight: 500; - color: hsl(var(--muted-foreground)); -`; - -const Dot = styled.span` - width: 6px; - height: 6px; - border-radius: 999px; - background: rgba(14, 165, 233, 0.85); - animation: ${pulse} 1.5s ease-in-out infinite; -`; - -const LoadingArea = styled.div` - margin-top: 26px; - padding-top: 22px; - border-top: 1px solid hsl(var(--border) / 0.7); + text-wrap: balance; + text-shadow: 0 10px 30px rgba(15, 23, 42, 0.08); `; const ProgressTrack = styled.div` position: relative; overflow: hidden; - width: 100%; - height: 6px; + margin-top: 28px; + width: min(320px, 72vw); + height: 8px; border-radius: 999px; - background: hsl(var(--muted) / 0.92); + background: + linear-gradient( + 90deg, + hsl(var(--muted) / 0.82) 0%, + hsl(var(--muted) / 0.96) 100% + ); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.32), + 0 12px 28px rgba(15, 23, 42, 0.08); `; const ProgressBar = styled.div` position: absolute; inset: 0 auto 0 0; - width: 46%; + width: 44%; border-radius: inherit; background: linear-gradient( 90deg, - rgba(56, 189, 248, 0.82) 0%, - rgba(16, 185, 129, 0.72) 100% + rgba(132, 204, 22, 0.96) 0%, + rgba(250, 204, 21, 0.9) 100% ); - animation: ${progress} 1.8s ease-in-out infinite; -`; - -const LoadingRow = styled.div` - display: flex; - align-items: baseline; - justify-content: space-between; - gap: 12px; - margin-top: 14px; - - @media (max-width: 640px) { - flex-direction: column; - align-items: flex-start; - } -`; - -const LoadingText = styled.p` - margin: 0; - font-size: 14px; - font-weight: 600; - color: hsl(var(--foreground)); -`; - -const LoadingHint = styled.p` - margin: 0; - font-size: 12px; - line-height: 1.6; - color: hsl(var(--muted-foreground)); - animation: ${pulse} 1.8s ease-in-out infinite; + box-shadow: 0 0 24px rgba(163, 230, 53, 0.35); + animation: ${progressShift} 1.6s ease-in-out infinite; `; interface SplashScreenProps { @@ -327,70 +202,35 @@ export function SplashScreen({ return ( - - - CREATIVE WORKBENCH - - - - - - - - Lime - - 正在准备创作工作台与本地运行状态,保持当前节奏,不打断你的上下文。 - - - - - - - - 本地优先 - - - - 创作工作台 - - - - 启动中 - - - - - - - - - - 正在加载... - 首次启动或更新后进入时间可能稍长 - - - + + + + + 青柠一下,灵感即来。 + + + );