From 50fabf243e5988ff08e9143ebbc4b44f62fabc2d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 10 Oct 2026 06:46:02 +0000 Subject: [PATCH] ui: sidebar-only nav, titlebar settings, desktop shortcut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove TitleBar tabs; open Settings from a titlebar gear button. Ship WiX MSI with Start Menu + Desktop shortcuts and product icon, without adding the install dir to PATH. Rebased onto main after PR #1 squash-merge to clear conflicts. Co-authored-by: 绿岸公式 --- .github/workflows/windows-msi.yml | 12 +-- Cargo.toml | 2 + README.md | 15 ++-- src/app.rs | 62 ++++++--------- src/i18n.rs | 3 - wix/Product.ico | Bin 0 -> 15086 bytes wix/main.wxs | 122 ++++++++++++++++++++++++++++++ 7 files changed, 158 insertions(+), 58 deletions(-) create mode 100644 wix/Product.ico create mode 100644 wix/main.wxs diff --git a/.github/workflows/windows-msi.yml b/.github/workflows/windows-msi.yml index 71a93bb..df3b0b0 100644 --- a/.github/workflows/windows-msi.yml +++ b/.github/workflows/windows-msi.yml @@ -70,16 +70,16 @@ jobs: shell: pwsh run: cargo install cargo-wix --locked - - name: Init WiX project if missing + - name: Build MSI shell: pwsh run: | if (-not (Test-Path "wix\main.wxs")) { - cargo wix init --force + throw "Missing wix\main.wxs (desktop shortcuts + product icon must be committed)" } - - - name: Build MSI - shell: pwsh - run: cargo wix --nocapture + if (-not (Test-Path "wix\Product.ico")) { + throw "Missing wix\Product.ico" + } + cargo wix --nocapture - name: Upload MSI artifact uses: actions/upload-artifact@v4 diff --git a/Cargo.toml b/Cargo.toml index d9c01f3..42bee0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,8 @@ product-name = "WSLc Desktop" manufacturer = "WSLc Desktop" license = false eula = false +product-icon = "wix/Product.ico" +upgrade-guid = "31263ED9-28F7-4608-AF04-A8CAE4591EB0" [dependencies] anyhow = "1" diff --git a/README.md b/README.md index a997357..76000f4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - **Volumes**:列出 / 创建 / 删除命名卷 - **Run**:按镜像引用启动 detached 容器(可选名称) - **引擎状态**:LIVE(真实 CLI)或 DEMO(内存样例数据) -- **设置**:界面语言(中文 / English,默认跟随系统:中文系统用中文,否则英文)与主题(深色 / 浅色) +- **设置**:TitleBar 齿轮按钮打开;界面语言(中文 / English,默认跟随系统)与主题(深色 / 浅色) ## 环境要求 @@ -68,15 +68,11 @@ rustc -vV # 确认 host 含 windows-msvc cargo install cargo-wix ``` -### 2. 生成安装工程并打 MSI +### 2. 打 MSI(含桌面图标) -在仓库根目录: +仓库已提交 `wix/main.wxs` 与 `wix/Product.ico`:安装后会创建 **开始菜单** 与 **桌面快捷方式**,**不会** 写入 PATH(无需命令行启动)。 ```powershell -# 首次:根据 Cargo.toml 生成 wix\main.wxs(可按需改图标、快捷方式、安装目录) -cargo wix init - -# 构建 release 并打包 MSI cargo wix ``` @@ -134,15 +130,16 @@ git push origin v0.1.0 成功后可在对应 workflow run 的 **Artifacts** 下载 `wslc-desktop-msi`;打 tag 时还会出现在 **Releases**。 -工作流在 `windows-latest` 上安装 Rust MSVC、WiX Toolset、`cargo-wix`,必要时执行 `cargo wix init`,再 `cargo wix` 产出 `target\wix\*.msi`。 +工作流在 `windows-latest` 上安装 Rust MSVC、WiX Toolset、`cargo-wix`,再 `cargo wix` 产出带桌面快捷方式的 MSI。 ## 项目结构 ```text .github/workflows/ # GitHub Actions(Windows MSI) +wix/ # MSI:桌面/开始菜单快捷方式 + 产品图标 src/ main.rs # 窗口启动与快捷键 - app.rs # 侧栏 + 分区界面(含设置) + app.rs # 侧栏导航 + TitleBar 设置按钮 i18n.rs # 中英文字符串与系统语言检测 wslc.rs # wslc CLI 封装与 Demo 回退 ``` diff --git a/src/app.rs b/src/app.rs index a7ce74b..df00674 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,15 +2,14 @@ use std::sync::mpsc::{Receiver, TryRecvError}; use std::time::Duration; use gpui_kit::component::{ - ActiveTheme, Disableable as _, Icon, IconName, Sizable as _, StyledExt as _, Theme, ThemeMode, - TitleBar, + ActiveTheme, Disableable as _, Icon, IconName, Selectable as _, Sizable as _, StyledExt as _, + Theme, ThemeMode, TitleBar, button::{Button, ButtonVariants as _}, h_flex, input::{Input, InputState}, label::Label, progress::Progress, sidebar::{Sidebar, SidebarGroup, SidebarHeader, SidebarMenu, SidebarMenuItem}, - tab::{Tab, TabBar}, v_flex, }; use gpui_kit::prelude::FluentBuilder as _; @@ -35,17 +34,6 @@ pub enum Section { } impl Section { - fn from_index(index: usize) -> Self { - match index { - 0 => Self::Containers, - 1 => Self::Images, - 2 => Self::Volumes, - 3 => Self::Run, - 4 => Self::Settings, - _ => Self::Containers, - } - } - fn label(self, t: &Strings) -> &'static str { match self { Self::Containers => t.containers, @@ -552,17 +540,30 @@ impl AppView { ]), ), ) - .child( - SidebarGroup::new(t.preferences).child( - SidebarMenu::new().children([SidebarMenuItem::new(t.settings) + } + + fn render_title_bar(&self, cx: &mut Context) -> impl IntoElement { + let t = self.t(); + TitleBar::new().child( + h_flex() + .id("title-bar-content") + .w_full() + .h_full() + .items_center() + .justify_end() + .pr_2() + .child( + Button::new("titlebar-settings") + .ghost() .icon(IconName::Settings) - .active(self.section == Section::Settings) + .tooltip(t.settings) + .selected(self.section == Section::Settings) .on_click(cx.listener(|this, _, _, cx| { this.section = Section::Settings; cx.notify(); - }))]), + })), ), - ) + ) } fn render_toolbar(&self, cx: &mut Context) -> impl IntoElement { @@ -1496,9 +1497,6 @@ impl AppView { impl Render for AppView { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - let section_index = self.section as usize; - let t = self.t(); - h_flex() .size_full() .bg(cx.theme().background) @@ -1507,23 +1505,7 @@ impl Render for AppView { v_flex() .size_full() .min_w_0() - .child( - TitleBar::new().child( - TabBar::new("section-tabs") - .mt(px(1.)) - .segmented() - .selected_index(section_index) - .on_click(cx.listener(|this, ix: &usize, _, cx| { - this.section = Section::from_index(*ix); - cx.notify(); - })) - .child(Tab::new().label(t.containers)) - .child(Tab::new().label(t.images)) - .child(Tab::new().label(t.volumes)) - .child(Tab::new().label(t.run)) - .child(Tab::new().label(t.settings)), - ), - ) + .child(self.render_title_bar(cx)) .child( v_flex() .flex_1() diff --git a/src/i18n.rs b/src/i18n.rs index ba33721..2c89427 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -41,7 +41,6 @@ impl Locale { pub struct Strings { pub app_subtitle: &'static str, pub browse: &'static str, - pub preferences: &'static str, pub containers: &'static str, pub images: &'static str, pub volumes: &'static str, @@ -129,7 +128,6 @@ pub struct Strings { pub static EN: Strings = Strings { app_subtitle: "WSL Containers", browse: "Browse", - preferences: "Preferences", containers: "Containers", images: "Images", volumes: "Volumes", @@ -217,7 +215,6 @@ pub static EN: Strings = Strings { pub static ZH: Strings = Strings { app_subtitle: "WSL 容器", browse: "浏览", - preferences: "偏好", containers: "容器", images: "镜像", volumes: "卷", diff --git a/wix/Product.ico b/wix/Product.ico new file mode 100644 index 0000000000000000000000000000000000000000..59dc283e9b37e121c74029a59856f9dedc4f189c GIT binary patch literal 15086 zcmeI1J#thr5QIg+0i2L;096hh5fgC^LXN;`h&cfFGn!pK=o*jy-qW*pu~fAlX{LL+ zHMRTfTBr0Ty-jy_DaTX#_AaGQDW%ita{ig~KXUHj;m`SFN?+cmbe}P~lo^+N4k=~a zwXR>^?;m+R=EYv4=KVc9PO(;FfvfSsgN@ELzSn}Uo{r+HhWckuy`)ba&l+`K;-jNj z?MXf2M>y~r4cE($dY1UA!9LNtt%il@Q7sTbK=Gkw(zwuf0ied}1S3lD9IrHFi zoVV(8uUc=@(1oVPJ^J+5etwTXqOWh!=T4*gk%t-jQD3}KQ_nhsQT?b78rm0q%|+Z< z`rbpN73H?*>z&v~`qVUf+=zbUpWeQ&KPygaqx$smQN8KjPPoIeUA3u z)|f{Pv1W_OI^&iCyw%t zn7{h(@$50&!RMp%5&qF9M!KaO9AXJae))g;{%3YXX4Mnn5L=wt^GDaBX|q~BJQkkC z8uuvwXySu&Eqbg!N8FkI(X)saInK4{v79ZIct`m6TKMpJJ(n=0Jlt9S(XmKxA~nuY zEMdr7jCjlc<@w2+q8V9^71e9C7I(({(YF}+Yk7d*;zs>v`Y-A4^)keT3cPpMDlqr?mHYe=hOJNBHOTZ$4OlkH=bsYZ2TG z|McpKcrYxhhX=-Uw)&@!MSAzfncThpdp#>|kALgKvi)oJuQMIp+YCoJiif{v{@QPJ pkNzkRJp9+{pE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + + + + +