Fixed build workflow

This commit is contained in:
Alexandr Bogomiakov
2025-07-23 23:53:46 +03:00
parent 201d008d81
commit 977d67cbf0
15 changed files with 1467 additions and 880 deletions

View File

@@ -1,10 +1,10 @@
use crate::gui::common::{perform_sync, KhmSettings};
use log::{error, info};
use std::sync::{Arc, Mutex};
use tray_icon::{
menu::{Menu, MenuItem, MenuId},
menu::{Menu, MenuId, MenuItem},
TrayIcon, TrayIconBuilder,
};
use crate::gui::common::{KhmSettings, perform_sync};
#[derive(Debug, Clone)]
pub struct SyncStatus {
@@ -30,21 +30,26 @@ pub struct TrayMenuIds {
}
/// Create tray icon with menu
pub fn create_tray_icon(settings: &KhmSettings, sync_status: &SyncStatus) -> (TrayIcon, TrayMenuIds) {
pub fn create_tray_icon(
settings: &KhmSettings,
sync_status: &SyncStatus,
) -> (TrayIcon, TrayMenuIds) {
// Create simple blue icon
let icon_data: Vec<u8> = (0..32*32).flat_map(|i| {
let y = i / 32;
let x = i % 32;
if x < 2 || x >= 30 || y < 2 || y >= 30 {
[255, 255, 255, 255] // White border
} else {
[64, 128, 255, 255] // Blue center
}
}).collect();
let icon_data: Vec<u8> = (0..32 * 32)
.flat_map(|i| {
let y = i / 32;
let x = i % 32;
if x < 2 || x >= 30 || y < 2 || y >= 30 {
[255, 255, 255, 255] // White border
} else {
[64, 128, 255, 255] // Blue center
}
})
.collect();
let icon = tray_icon::Icon::from_rgba(icon_data, 32, 32).unwrap();
let menu = Menu::new();
// Show current configuration status (static)
let host_text = if settings.host.is_empty() {
"Host: Not configured"
@@ -52,64 +57,75 @@ pub fn create_tray_icon(settings: &KhmSettings, sync_status: &SyncStatus) -> (Tr
&format!("Host: {}", settings.host)
};
menu.append(&MenuItem::new(host_text, false, None)).unwrap();
let flow_text = if settings.flow.is_empty() {
"Flow: Not configured"
} else {
&format!("Flow: {}", settings.flow)
};
menu.append(&MenuItem::new(flow_text, false, None)).unwrap();
let is_auto_sync_enabled = !settings.host.is_empty() && !settings.flow.is_empty() && settings.in_place;
let sync_text = format!("Auto sync: {} ({}min)",
if is_auto_sync_enabled { "On" } else { "Off" },
settings.auto_sync_interval_minutes);
menu.append(&MenuItem::new(&sync_text, false, None)).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator()).unwrap();
let is_auto_sync_enabled =
!settings.host.is_empty() && !settings.flow.is_empty() && settings.in_place;
let sync_text = format!(
"Auto sync: {} ({}min)",
if is_auto_sync_enabled { "On" } else { "Off" },
settings.auto_sync_interval_minutes
);
menu.append(&MenuItem::new(&sync_text, false, None))
.unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator())
.unwrap();
// Sync Now menu item
let sync_item = MenuItem::new("Sync Now", !settings.host.is_empty() && !settings.flow.is_empty(), None);
let sync_item = MenuItem::new(
"Sync Now",
!settings.host.is_empty() && !settings.flow.is_empty(),
None,
);
let sync_id = sync_item.id().clone();
menu.append(&sync_item).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator()).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator())
.unwrap();
// Settings menu item
let settings_item = MenuItem::new("Settings", true, None);
let settings_id = settings_item.id().clone();
menu.append(&settings_item).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator()).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator())
.unwrap();
// Quit menu item
let quit_item = MenuItem::new("Quit", true, None);
let quit_id = quit_item.id().clone();
menu.append(&quit_item).unwrap();
// Create initial tooltip
let tooltip = create_tooltip(settings, sync_status);
let tray_icon = TrayIconBuilder::new()
.with_tooltip(&tooltip)
.with_icon(icon)
.with_menu(Box::new(menu))
.build()
.unwrap();
let menu_ids = TrayMenuIds {
settings_id,
quit_id,
sync_id,
};
(tray_icon, menu_ids)
}
/// Update tray menu with new settings
pub fn update_tray_menu(tray_icon: &TrayIcon, settings: &KhmSettings) -> TrayMenuIds {
let menu = Menu::new();
// Show current configuration status (static)
let host_text = if settings.host.is_empty() {
"Host: Not configured"
@@ -117,43 +133,54 @@ pub fn update_tray_menu(tray_icon: &TrayIcon, settings: &KhmSettings) -> TrayMen
&format!("Host: {}", settings.host)
};
menu.append(&MenuItem::new(host_text, false, None)).unwrap();
let flow_text = if settings.flow.is_empty() {
"Flow: Not configured"
} else {
&format!("Flow: {}", settings.flow)
};
menu.append(&MenuItem::new(flow_text, false, None)).unwrap();
let is_auto_sync_enabled = !settings.host.is_empty() && !settings.flow.is_empty() && settings.in_place;
let sync_text = format!("Auto sync: {} ({}min)",
if is_auto_sync_enabled { "On" } else { "Off" },
settings.auto_sync_interval_minutes);
menu.append(&MenuItem::new(&sync_text, false, None)).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator()).unwrap();
let is_auto_sync_enabled =
!settings.host.is_empty() && !settings.flow.is_empty() && settings.in_place;
let sync_text = format!(
"Auto sync: {} ({}min)",
if is_auto_sync_enabled { "On" } else { "Off" },
settings.auto_sync_interval_minutes
);
menu.append(&MenuItem::new(&sync_text, false, None))
.unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator())
.unwrap();
// Sync Now menu item
let sync_item = MenuItem::new("Sync Now", !settings.host.is_empty() && !settings.flow.is_empty(), None);
let sync_item = MenuItem::new(
"Sync Now",
!settings.host.is_empty() && !settings.flow.is_empty(),
None,
);
let sync_id = sync_item.id().clone();
menu.append(&sync_item).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator()).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator())
.unwrap();
// Settings menu item
let settings_item = MenuItem::new("Settings", true, None);
let settings_id = settings_item.id().clone();
menu.append(&settings_item).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator()).unwrap();
menu.append(&tray_icon::menu::PredefinedMenuItem::separator())
.unwrap();
// Quit menu item
let quit_item = MenuItem::new("Quit", true, None);
let quit_id = quit_item.id().clone();
menu.append(&quit_item).unwrap();
tray_icon.set_menu(Some(Box::new(menu)));
TrayMenuIds {
settings_id,
quit_id,
@@ -163,14 +190,17 @@ pub fn update_tray_menu(tray_icon: &TrayIcon, settings: &KhmSettings) -> TrayMen
/// Create tooltip text for tray icon
pub fn create_tooltip(settings: &KhmSettings, sync_status: &SyncStatus) -> String {
let mut tooltip = format!("KHM - SSH Key Manager\nHost: {}\nFlow: {}", settings.host, settings.flow);
let mut tooltip = format!(
"KHM - SSH Key Manager\nHost: {}\nFlow: {}",
settings.host, settings.flow
);
if let Some(keys_count) = sync_status.last_sync_keys {
tooltip.push_str(&format!("\nLast sync: {} keys", keys_count));
} else {
tooltip.push_str("\nLast sync: Never");
}
if let Some(seconds) = sync_status.next_sync_in_seconds {
if seconds > 60 {
tooltip.push_str(&format!("\nNext sync: {}m {}s", seconds / 60, seconds % 60));
@@ -178,7 +208,7 @@ pub fn create_tooltip(settings: &KhmSettings, sync_status: &SyncStatus) -> Strin
tooltip.push_str(&format!("\nNext sync: {}s", seconds));
}
}
tooltip
}
@@ -186,18 +216,24 @@ pub fn create_tooltip(settings: &KhmSettings, sync_status: &SyncStatus) -> Strin
pub fn start_auto_sync_task(
settings: Arc<Mutex<KhmSettings>>,
sync_status: Arc<Mutex<SyncStatus>>,
event_sender: winit::event_loop::EventLoopProxy<crate::gui::UserEvent>
event_sender: winit::event_loop::EventLoopProxy<crate::gui::UserEvent>,
) -> Option<std::thread::JoinHandle<()>> {
let initial_settings = settings.lock().unwrap().clone();
// Only start auto sync if settings are valid and in_place is enabled
if initial_settings.host.is_empty() || initial_settings.flow.is_empty() || !initial_settings.in_place {
if initial_settings.host.is_empty()
|| initial_settings.flow.is_empty()
|| !initial_settings.in_place
{
info!("Auto sync disabled or settings invalid");
return None;
}
info!("Starting auto sync with interval {} minutes", initial_settings.auto_sync_interval_minutes);
info!(
"Starting auto sync with interval {} minutes",
initial_settings.auto_sync_interval_minutes
);
let handle = std::thread::spawn(move || {
// Initial sync on startup
info!("Performing initial sync on startup");
@@ -207,7 +243,10 @@ pub fn start_auto_sync_task(
rt.block_on(async {
match perform_sync(&current_settings).await {
Ok(keys_count) => {
info!("Initial sync completed successfully with {} keys", keys_count);
info!(
"Initial sync completed successfully with {} keys",
keys_count
);
let mut status = sync_status.lock().unwrap();
status.last_sync_time = Some(std::time::Instant::now());
status.last_sync_keys = Some(keys_count);
@@ -219,27 +258,28 @@ pub fn start_auto_sync_task(
}
});
}
// Start menu update timer
let timer_sender = event_sender.clone();
std::thread::spawn(move || {
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
let _ = timer_sender.send_event(crate::gui::UserEvent::UpdateMenu);
}
std::thread::spawn(move || loop {
std::thread::sleep(std::time::Duration::from_secs(1));
let _ = timer_sender.send_event(crate::gui::UserEvent::UpdateMenu);
});
// Periodic sync
loop {
let interval_minutes = current_settings.auto_sync_interval_minutes;
std::thread::sleep(std::time::Duration::from_secs(interval_minutes as u64 * 60));
let current_settings = settings.lock().unwrap().clone();
if current_settings.host.is_empty() || current_settings.flow.is_empty() || !current_settings.in_place {
if current_settings.host.is_empty()
|| current_settings.flow.is_empty()
|| !current_settings.in_place
{
info!("Auto sync stopped due to invalid settings or disabled in_place");
break;
}
info!("Performing scheduled auto sync");
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
@@ -258,7 +298,7 @@ pub fn start_auto_sync_task(
});
}
});
Some(handle)
}
@@ -268,7 +308,7 @@ pub fn update_sync_status(settings: &KhmSettings, sync_status: &mut SyncStatus)
if let Some(last_sync) = sync_status.last_sync_time {
let elapsed = last_sync.elapsed().as_secs();
let interval_seconds = settings.auto_sync_interval_minutes as u64 * 60;
if elapsed < interval_seconds {
sync_status.next_sync_in_seconds = Some(interval_seconds - elapsed);
} else {