mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: show dialog when attempting to reconnect to daemon
This commit is contained in:
parent
b1229a3e1e
commit
c77fc555ac
@ -3,7 +3,6 @@ mod connection;
|
||||
mod macros;
|
||||
|
||||
pub use lact_schema as schema;
|
||||
use lact_schema::request::ProfileBase;
|
||||
|
||||
use amdgpu_sysfs::gpu_handle::{
|
||||
power_profile_mode::PowerProfileModesTable, PerformanceLevel, PowerLevelKind,
|
||||
@ -12,7 +11,7 @@ use anyhow::Context;
|
||||
use connection::{tcp::TcpConnection, unix::UnixConnection, DaemonConnection};
|
||||
use nix::unistd::getuid;
|
||||
use schema::{
|
||||
request::{ConfirmCommand, SetClocksCommand},
|
||||
request::{ConfirmCommand, ProfileBase, SetClocksCommand},
|
||||
ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanOptions, PowerStates, ProfilesInfo,
|
||||
Request, Response, SystemInfo,
|
||||
};
|
||||
@ -21,14 +20,19 @@ use std::{
|
||||
future::Future, marker::PhantomData, os::unix::net::UnixStream, path::PathBuf, pin::Pin,
|
||||
rc::Rc, time::Duration,
|
||||
};
|
||||
use tokio::{net::ToSocketAddrs, sync::Mutex};
|
||||
use tokio::{
|
||||
net::ToSocketAddrs,
|
||||
sync::{broadcast, Mutex},
|
||||
};
|
||||
use tracing::{error, info};
|
||||
|
||||
const STATUS_MSG_CHANNEL_SIZE: usize = 16;
|
||||
const RECONNECT_INTERVAL_MS: u64 = 250;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DaemonClient {
|
||||
stream: Rc<Mutex<Box<dyn DaemonConnection>>>,
|
||||
status_tx: broadcast::Sender<ConnectionStatusMsg>,
|
||||
pub embedded: bool,
|
||||
}
|
||||
|
||||
@ -41,6 +45,7 @@ impl DaemonClient {
|
||||
Ok(Self {
|
||||
stream: Rc::new(Mutex::new(stream)),
|
||||
embedded: false,
|
||||
status_tx: broadcast::Sender::new(STATUS_MSG_CHANNEL_SIZE),
|
||||
})
|
||||
}
|
||||
|
||||
@ -50,6 +55,7 @@ impl DaemonClient {
|
||||
Ok(Self {
|
||||
stream: Rc::new(Mutex::new(stream)),
|
||||
embedded: false,
|
||||
status_tx: broadcast::Sender::new(STATUS_MSG_CHANNEL_SIZE),
|
||||
})
|
||||
}
|
||||
|
||||
@ -58,9 +64,14 @@ impl DaemonClient {
|
||||
Ok(Self {
|
||||
stream: Rc::new(Mutex::new(Box::new(connection))),
|
||||
embedded,
|
||||
status_tx: broadcast::Sender::new(STATUS_MSG_CHANNEL_SIZE),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn status_receiver(&self) -> broadcast::Receiver<ConnectionStatusMsg> {
|
||||
self.status_tx.subscribe()
|
||||
}
|
||||
|
||||
fn make_request<'a, 'r, T: Deserialize<'r>>(
|
||||
&'a self,
|
||||
request: Request<'a>,
|
||||
@ -76,6 +87,7 @@ impl DaemonClient {
|
||||
}),
|
||||
Err(err) => {
|
||||
error!("Could not make request: {err}, reconnecting to socket");
|
||||
let _ = self.status_tx.send(ConnectionStatusMsg::Disconnected);
|
||||
|
||||
loop {
|
||||
match stream.new_connection().await {
|
||||
@ -83,11 +95,15 @@ impl DaemonClient {
|
||||
info!("Established new socket connection");
|
||||
*stream = new_connection;
|
||||
drop(stream);
|
||||
|
||||
let _ = self.status_tx.send(ConnectionStatusMsg::Reconnected);
|
||||
|
||||
return self.make_request(request).await;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Could not reconnect: {err:#}, retrying in {RECONNECT_INTERVAL_MS}ms");
|
||||
std::thread::sleep(Duration::from_millis(RECONNECT_INTERVAL_MS));
|
||||
tokio::time::sleep(Duration::from_millis(RECONNECT_INTERVAL_MS))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -249,3 +265,9 @@ impl<'a, T: Deserialize<'a>> ResponseBuffer<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ConnectionStatusMsg {
|
||||
Disconnected,
|
||||
Reconnected,
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use gtk::{
|
||||
MessageType, ResponseType,
|
||||
};
|
||||
use header::{Header, HeaderMsg};
|
||||
use lact_client::DaemonClient;
|
||||
use lact_client::{ConnectionStatusMsg, DaemonClient};
|
||||
use lact_daemon::MODULE_CONF_PATH;
|
||||
use lact_schema::{
|
||||
args::GuiArgs,
|
||||
@ -62,7 +62,7 @@ impl AsyncComponent for AppModel {
|
||||
type CommandOutput = ();
|
||||
|
||||
view! {
|
||||
#[name = "root_window"]
|
||||
#[root]
|
||||
gtk::ApplicationWindow {
|
||||
set_title: Some("LACT"),
|
||||
set_default_width: 600,
|
||||
@ -78,6 +78,17 @@ impl AsyncComponent for AppModel {
|
||||
model.root_stack.container.clone(),
|
||||
model.apply_revealer.widget(),
|
||||
}
|
||||
},
|
||||
|
||||
#[name = "reconnecting_dialog"]
|
||||
gtk::MessageDialog::new(
|
||||
Some(&root),
|
||||
gtk::DialogFlags::MODAL,
|
||||
gtk::MessageType::Error,
|
||||
gtk::ButtonsType::None,
|
||||
"Daemon connection lost, reconnecting...",
|
||||
) -> gtk::MessageDialog {
|
||||
set_title: Some("Connection Lost"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +116,19 @@ impl AsyncComponent for AppModel {
|
||||
.expect("Could not establish any daemon connection"),
|
||||
};
|
||||
|
||||
let mut conn_status_rx = daemon_client.status_receiver();
|
||||
relm4::spawn_local(clone!(
|
||||
#[strong]
|
||||
sender,
|
||||
async move {
|
||||
loop {
|
||||
if let Ok(msg) = conn_status_rx.recv().await {
|
||||
sender.input(AppMsg::ConnectionStatus(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
register_actions(&sender);
|
||||
|
||||
let system_info_buf = daemon_client
|
||||
@ -194,7 +218,7 @@ impl AsyncComponent for AppModel {
|
||||
root: &Self::Root,
|
||||
) {
|
||||
trace!("update {msg:#?}");
|
||||
if let Err(err) = self.handle_msg(msg, sender.clone(), root).await {
|
||||
if let Err(err) = self.handle_msg(msg, sender.clone(), root, widgets).await {
|
||||
show_error(root, &err);
|
||||
}
|
||||
self.update_view(widgets, sender);
|
||||
@ -207,13 +231,13 @@ impl AppModel {
|
||||
msg: AppMsg,
|
||||
sender: AsyncComponentSender<Self>,
|
||||
root: >k::ApplicationWindow,
|
||||
widgets: &AppModelWidgets,
|
||||
) -> Result<(), Rc<anyhow::Error>> {
|
||||
match msg {
|
||||
AppMsg::Error(err) => Err(err),
|
||||
AppMsg::Error(err) => return Err(err),
|
||||
AppMsg::ReloadProfiles => {
|
||||
self.reload_profiles().await?;
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ReloadData { full } => {
|
||||
let gpu_id = self.current_gpu_id()?;
|
||||
@ -222,12 +246,10 @@ impl AppModel {
|
||||
} else {
|
||||
self.update_gpu_data(gpu_id, sender).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::SelectProfile(profile) => {
|
||||
self.daemon_client.set_profile(profile).await?;
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::CreateProfile(name, base) => {
|
||||
self.daemon_client
|
||||
@ -235,30 +257,26 @@ impl AppModel {
|
||||
.await?;
|
||||
self.daemon_client.set_profile(Some(name)).await?;
|
||||
sender.input(AppMsg::ReloadProfiles);
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::DeleteProfile(profile) => {
|
||||
self.daemon_client.delete_profile(profile).await?;
|
||||
sender.input(AppMsg::ReloadProfiles);
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::Stats(stats) => {
|
||||
self.root_stack.info_page.set_stats(&stats);
|
||||
self.root_stack.thermals_page.set_stats(&stats, false);
|
||||
self.root_stack.oc_page.set_stats(&stats, false);
|
||||
self.graphs_window.set_stats(&stats);
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ApplyChanges => self
|
||||
.apply_settings(self.current_gpu_id()?, root, &sender)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
err.into()
|
||||
}),
|
||||
AppMsg::ApplyChanges => {
|
||||
self.apply_settings(self.current_gpu_id()?, root, &sender)
|
||||
.await
|
||||
.inspect_err(|_| {
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
})?;
|
||||
}
|
||||
AppMsg::RevertChanges => {
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ResetClocks => {
|
||||
let gpu_id = self.current_gpu_id()?;
|
||||
@ -269,8 +287,6 @@ impl AppModel {
|
||||
.confirm_pending_config(ConfirmCommand::Confirm)
|
||||
.await?;
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ResetPmfw => {
|
||||
let gpu_id = self.current_gpu_id()?;
|
||||
@ -279,34 +295,30 @@ impl AppModel {
|
||||
.confirm_pending_config(ConfirmCommand::Confirm)
|
||||
.await?;
|
||||
sender.input(AppMsg::ReloadData { full: false });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ShowGraphsWindow => {
|
||||
self.graphs_window.show();
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::DumpVBios => {
|
||||
self.dump_vbios(&self.current_gpu_id()?, root).await;
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::DebugSnapshot => {
|
||||
self.generate_debug_snapshot(root).await;
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::EnableOverdrive => {
|
||||
toggle_overdrive(&self.daemon_client, true, root.clone()).await;
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::DisableOverdrive => {
|
||||
toggle_overdrive(&self.daemon_client, false, root.clone()).await;
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ResetConfig => {
|
||||
self.daemon_client.reset_config().await?;
|
||||
sender.input(AppMsg::ReloadData { full: true });
|
||||
Ok(())
|
||||
}
|
||||
AppMsg::ConnectionStatus(status) => match status {
|
||||
ConnectionStatusMsg::Disconnected => widgets.reconnecting_dialog.present(),
|
||||
ConnectionStatusMsg::Reconnected => widgets.reconnecting_dialog.hide(),
|
||||
},
|
||||
AppMsg::AskConfirmation(options, confirmed_msg) => {
|
||||
let sender = sender.clone();
|
||||
|
||||
@ -318,10 +330,9 @@ impl AppModel {
|
||||
}
|
||||
});
|
||||
controller.detach_runtime();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn current_gpu_id(&self) -> anyhow::Result<String> {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::confirmation_dialog::ConfirmationOptions;
|
||||
use lact_client::ConnectionStatusMsg;
|
||||
use lact_schema::{request::ProfileBase, DeviceStats};
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -21,6 +22,7 @@ pub enum AppMsg {
|
||||
SelectProfile(Option<String>),
|
||||
CreateProfile(String, ProfileBase),
|
||||
DeleteProfile(String),
|
||||
ConnectionStatus(ConnectionStatusMsg),
|
||||
AskConfirmation(ConfirmationOptions, Box<AppMsg>),
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user