Skip to main content

par_term/
update_dialog.rs

1//! Update notification dialog overlay.
2//!
3//! Renders an egui modal window when a new version of par-term is available,
4//! showing version info, release notes, and install/skip/dismiss actions.
5
6use crate::update_checker::UpdateCheckResult;
7
8/// Action returned by the update dialog.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum UpdateDialogAction {
11    /// User dismissed the dialog.
12    Dismiss,
13    /// User wants to skip this version.
14    SkipVersion(String),
15    /// User wants to install the update.
16    InstallUpdate(String),
17    /// Dialog is still open, no action taken.
18    None,
19}
20
21/// Render the update dialog overlay.
22///
23/// Call this when `show_update_dialog` is true. Returns the user's action.
24///
25/// When `installing` is true, the Install button is disabled and shows "Installing...".
26/// The `install_status` message (if any) is displayed below the buttons.
27pub fn render(
28    ctx: &egui::Context,
29    update_result: &UpdateCheckResult,
30    current_version: &str,
31    installation_type: par_term_settings_ui::InstallationType,
32    installing: bool,
33    install_status: Option<&str>,
34) -> UpdateDialogAction {
35    let mut action = UpdateDialogAction::None;
36
37    // Only show dialog for UpdateAvailable
38    let info = match update_result {
39        UpdateCheckResult::UpdateAvailable(info) => info,
40        _ => return UpdateDialogAction::Dismiss,
41    };
42
43    let version_str = info.version.strip_prefix('v').unwrap_or(&info.version);
44
45    egui::Window::new("Update Available")
46        .collapsible(false)
47        .resizable(true)
48        .default_width(450.0)
49        .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0])
50        .show(ctx, |ui| {
51            ui.vertical(|ui| {
52                // Version info
53                ui.heading(format!("par-term v{} is available!", version_str));
54                ui.add_space(4.0);
55                ui.label(format!("You are currently running v{}", current_version));
56                ui.add_space(12.0);
57
58                // Release notes
59                if let Some(ref notes) = info.release_notes
60                    && !notes.is_empty()
61                {
62                    ui.label(egui::RichText::new("Release Notes").strong());
63                    ui.add_space(4.0);
64                    egui::ScrollArea::vertical()
65                        .max_height(200.0)
66                        .show(ui, |ui| {
67                            ui.label(notes);
68                        });
69                    ui.add_space(8.0);
70                }
71
72                // Release URL link
73                ui.hyperlink_to("View release on GitHub", &info.release_url);
74                ui.add_space(12.0);
75
76                // Installation-specific UI
77                match installation_type {
78                    par_term_settings_ui::InstallationType::Homebrew => {
79                        ui.label(
80                            egui::RichText::new("Update via Homebrew:").color(egui::Color32::GRAY),
81                        );
82                        ui.code("brew upgrade --cask par-term");
83                        ui.add_space(8.0);
84                    }
85                    par_term_settings_ui::InstallationType::CargoInstall => {
86                        ui.label(
87                            egui::RichText::new("Update via Cargo:").color(egui::Color32::GRAY),
88                        );
89                        ui.code("cargo install par-term");
90                        ui.add_space(8.0);
91                    }
92                    _ => {
93                        // Standalone/Bundle - show Install button
94                        if installing {
95                            let button =
96                                egui::Button::new(egui::RichText::new("Installing...").strong());
97                            ui.add_enabled(false, button);
98                        } else if ui
99                            .button(egui::RichText::new("Install Update").strong())
100                            .clicked()
101                        {
102                            action = UpdateDialogAction::InstallUpdate(version_str.to_string());
103                        }
104                        ui.add_space(8.0);
105                    }
106                }
107
108                // Show install status message
109                if let Some(status) = install_status {
110                    ui.add_space(4.0);
111                    let color = if status.starts_with("Update failed") {
112                        egui::Color32::from_rgb(255, 100, 100)
113                    } else if status.starts_with("Updated to") {
114                        egui::Color32::from_rgb(100, 255, 100)
115                    } else {
116                        egui::Color32::YELLOW
117                    };
118                    ui.label(egui::RichText::new(status).color(color));
119                    ui.add_space(4.0);
120                }
121
122                // Bottom buttons
123                ui.separator();
124                ui.add_space(4.0);
125                ui.horizontal(|ui| {
126                    // Disable Skip and Dismiss while installing
127                    ui.add_enabled_ui(!installing, |ui| {
128                        if ui.button("Skip This Version").clicked() {
129                            action = UpdateDialogAction::SkipVersion(version_str.to_string());
130                        }
131                        if ui.button("Dismiss").clicked() {
132                            action = UpdateDialogAction::Dismiss;
133                        }
134                    });
135                });
136            });
137        });
138
139    action
140}