Power off and restart dialogs
This commit is contained in:
parent
93d4818823
commit
bfe8d8506b
1 changed files with 120 additions and 6 deletions
126
src/greeter.rs
126
src/greeter.rs
|
|
@ -33,11 +33,14 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process,
|
process,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tokio::{net::UnixStream, time};
|
use tokio::{net::UnixStream, time};
|
||||||
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
||||||
use zbus::{dbus_proxy, Connection};
|
use zbus::{dbus_proxy, Connection};
|
||||||
|
|
||||||
|
use crate::fl;
|
||||||
|
|
||||||
#[dbus_proxy(
|
#[dbus_proxy(
|
||||||
interface = "com.system76.CosmicGreeter",
|
interface = "com.system76.CosmicGreeter",
|
||||||
default_service = "com.system76.CosmicGreeter",
|
default_service = "com.system76.CosmicGreeter",
|
||||||
|
|
@ -371,6 +374,24 @@ pub enum SocketState {
|
||||||
Error(Arc<io::Error>),
|
Error(Arc<io::Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum DialogPage {
|
||||||
|
Restart(Instant),
|
||||||
|
Shutdown(Instant),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DialogPage {
|
||||||
|
fn remaining(instant: Instant) -> Option<Duration> {
|
||||||
|
let elapsed = instant.elapsed();
|
||||||
|
let timeout = Duration::new(60, 0);
|
||||||
|
if elapsed < timeout {
|
||||||
|
Some(timeout - elapsed)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Messages that are used specifically by our [`App`].
|
/// Messages that are used specifically by our [`App`].
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
|
|
@ -386,8 +407,13 @@ pub enum Message {
|
||||||
Auth(Arc<UnixStream>, Option<String>),
|
Auth(Arc<UnixStream>, Option<String>),
|
||||||
Login(Arc<UnixStream>),
|
Login(Arc<UnixStream>),
|
||||||
Error(Arc<UnixStream>, String),
|
Error(Arc<UnixStream>, String),
|
||||||
|
DialogCancel,
|
||||||
|
DialogConfirm,
|
||||||
Reconnect,
|
Reconnect,
|
||||||
Suspend,
|
Suspend,
|
||||||
|
Restart,
|
||||||
|
Shutdown,
|
||||||
|
Heartbeat,
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,6 +434,7 @@ pub struct App {
|
||||||
session_names: Vec<String>,
|
session_names: Vec<String>,
|
||||||
selected_session: String,
|
selected_session: String,
|
||||||
error_opt: Option<String>,
|
error_opt: Option<String>,
|
||||||
|
dialog_page_opt: Option<DialogPage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -520,6 +547,7 @@ impl cosmic::Application for App {
|
||||||
session_names,
|
session_names,
|
||||||
selected_session,
|
selected_session,
|
||||||
error_opt: None,
|
error_opt: None,
|
||||||
|
dialog_page_opt: None,
|
||||||
};
|
};
|
||||||
let command = app.update(Message::Reconnect);
|
let command = app.update(Message::Reconnect);
|
||||||
(app, command)
|
(app, command)
|
||||||
|
|
@ -707,6 +735,44 @@ impl cosmic::Application for App {
|
||||||
|x| x,
|
|x| x,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Message::DialogCancel => {
|
||||||
|
self.dialog_page_opt = None;
|
||||||
|
}
|
||||||
|
Message::DialogConfirm => {
|
||||||
|
match self.dialog_page_opt.take() {
|
||||||
|
Some(DialogPage::Restart(_)) => {
|
||||||
|
#[cfg(feature = "logind")]
|
||||||
|
return Command::perform(
|
||||||
|
async move {
|
||||||
|
match crate::logind::reboot().await {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("failed to reboot: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message::none()
|
||||||
|
},
|
||||||
|
|x| x,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Some(DialogPage::Shutdown(_)) => {
|
||||||
|
#[cfg(feature = "logind")]
|
||||||
|
return Command::perform(
|
||||||
|
async move {
|
||||||
|
match crate::logind::power_off().await {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("failed to power off: {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message::none()
|
||||||
|
},
|
||||||
|
|x| x,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::Suspend => {
|
Message::Suspend => {
|
||||||
#[cfg(feature = "logind")]
|
#[cfg(feature = "logind")]
|
||||||
return Command::perform(
|
return Command::perform(
|
||||||
|
|
@ -722,6 +788,22 @@ impl cosmic::Application for App {
|
||||||
|x| x,
|
|x| x,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Message::Restart => {
|
||||||
|
self.dialog_page_opt = Some(DialogPage::Restart(Instant::now()));
|
||||||
|
}
|
||||||
|
Message::Shutdown => {
|
||||||
|
self.dialog_page_opt = Some(DialogPage::Shutdown(Instant::now()));
|
||||||
|
}
|
||||||
|
Message::Heartbeat => {
|
||||||
|
match self.dialog_page_opt {
|
||||||
|
Some(DialogPage::Restart(instant)) | Some(DialogPage::Shutdown(instant)) => {
|
||||||
|
if DialogPage::remaining(instant).is_none() {
|
||||||
|
return self.update(Message::DialogConfirm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::Exit => {
|
Message::Exit => {
|
||||||
let mut commands = Vec::new();
|
let mut commands = Vec::new();
|
||||||
for (_output, surface_id) in self.surface_ids.drain() {
|
for (_output, surface_id) in self.surface_ids.drain() {
|
||||||
|
|
@ -800,10 +882,10 @@ impl cosmic::Application for App {
|
||||||
.on_press(Message::Suspend),
|
.on_press(Message::Suspend),
|
||||||
widget::button(widget::icon::from_name("system-reboot-symbolic"))
|
widget::button(widget::icon::from_name("system-reboot-symbolic"))
|
||||||
.padding(12.0)
|
.padding(12.0)
|
||||||
.on_press(Message::None),
|
.on_press(Message::Restart),
|
||||||
widget::button(widget::icon::from_name("system-shutdown-symbolic"))
|
widget::button(widget::icon::from_name("system-shutdown-symbolic"))
|
||||||
.padding(12.0)
|
.padding(12.0)
|
||||||
.on_press(Message::None),
|
.on_press(Message::Shutdown),
|
||||||
]
|
]
|
||||||
.padding([16.0, 0.0, 0.0, 0.0])
|
.padding([16.0, 0.0, 0.0, 0.0])
|
||||||
.spacing(8.0);
|
.spacing(8.0);
|
||||||
|
|
@ -986,7 +1068,7 @@ impl cosmic::Application for App {
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::image_container::ImageContainer::new(
|
let content = crate::image_container::ImageContainer::new(
|
||||||
widget::container(
|
widget::container(
|
||||||
widget::layer_container(
|
widget::layer_container(
|
||||||
iced::widget::row![left_element, right_element]
|
iced::widget::row![left_element, right_element]
|
||||||
|
|
@ -1018,8 +1100,40 @@ impl cosmic::Application for App {
|
||||||
Some(some) => some.clone(),
|
Some(some) => some.clone(),
|
||||||
None => self.flags.fallback_background.clone(),
|
None => self.flags.fallback_background.clone(),
|
||||||
})
|
})
|
||||||
.content_fit(iced::ContentFit::Cover)
|
.content_fit(iced::ContentFit::Cover);
|
||||||
.into()
|
|
||||||
|
let popover = widget::popover(content).modal(true);
|
||||||
|
match self.dialog_page_opt {
|
||||||
|
Some(DialogPage::Restart(instant)) => {
|
||||||
|
let remaining = DialogPage::remaining(instant).unwrap_or_default();
|
||||||
|
popover
|
||||||
|
.popup(
|
||||||
|
widget::dialog(fl!("restart-now"))
|
||||||
|
.icon(widget::icon::from_name("system-restart-symbolic").size(64))
|
||||||
|
.body(fl!("restart-timeout", seconds = remaining.as_secs()))
|
||||||
|
.primary_action(widget::button::suggested(fl!("restart")).on_press(Message::DialogConfirm))
|
||||||
|
.secondary_action(
|
||||||
|
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
},
|
||||||
|
Some(DialogPage::Shutdown(instant)) => {
|
||||||
|
let remaining = DialogPage::remaining(instant).unwrap_or_default();
|
||||||
|
popover
|
||||||
|
.popup(
|
||||||
|
widget::dialog(fl!("shutdown-now"))
|
||||||
|
.icon(widget::icon::from_name("system-shutdown-symbolic").size(64))
|
||||||
|
.body(fl!("shutdown-timeout", seconds = remaining.as_secs()))
|
||||||
|
.primary_action(widget::button::suggested(fl!("shutdown")).on_press(Message::DialogConfirm))
|
||||||
|
.secondary_action(
|
||||||
|
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
},
|
||||||
|
None => popover.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
fn subscription(&self) -> Subscription<Self::Message> {
|
||||||
|
|
@ -1064,7 +1178,7 @@ impl cosmic::Application for App {
|
||||||
loop {
|
loop {
|
||||||
// Send heartbeat once a second to update time
|
// Send heartbeat once a second to update time
|
||||||
//TODO: only send this when needed
|
//TODO: only send this when needed
|
||||||
msg_tx.send(Message::None).await.unwrap();
|
msg_tx.send(Message::Heartbeat).await.unwrap();
|
||||||
time::sleep(time::Duration::new(1, 0)).await;
|
time::sleep(time::Duration::new(1, 0)).await;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue