mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-05 14:35:20 -04:00
refactor(multiverse): Use a mpsc channel to propagate status messages to the status widget
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
sync::{
|
||||
mpsc::{self, Receiver},
|
||||
Arc, Mutex,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use tokio::{spawn, task::JoinHandle, time::sleep};
|
||||
use tokio::{
|
||||
spawn,
|
||||
task::{spawn_blocking, JoinHandle},
|
||||
time::sleep,
|
||||
};
|
||||
|
||||
const MESSAGE_DURATION: Duration = Duration::from_secs(4);
|
||||
|
||||
@@ -11,32 +18,56 @@ pub struct Status {
|
||||
/// Content of the latest status message, if set.
|
||||
pub last_status_message: Arc<Mutex<Option<String>>>,
|
||||
|
||||
/// A task to automatically clear the status message in N seconds, if set.
|
||||
pub clear_status_message: Option<JoinHandle<()>>,
|
||||
message_sender: mpsc::Sender<String>,
|
||||
|
||||
_receiver_task: JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl Status {
|
||||
/// Create a new empty [`Status`] widget.
|
||||
pub fn new() -> Self {
|
||||
Self { last_status_message: Default::default(), clear_status_message: Default::default() }
|
||||
let (message_sender, receiver) = mpsc::channel();
|
||||
let last_status_message = Arc::new(Mutex::new(None));
|
||||
|
||||
let receiver_task = spawn_blocking({
|
||||
let last_status_message = last_status_message.clone();
|
||||
move || Self::receiving_task(receiver, last_status_message)
|
||||
});
|
||||
|
||||
Self { last_status_message, _receiver_task: receiver_task, message_sender }
|
||||
}
|
||||
|
||||
fn receiving_task(receiver: Receiver<String>, status_message: Arc<Mutex<Option<String>>>) {
|
||||
let mut clear_message_task: Option<JoinHandle<()>> = None;
|
||||
|
||||
while let Ok(message) = receiver.recv() {
|
||||
if let Some(task) = clear_message_task.take() {
|
||||
task.abort();
|
||||
}
|
||||
|
||||
{
|
||||
let mut status_message = status_message.lock().unwrap();
|
||||
*status_message = Some(message);
|
||||
}
|
||||
|
||||
clear_message_task = Some(spawn({
|
||||
let status_message = status_message.clone();
|
||||
|
||||
async move {
|
||||
// Clear the status message in 4 seconds.
|
||||
sleep(MESSAGE_DURATION).await;
|
||||
status_message.lock().unwrap().take();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the current status message (displayed at the bottom), for a few
|
||||
/// seconds.
|
||||
pub fn set_message(&mut self, status: String) {
|
||||
if let Some(handle) = self.clear_status_message.take() {
|
||||
// Cancel the previous task to clear the status message.
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
*self.last_status_message.lock().unwrap() = Some(status);
|
||||
|
||||
let message = self.last_status_message.clone();
|
||||
self.clear_status_message = Some(spawn(async move {
|
||||
// Clear the status message in 4 seconds.
|
||||
sleep(MESSAGE_DURATION).await;
|
||||
|
||||
*message.lock().unwrap() = None;
|
||||
}));
|
||||
pub fn set_message(&self, status: String) {
|
||||
self.message_sender.send(status).expect(
|
||||
"We should be able to send the status message since the receiver is alive \
|
||||
as long as we are alive",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user