use super::egui_overlays;
use super::types::{DemoteAction, DemoteSnapshot, PostRenderActions};
use crate::agent_commands_store::AgentCommandStore;
use crate::command_palette::CommandPalette;
use crate::config::Config;
use crate::crash_triage::CrashTriageState;
use crate::pane::{PaneBounds, SplitDirection};
use crate::status_bar::StatusBarUI;
use arc_swap::ArcSwap;
#[cfg(feature = "mux")]
use crate::app::tmux_handler::tmux_state::TmuxState;
pub(super) fn render_demote_overlays(
ctx: &egui::Context,
snapshot: DemoteSnapshot,
pane_bounds: Option<PaneBounds>,
actions: &mut PostRenderActions,
) {
match snapshot {
DemoteSnapshot::PickTab => {
egui_overlays::render_toast_overlay(
ctx,
Some("Click a tab to merge into (Esc to cancel)"),
);
}
DemoteSnapshot::PickPane => {
egui_overlays::render_toast_overlay(
ctx,
Some("Click a pane to merge into (Esc to cancel)"),
);
}
DemoteSnapshot::ChooseDirection {
source_tab_id,
target_tab_id,
target_pane_id,
} => {
if let Some(bounds) = pane_bounds {
let center_x = bounds.x + bounds.width / 2.0;
let center_y = bounds.y + bounds.height / 2.0;
egui::Area::new(egui::Id::new("demote_direction_overlay"))
.fixed_pos(egui::pos2(center_x - 100.0, center_y - 30.0))
.order(egui::Order::Foreground)
.show(ctx, |ui| {
egui::Frame::NONE
.fill(egui::Color32::from_rgba_unmultiplied(30, 30, 30, 240))
.inner_margin(egui::Margin::symmetric(16, 10))
.corner_radius(8.0)
.stroke(egui::Stroke::new(1.0, egui::Color32::from_rgb(80, 80, 80)))
.show(ui, |ui| {
ui.style_mut().visuals.override_text_color =
Some(egui::Color32::from_rgb(255, 255, 255));
ui.vertical_centered(|ui| {
ui.label(egui::RichText::new("Split direction:").size(14.0));
ui.add_space(4.0);
ui.horizontal(|ui| {
if ui
.button(egui::RichText::new("Horizontal").size(14.0))
.clicked()
{
actions.demote = DemoteAction::Execute {
source_tab_id,
target_tab_id,
target_pane_id,
direction: SplitDirection::Horizontal,
};
}
if ui
.button(egui::RichText::new("Vertical").size(14.0))
.clicked()
{
actions.demote = DemoteAction::Execute {
source_tab_id,
target_tab_id,
target_pane_id,
direction: SplitDirection::Vertical,
};
}
});
});
});
});
}
}
DemoteSnapshot::Idle => {}
}
}
pub(super) fn open_command_palette_with_runtime_rows(
status_bar_ui: &StatusBarUI,
agent_commands: &AgentCommandStore,
crash_triage: &mut CrashTriageState,
config: &ArcSwap<Config>,
command_palette: &mut CommandPalette,
#[cfg(feature = "mux")] tmux_state: &TmuxState,
) {
#[cfg_attr(not(feature = "mux"), allow(unused_mut))]
let mut plugin_rows = crate::command_palette::catalog::plugin_palette_entries(
&status_bar_ui.plugin_host().palette_actions(),
);
#[cfg(feature = "mux")]
{
let map = &tmux_state.tmux_pane_owners;
plugin_rows.extend(
tmux_state
.agent_roster
.palette_rows(&|pane| map.contains_key(&pane)),
);
}
plugin_rows.extend(agent_commands.palette_rows());
plugin_rows.extend(crate::command_palette::catalog::agent_palette_entries(
&config.load().agents,
));
plugin_rows.extend(crash_triage.palette_entries());
#[cfg(feature = "mux")]
plugin_rows.extend(tmux_state.mux_palette_rows());
command_palette.open(plugin_rows);
}
pub(super) fn render_update_dialog(
ctx: &egui::Context,
update_state: &mut crate::app::window_state::UpdateState,
status_bar_ui: &mut StatusBarUI,
config: &ArcSwap<Config>,
actions: &mut PostRenderActions,
) {
if !update_state.show_dialog {
return;
}
if let Some(ref rx) = update_state.install_receiver
&& let Ok(result) = rx.try_recv()
{
match result {
Ok(update_result) => {
update_state.install_status = Some(format!(
"Updated to v{}! Restart par-term to use the new version.",
update_result.new_version
));
update_state.installing = false;
status_bar_ui.update_available_version = None;
}
Err(e) => {
update_state.install_status = Some(format!("Update failed: {}", e));
update_state.installing = false;
}
}
update_state.install_receiver = None;
}
if let Some(ref update_result) = update_state.last_result {
let dialog_action = crate::update_dialog::render(
ctx,
update_result,
env!("CARGO_PKG_VERSION"),
update_state.installation_type,
update_state.installing,
update_state.install_status.as_deref(),
);
match dialog_action {
crate::update_dialog::UpdateDialogAction::Dismiss => {
if !update_state.installing {
update_state.show_dialog = false;
update_state.install_status = None;
}
}
crate::update_dialog::UpdateDialogAction::SkipVersion(v) => {
config.rcu(|old| {
let mut new = (**old).clone();
new.updates.skipped_version = Some(v.clone());
std::sync::Arc::new(new)
});
update_state.show_dialog = false;
status_bar_ui.update_available_version = None;
update_state.install_status = None;
actions.save_config = true;
}
crate::update_dialog::UpdateDialogAction::InstallUpdate(v) => {
if !update_state.installing {
update_state.installing = true;
update_state.install_status = Some("Downloading update...".to_string());
let (tx, rx) = std::sync::mpsc::channel();
update_state.install_receiver = Some(rx);
let version = v.clone();
let current_version = crate::VERSION.to_string();
std::thread::spawn(move || {
let result = par_term_update::self_updater::perform_update(
&version,
¤t_version,
);
let _ = tx.send(result);
});
}
}
crate::update_dialog::UpdateDialogAction::None => {}
}
} else {
update_state.show_dialog = false;
}
}