feat: use spinner widget from libcosmic for authentication

This commit is contained in:
Fred 2026-06-24 19:12:46 +02:00 committed by GitHub
parent b877ea6573
commit 953478f801
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 6 additions and 115 deletions

View file

@ -390,7 +390,6 @@ pub enum Message {
HighContrast(bool), HighContrast(bool),
InvertColors(bool), InvertColors(bool),
WaylandUpdate(WaylandUpdate), WaylandUpdate(WaylandUpdate),
SpinnerTick,
} }
impl From<common::Message> for Message { impl From<common::Message> for Message {
@ -420,8 +419,6 @@ pub struct App {
accessibility: Accessibility, accessibility: Accessibility,
authenticating: bool, authenticating: bool,
spinner_rotation: f32,
spinner_handle: Option<cosmic::iced::task::Handle>,
} }
#[derive(Default)] #[derive(Default)]
@ -902,14 +899,7 @@ impl App {
widget::row::with_capacity(2) widget::row::with_capacity(2)
.spacing(8.0) .spacing(8.0)
.align_y(Alignment::Center) .align_y(Alignment::Center)
.push( .push(widget::indeterminate_circular().size(16.0).bar_height(2.0))
widget::icon::from_name("process-working-symbolic")
.size(16)
.icon()
.rotation(iced::Rotation::Floating(iced::Radians(
self.spinner_rotation.to_radians(),
))),
)
.push(widget::text(fl!("authenticating"))), .push(widget::text(fl!("authenticating"))),
) )
.width(Length::Fill) .width(Length::Fill)
@ -1173,8 +1163,6 @@ impl cosmic::Application for App {
randr_list: None, randr_list: None,
surface_id_pairs: Vec::new(), surface_id_pairs: Vec::new(),
authenticating: false, authenticating: false,
spinner_rotation: 0.0,
spinner_handle: None,
}; };
(app, Task::batch(tasks)) (app, Task::batch(tasks))
} }
@ -1482,39 +1470,12 @@ impl cosmic::Application for App {
self.common.error_opt = None; self.common.error_opt = None;
self.authenticating = true; self.authenticating = true;
self.send_request(Request::PostAuthMessageResponse { response }); self.send_request(Request::PostAuthMessageResponse { response });
// Start spinner animation if not already running
if self.spinner_handle.is_none() {
let (spinner_task, handle) =
cosmic::task::stream(cosmic::iced::stream::channel(
1,
|mut msg_tx: iced::futures::channel::mpsc::Sender<_>| async move {
let mut interval = time::interval(Duration::from_millis(16)); // ~60fps
loop {
msg_tx
.send(cosmic::Action::App(Message::SpinnerTick))
.await
.unwrap();
interval.tick().await;
}
},
))
.abortable();
self.spinner_handle = Some(handle);
return spinner_task;
}
} }
Message::Login => { Message::Login => {
self.common.prompt_opt = None; self.common.prompt_opt = None;
self.common.error_opt = None; self.common.error_opt = None;
self.authenticating = false; self.authenticating = false;
// Stop spinner animation
if let Some(handle) = self.spinner_handle.take() {
handle.abort();
}
self.spinner_rotation = 0.0;
match self.flags.sessions.get(&self.selected_session).cloned() { match self.flags.sessions.get(&self.selected_session).cloned() {
Some((cmd, env)) => { Some((cmd, env)) => {
self.send_request(Request::StartSession { cmd, env }); self.send_request(Request::StartSession { cmd, env });
@ -1527,12 +1488,6 @@ impl cosmic::Application for App {
self.common.error_opt = Some(error); self.common.error_opt = Some(error);
self.authenticating = false; self.authenticating = false;
// Stop spinner animation
if let Some(handle) = self.spinner_handle.take() {
handle.abort();
}
self.spinner_rotation = 0.0;
self.send_request(Request::CancelSession); self.send_request(Request::CancelSession);
} }
Message::Reconnect => { Message::Reconnect => {
@ -1863,10 +1818,6 @@ impl cosmic::Application for App {
}; };
return reposition_subsurface(*subsurface_id, loc.x as i32, loc.y as i32); return reposition_subsurface(*subsurface_id, loc.x as i32, loc.y as i32);
} }
Message::SpinnerTick => {
// Update spinner rotation angle (360 degrees per second = 6 degrees per frame at 60fps)
self.spinner_rotation = (self.spinner_rotation + 6.0) % 360.0;
}
} }
Task::none() Task::none()
} }

View file

@ -274,7 +274,6 @@ pub enum Message {
Error(String), Error(String),
Lock, Lock,
Unlock, Unlock,
SpinnerTick,
} }
impl From<common::Message> for Message { impl From<common::Message> for Message {
@ -312,8 +311,6 @@ pub struct App {
inhibit_opt: Option<Arc<OwnedFd>>, inhibit_opt: Option<Arc<OwnedFd>>,
value_tx_opt: Option<mpsc::Sender<String>>, value_tx_opt: Option<mpsc::Sender<String>>,
authenticating: bool, authenticating: bool,
spinner_rotation: f32,
spinner_handle: Option<cosmic::iced::task::Handle>,
} }
impl App { impl App {
@ -566,14 +563,7 @@ impl App {
widget::row::with_capacity(2) widget::row::with_capacity(2)
.spacing(8.0) .spacing(8.0)
.align_y(Alignment::Center) .align_y(Alignment::Center)
.push( .push(widget::indeterminate_circular().size(16.0).bar_height(2.0))
widget::icon::from_name("process-working-symbolic")
.size(16)
.icon()
.rotation(iced::Rotation::Floating(iced::Radians(
self.spinner_rotation.to_radians(),
))),
)
.push(widget::text(fl!("authenticating"))), .push(widget::text(fl!("authenticating"))),
) )
.width(Length::Fill) .width(Length::Fill)
@ -675,8 +665,6 @@ impl cosmic::Application for App {
inhibit_opt: None, inhibit_opt: None,
value_tx_opt: None, value_tx_opt: None,
authenticating: false, authenticating: false,
spinner_rotation: 0.0,
spinner_handle: None,
}; };
let task = if cfg!(feature = "logind") { let task = if cfg!(feature = "logind") {
@ -1047,40 +1035,11 @@ impl cosmic::Application for App {
self.authenticating = true; self.authenticating = true;
match self.value_tx_opt.take() { match self.value_tx_opt.take() {
Some(value_tx) => { Some(value_tx) => {
// Start spinner animation if not already running
if self.spinner_handle.is_none() {
let (spinner_task, handle) =
cosmic::task::stream(cosmic::iced::stream::channel(
1,
|mut msg_tx: futures::channel::mpsc::Sender<_>| async move {
let mut interval =
tokio::time::interval(Duration::from_millis(16)); // ~60fps
loop {
msg_tx
.send(cosmic::Action::App(Message::SpinnerTick))
.await
.unwrap();
interval.tick().await;
}
},
))
.abortable();
self.spinner_handle = Some(handle);
return Task::batch([
spinner_task,
cosmic::task::future(async move {
value_tx.send(value).await.unwrap();
Message::Channel(value_tx)
}),
]);
} else {
return cosmic::task::future(async move { return cosmic::task::future(async move {
value_tx.send(value).await.unwrap(); value_tx.send(value).await.unwrap();
Message::Channel(value_tx) Message::Channel(value_tx)
}); });
} }
}
None => tracing::warn!("tried to submit when value_tx_opt not set"), None => tracing::warn!("tried to submit when value_tx_opt not set"),
} }
} }
@ -1098,16 +1057,6 @@ impl cosmic::Application for App {
Message::Error(error) => { Message::Error(error) => {
self.common.error_opt = Some(error); self.common.error_opt = Some(error);
self.authenticating = false; self.authenticating = false;
// Stop spinner animation
if let Some(handle) = self.spinner_handle.take() {
handle.abort();
}
self.spinner_rotation = 0.0;
}
Message::SpinnerTick => {
// Update spinner rotation angle (360 degrees per second = 6 degrees per frame at 60fps)
self.spinner_rotation = (self.spinner_rotation + 6.0) % 360.0;
} }
Message::Lock => match self.state { Message::Lock => match self.state {
State::Unlocked => { State::Unlocked => {
@ -1119,10 +1068,6 @@ impl cosmic::Application for App {
self.value_tx_opt = None; self.value_tx_opt = None;
// Reset authenticating state // Reset authenticating state
self.authenticating = false; self.authenticating = false;
if let Some(handle) = self.spinner_handle.take() {
handle.abort();
}
self.spinner_rotation = 0.0;
// Try to create lockfile when locking // Try to create lockfile when locking
if let Some(ref lockfile) = self.flags.lockfile_opt if let Some(ref lockfile) = self.flags.lockfile_opt
&& let Err(err) = fs::File::create(lockfile) && let Err(err) = fs::File::create(lockfile)
@ -1151,11 +1096,6 @@ impl cosmic::Application for App {
// Stop authenticating // Stop authenticating
self.authenticating = false; self.authenticating = false;
// Stop spinner animation
if let Some(handle) = self.spinner_handle.take() {
handle.abort();
}
self.spinner_rotation = 0.0;
// Try to delete lockfile when unlocking // Try to delete lockfile when unlocking
if let Some(ref lockfile) = self.flags.lockfile_opt if let Some(ref lockfile) = self.flags.lockfile_opt
&& let Err(err) = fs::remove_file(lockfile) && let Err(err) = fs::remove_file(lockfile)