diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 20546ea..9edaeca 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,9 +27,8 @@ jobs: body: | ## 下载 - ### Windows (x86_64) — 推荐 - - `gitsave-gui-windows-x86_64.msi` — **图形安装包**(推荐,双击安装即可) - - `gitsave-gui-windows-x86_64.exe` — GUI 便携版(无需安装,直接运行) + ### Windows (x86_64) + - `gitsave-gui-windows-x86_64.exe` — GUI 便携版(直接运行) - `gitsave-windows-x86_64.exe` — TUI/命令行版 ### Linux (x86_64) @@ -164,7 +163,7 @@ jobs: asset_name: gitsave-windows-x86_64.exe asset_content_type: application/octet-stream - # 构建 Windows GUI 版本 (native MSVC runner) + MSI 安装包 + # 构建 Windows GUI 版本 (native MSVC runner) - 仅便携版 build-windows-gui: needs: create-release runs-on: windows-latest @@ -189,31 +188,6 @@ jobs: asset_name: gitsave-gui-windows-x86_64.exe asset_content_type: application/octet-stream - - name: Add WiX Toolset v3 to PATH - run: echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: Install cargo-wix - run: cargo install cargo-wix --version "0.3.9" --locked - - - name: Build MSI installer - run: | - $version = (Select-String -Path Cargo.toml -Pattern '^version = "(.+)"').Matches[0].Groups[1].Value - cargo wix --no-build --nocapture -dVersion=$version - # Rename to a stable filename independent of the version number - $msi = Get-ChildItem -Path target\wix -Filter "gitsave-*.msi" | Select-Object -First 1 - if (-not $msi) { throw "MSI not found in target\wix" } - Move-Item $msi.FullName "target\wix\gitsave-gui-windows-x86_64.msi" - - - name: Upload Windows MSI installer - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: ./target/wix/gitsave-gui-windows-x86_64.msi - asset_name: gitsave-gui-windows-x86_64.msi - asset_content_type: application/octet-stream - # 构建 macOS TUI 版本 (x86_64) build-macos: needs: create-release diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 1224a7c..97704ad 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -139,7 +139,6 @@ enum Modal { enum ConfirmAction { SwitchRoute { name: String }, DiscardChanges, - DeleteRoute { name: String }, } #[derive(Debug, Clone)] @@ -210,7 +209,6 @@ enum Message { // Main – misc BeginDiscard, BeginAmend, - BeginDeleteRoute, ToggleRecovery, // Modal ModalInput(String), @@ -547,27 +545,6 @@ impl GitsaveApp { Task::none() } - Message::BeginDeleteRoute => { - if let Screen::Main(s) = &mut self.screen { - if let Some(r) = s.selected_route() { - if r.is_current { - s.notify_err("Cannot delete the current route"); - } else { - let name = r.name.clone(); - s.modal = Some(Modal::Confirm { - prompt: format!( - "Delete route '{name}'?\n\ - All saves on this route will be permanently removed.\n\ - This cannot be undone." - ), - action: ConfirmAction::DeleteRoute { name }, - }); - } - } - } - Task::none() - } - Message::ToggleRecovery => { if let Screen::Main(s) = &mut self.screen { s.is_recovery = !s.is_recovery; @@ -704,19 +681,6 @@ impl GitsaveApp { Message::ActionDone, ) } - ConfirmAction::DeleteRoute { name } => { - let dir = match &mut self.screen { - Screen::Main(s) => { - s.busy = true; - s.dir.clone() - } - _ => return Task::none(), - }; - Task::perform( - async move { delete_route(dir, name) }, - Message::ActionDone, - ) - } }, Modal::TextInput { value, action, .. } => { let name = value.trim().to_string(); @@ -978,13 +942,13 @@ fn view_header(s: &MainState) -> Element { .unwrap_or("—"); let recovery_badge: Element = if s.is_recovery { - text(" ⚕ RECOVERY MODE ").size(12).color(C_RECOVERY).into() + text(" [RECOVERY MODE] ").size(12).color(C_RECOVERY).into() } else { horizontal_space().width(0).into() }; let busy_badge: Element = if s.busy { - text(" ⟳ ").size(12).color(C_DIM).into() + text(" ... ").size(12).color(C_DIM).into() } else { horizontal_space().width(0).into() }; @@ -996,12 +960,12 @@ fn view_header(s: &MainState) -> Element { recovery_badge, busy_badge, horizontal_space(), - button(text("⟳").size(14).color(C_DIM)) + button(text("~").size(14).color(C_DIM)) .on_press(Message::Refresh) .style(style_btn_ghost) .padding([4, 8]), horizontal_space().width(4), - button(text("← Back").size(12).color(C_DIM)) + button(text("< Back").size(12).color(C_DIM)) .on_press(Message::BackToPicker) .style(style_btn_ghost) .padding([4, 10]), @@ -1075,7 +1039,7 @@ fn view_routes_panel(s: &MainState) -> Element { && !s.busy; let switch_btn = { - let b = button(text("→ Switch to").size(12)) + let b = button(text("> Switch to").size(12)) .style(style_btn_secondary) .padding([5, 10]) .width(Length::Fill); @@ -1087,7 +1051,7 @@ fn view_routes_panel(s: &MainState) -> Element { }; let rename_btn = { - let b = button(text("✎ Rename").size(12)) + let b = button(text("Rename").size(12)) .style(style_btn_secondary) .padding([5, 10]) .width(Length::Fill); @@ -1098,27 +1062,8 @@ fn view_routes_panel(s: &MainState) -> Element { } }; - let can_delete = s - .routes - .get(s.sel_route) - .map(|r| !r.is_current && !is_recovery_branch_name(&r.name)) - .unwrap_or(false) - && !s.busy; - - let delete_btn = { - let b = button(text("✕ Delete Route").size(12).color(C_ERROR)) - .style(style_btn_ghost) - .padding([5, 10]) - .width(Length::Fill); - if can_delete { - b.on_press(Message::BeginDeleteRoute) - } else { - b - } - }; - let recovery_label = - if s.is_recovery { "✕ Exit Recovery" } else { "⚕ Recovery Mode" }; + if s.is_recovery { "Exit Recovery" } else { "Recovery Mode" }; let recovery_color = if s.is_recovery { C_WARN } else { C_DIM }; container( @@ -1144,8 +1089,6 @@ fn view_routes_panel(s: &MainState) -> Element { switch_btn, vertical_space().height(2), rename_btn, - vertical_space().height(2), - delete_btn, vertical_space().height(8), button(text(recovery_label).size(12).color(recovery_color)) .on_press(Message::ToggleRecovery) @@ -1239,14 +1182,14 @@ fn view_save_bar(s: &MainState) -> Element { }; let save_btn = { - let b = button(text("💾 Save").size(13)) + let b = button(text("Save").size(13)) .style(style_btn_primary) .padding([7, 14]); if s.busy { b } else { b.on_press(Message::TrySave) } }; let force_btn = { - let b = button(text("⚡ Force Save").size(13)) + let b = button(text("Force Save").size(13)) .style(style_btn_secondary) .padding([7, 14]); if s.busy { b } else { b.on_press(Message::ForceSave) } @@ -1254,7 +1197,7 @@ fn view_save_bar(s: &MainState) -> Element { let rollback_btn = { let enabled = !s.history.is_empty() && !s.busy; - let b = button(text("↩ Rollback").size(13)) + let b = button(text("Rollback").size(13)) .style(if enabled { style_btn_secondary } else { style_btn_disabled }) .padding([7, 14]); if enabled { b.on_press(Message::BeginRollback) } else { b } @@ -1263,7 +1206,7 @@ fn view_save_bar(s: &MainState) -> Element { let discard_btn = { let enabled = s.is_dirty() && !s.busy; let label_color = if enabled { C_ERROR } else { C_DIM }; - let b = button(text("✕ Discard").size(13).color(label_color)) + let b = button(text("Discard").size(13).color(label_color)) .style(style_btn_ghost) .padding([7, 14]); if enabled { b.on_press(Message::BeginDiscard) } else { b } @@ -1271,7 +1214,7 @@ fn view_save_bar(s: &MainState) -> Element { let amend_btn = { let enabled = !s.history.is_empty() && !s.busy; - let b = button(text("✎ Amend").size(13).color(C_DIM)) + let b = button(text("Amend").size(13).color(C_DIM)) .style(style_btn_ghost) .padding([7, 14]); if enabled { b.on_press(Message::BeginAmend) } else { b } @@ -1316,7 +1259,7 @@ fn view_status_bar(s: &MainState) -> Element { let content: Element = match &s.status { None => text("Loading status…").size(12).color(C_DIM).into(), Some(status) if !status.has_uncommitted_changes => { - text("✓ Working directory clean").size(12).color(C_SUCCESS).into() + text("Working directory clean").size(12).color(C_SUCCESS).into() } Some(status) => { let n = status.pending_changes.len(); @@ -1344,7 +1287,7 @@ fn view_status_bar(s: &MainState) -> Element { }; column![ - text(format!("⚠ {n} uncommitted change(s)")) + text(format!("! {n} uncommitted change(s)")) .size(12) .color(C_WARN), column(file_rows).spacing(2), @@ -1649,11 +1592,6 @@ fn discard_changes(dir: PathBuf) -> Result<(), String> { SaveManager::new(core).discard_changes().map_err(|e| e.to_string()) } -fn delete_route(dir: PathBuf, name: String) -> Result<(), String> { - let core = Git2Core::open(&dir).map_err(|e| e.to_string())?; - RouteManager::new(core).delete_route(&name).map_err(|e| e.to_string()) -} - fn amend_message(dir: PathBuf, message: String) -> Result<(), String> { let core = Git2Core::open(&dir).map_err(|e| e.to_string())?; SaveManager::new(core)