mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-08-17 16:34:54 -05:00
feat: enable autostart during the service setup (#1146)
This commit is contained in:
@@ -254,6 +254,8 @@ service-logs = Service Logs
|
||||
service-start = Start
|
||||
service-stop = Stop
|
||||
service-restart = Restart
|
||||
service-autostart = Autostart on boot
|
||||
service-autostart-disable = Also disable autostart
|
||||
|
||||
version-mismatch-description =
|
||||
Version mismatch between GUI and Daemon ({$gui_version}-{$gui_commit} vs {$daemon_version}-{$daemon_commit})!
|
||||
|
||||
+6
-2
@@ -666,10 +666,13 @@ impl AppModel {
|
||||
self.overdrive_dialog.emit(OverdriveDialogMsg::Show);
|
||||
}
|
||||
AppMsg::ShowServiceSetupDialog => {
|
||||
let (manager_proxy, unit_proxy) = systemd::connect_unit_proxy().await?;
|
||||
|
||||
let params = ServiceSetupDialogParams {
|
||||
parent: root.clone().upcast(),
|
||||
initial_client: Ok((self.daemon_client.clone(), self.system_info.clone())),
|
||||
unit_proxy: systemd::connect_unit_proxy().await?,
|
||||
manager_proxy,
|
||||
unit_proxy,
|
||||
};
|
||||
let controller = ServiceSetupDialog::builder()
|
||||
.launch(params)
|
||||
@@ -1431,10 +1434,11 @@ async fn create_connection(
|
||||
Ok(client) => (client, false),
|
||||
Err(err) => {
|
||||
let configured_client = match connect_unit_proxy().await {
|
||||
Ok(unit_proxy) => {
|
||||
Ok((manager_proxy, unit_proxy)) => {
|
||||
let params = ServiceSetupDialogParams {
|
||||
parent: root.clone().upcast(),
|
||||
initial_client: Err(err),
|
||||
manager_proxy,
|
||||
unit_proxy,
|
||||
};
|
||||
let service_setup = ServiceSetupDialog::builder().launch(params).into_stream();
|
||||
|
||||
@@ -3,12 +3,13 @@ pub mod systemd;
|
||||
use crate::I18N;
|
||||
use crate::app::components::info_row::{InfoRow, InfoRowExt};
|
||||
use crate::app::utils::ext::FlowBoxExt;
|
||||
use crate::service_setup::systemd::{START_MODE_REPLACE, UnitProxy};
|
||||
use crate::service_setup::systemd::{ManagerProxy, START_MODE_REPLACE, UNIT_NAME, UnitProxy};
|
||||
use adw::prelude::*;
|
||||
use anyhow::{Context as _, anyhow};
|
||||
use i18n_embed_fl::fl;
|
||||
use lact_client::DaemonClient;
|
||||
use lact_schema::{SystemInfo, VersionInfo};
|
||||
use relm4::binding::{BoolBinding, ConnectBinding as _};
|
||||
use relm4::{
|
||||
AsyncComponentSender, RelmWidgetExt,
|
||||
css::{self, ERROR, SUCCESS, WARNING},
|
||||
@@ -22,15 +23,19 @@ use tracing::debug;
|
||||
|
||||
pub struct ServiceSetupDialog {
|
||||
connection_status: ConnectionStatus,
|
||||
manager_proxy: ManagerProxy<'static>,
|
||||
unit_proxy: UnitProxy<'static>,
|
||||
service_logs: gtk::TextBuffer,
|
||||
service_state: String,
|
||||
autostart_on_start: BoolBinding,
|
||||
autostart_on_stop: BoolBinding,
|
||||
setup_error: Option<anyhow::Error>,
|
||||
}
|
||||
|
||||
pub struct ServiceSetupDialogParams {
|
||||
pub parent: gtk::ApplicationWindow,
|
||||
pub initial_client: anyhow::Result<(DaemonClient, SystemInfo)>,
|
||||
pub manager_proxy: ManagerProxy<'static>,
|
||||
pub unit_proxy: UnitProxy<'static>,
|
||||
}
|
||||
|
||||
@@ -188,17 +193,35 @@ impl AsyncComponent for ServiceSetupDialog {
|
||||
set_hexpand: true,
|
||||
set_halign: gtk::Align::End,
|
||||
|
||||
gtk::Button {
|
||||
adw::SplitButton {
|
||||
set_label: &fl!(I18N, "service-start"),
|
||||
connect_clicked => ServiceSetupDialogMsg::StartService,
|
||||
add_css_class: "suggested-action",
|
||||
|
||||
#[wrap(Some)]
|
||||
set_popover = >k::Popover {
|
||||
gtk::CheckButton {
|
||||
set_label: Some(&fl!(I18N, "service-autostart")),
|
||||
bind: &model.autostart_on_start,
|
||||
},
|
||||
},
|
||||
|
||||
#[watch]
|
||||
set_visible: model.service_state != systemd::UNIT_STATE_ACTIVE,
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
adw::SplitButton {
|
||||
set_label: &fl!(I18N, "service-stop"),
|
||||
connect_clicked => ServiceSetupDialogMsg::StopService,
|
||||
|
||||
#[wrap(Some)]
|
||||
set_popover = >k::Popover {
|
||||
gtk::CheckButton {
|
||||
set_label: Some(&fl!(I18N, "service-autostart-disable")),
|
||||
bind: &model.autostart_on_stop,
|
||||
},
|
||||
},
|
||||
|
||||
#[watch]
|
||||
set_visible: model.service_state == systemd::UNIT_STATE_ACTIVE,
|
||||
},
|
||||
@@ -253,7 +276,10 @@ impl AsyncComponent for ServiceSetupDialog {
|
||||
|
||||
let model = Self {
|
||||
connection_status,
|
||||
manager_proxy: params.manager_proxy,
|
||||
unit_proxy: params.unit_proxy,
|
||||
autostart_on_start: BoolBinding::new(true),
|
||||
autostart_on_stop: BoolBinding::new(true),
|
||||
service_logs: gtk::TextBuffer::builder()
|
||||
.text(service_logs_handle.await.unwrap())
|
||||
.build(),
|
||||
@@ -289,12 +315,30 @@ impl ServiceSetupDialog {
|
||||
match msg {
|
||||
ServiceSetupDialogMsg::Reconnect => (),
|
||||
ServiceSetupDialogMsg::StartService => {
|
||||
self.unit_proxy.start(START_MODE_REPLACE).await?;
|
||||
// Note: this order is important, doing it the other way around causes 2 polkit prompts
|
||||
if self.autostart_on_start.value() {
|
||||
self.manager_proxy
|
||||
.enable_unit_files(&[UNIT_NAME], false, true)
|
||||
.await
|
||||
.context("could not enable unit")?;
|
||||
}
|
||||
|
||||
self.unit_proxy
|
||||
.start(START_MODE_REPLACE)
|
||||
.await
|
||||
.context("could not start unit")?;
|
||||
}
|
||||
ServiceSetupDialogMsg::RestartService => {
|
||||
self.unit_proxy.restart(START_MODE_REPLACE).await?;
|
||||
}
|
||||
ServiceSetupDialogMsg::StopService => {
|
||||
if self.autostart_on_stop.value() {
|
||||
self.manager_proxy
|
||||
.disable_unit_files(&[UNIT_NAME], false)
|
||||
.await
|
||||
.context("could not disable unit")?;
|
||||
}
|
||||
|
||||
self.unit_proxy.stop(START_MODE_REPLACE).await?;
|
||||
}
|
||||
ServiceSetupDialogMsg::Close => {
|
||||
|
||||
@@ -3,13 +3,13 @@ use anyhow::{Context, bail};
|
||||
use relm4::tokio::process::Command;
|
||||
use zbus::{proxy, zvariant::OwnedObjectPath};
|
||||
|
||||
const UNIT_NAME: &str = "lactd.service";
|
||||
pub const UNIT_NAME: &str = "lactd.service";
|
||||
|
||||
pub const UNIT_STATE_ACTIVE: &str = "active";
|
||||
|
||||
pub const START_MODE_REPLACE: &str = "replace";
|
||||
|
||||
pub async fn connect_unit_proxy() -> anyhow::Result<UnitProxy<'static>> {
|
||||
pub async fn connect_unit_proxy() -> anyhow::Result<(ManagerProxy<'static>, UnitProxy<'static>)> {
|
||||
let conn = zbus::Connection::system()
|
||||
.await
|
||||
.context("Could not establish DBus connection")?;
|
||||
@@ -19,7 +19,7 @@ pub async fn connect_unit_proxy() -> anyhow::Result<UnitProxy<'static>> {
|
||||
.context("Could not connect to systemd manager interface")?;
|
||||
|
||||
let path = manager
|
||||
.get_unit(UNIT_NAME)
|
||||
.load_unit(UNIT_NAME)
|
||||
.await
|
||||
.context("Could not get lact systemd unit")?;
|
||||
|
||||
@@ -29,7 +29,7 @@ pub async fn connect_unit_proxy() -> anyhow::Result<UnitProxy<'static>> {
|
||||
.await
|
||||
.context("Could not connect to systemd unit interface")?;
|
||||
|
||||
Ok(unit)
|
||||
Ok((manager, unit))
|
||||
}
|
||||
|
||||
#[proxy(
|
||||
@@ -39,7 +39,7 @@ pub async fn connect_unit_proxy() -> anyhow::Result<UnitProxy<'static>> {
|
||||
)]
|
||||
pub trait Manager {
|
||||
#[zbus(allow_interactive_auth)]
|
||||
fn get_unit(&self, name: &str) -> zbus::Result<OwnedObjectPath>;
|
||||
fn load_unit(&self, name: &str) -> zbus::Result<OwnedObjectPath>;
|
||||
|
||||
#[zbus(allow_interactive_auth)]
|
||||
fn enable_unit_files(
|
||||
@@ -48,6 +48,13 @@ pub trait Manager {
|
||||
runtime: bool,
|
||||
force: bool,
|
||||
) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
|
||||
|
||||
#[zbus(allow_interactive_auth)]
|
||||
fn disable_unit_files(
|
||||
&self,
|
||||
files: &[&str],
|
||||
runtime: bool,
|
||||
) -> zbus::Result<Vec<(String, String, String)>>;
|
||||
}
|
||||
|
||||
#[proxy(
|
||||
|
||||
Reference in New Issue
Block a user