final polish

This commit is contained in:
ms2k 2026-03-31 22:46:58 +09:00
commit b23c89cc1f

View file

@ -8,7 +8,7 @@ use std::collections::HashMap;
use crate::config::Config;
use crate::countries::{get_countries, Country};
use crate::flags;
use crate::nordvpn::{self, CmdResult, Poller};
use crate::nordvpn::{self, CmdResult, Poller, StatusInfo};
use crate::ui::config_dialog::{ConfigDialog, DialogResult};
use crate::ui::country_selector::CountrySelector;
use crate::world_map::WorldMap;
@ -28,10 +28,12 @@ pub struct App {
config_dialog: Option<ConfigDialog>,
/// Last connect/disconnect result shown inline below the status bar.
notification: Option<String>,
/// A connect key that is awaiting user confirmation before being dispatched.
pending_connect: Option<String>,
}
impl App {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
pub fn new(_cc: &eframe::CreationContext<'_>) -> Self {
let config = Config::load();
let countries = get_countries(&config.external_app);
let poller = Poller::new(config.external_app.clone(), config.refresh_rate);
@ -53,6 +55,7 @@ impl App {
world_map: WorldMap::new(),
config_dialog: None,
notification: None,
pending_connect: None,
}
}
@ -64,6 +67,16 @@ impl App {
});
}
/// If already connected, queue a confirmation prompt; otherwise connect immediately.
fn request_connect(&mut self, key: String, status: &StatusInfo) {
if status.is_connected() {
self.pending_connect = Some(key);
} else {
self.notification = None;
self.spawn_connect(key);
}
}
fn spawn_disconnect(&self) {
let app = self.config.external_app.clone();
let tx = self.cmd_tx.clone();
@ -162,7 +175,7 @@ impl eframe::App for App {
}
// ── Left panel — country selector ───────────────────────────────────
let panel_width = ctx.screen_rect().width() * 0.3;
let panel_width = ctx.content_rect().width() * 0.3;
let connect_key =
egui::SidePanel::left("country_selector")
.exact_width(panel_width)
@ -179,16 +192,52 @@ impl eframe::App for App {
.inner;
if let Some(key) = connect_key {
self.notification = None;
self.spawn_connect(key);
self.request_connect(key, &status);
}
// ── Central panel — world map ────────────────────────────────────────
egui::CentralPanel::default().show(ctx, |ui| {
if let Some(key) = self.world_map.show(ui, &self.countries, status.country.as_deref()) {
self.notification = None;
self.spawn_connect(key);
self.request_connect(key, &status);
}
});
// ── Confirmation modal ───────────────────────────────────────────────
if let Some(key) = self.pending_connect.clone() {
let label = self
.countries
.iter()
.find(|c| c.nordvpn_key == key)
.map(|c| c.name.as_str())
.unwrap_or(key.as_str());
let mut confirmed = false;
let mut cancelled = false;
egui::Window::new("Confirm")
.collapsible(false)
.resizable(false)
.anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0])
.show(ctx, |ui| {
ui.label(format!("Switch server to {}?", label));
ui.add_space(8.0);
ui.horizontal(|ui| {
if ui.button("Connect").clicked() {
confirmed = true;
}
if ui.button("Cancel").clicked() {
cancelled = true;
}
});
});
if confirmed {
self.notification = None;
self.spawn_connect(key);
self.pending_connect = None;
} else if cancelled {
self.pending_connect = None;
}
}
}
}