Signaling when to Save

app.rs

There are two scenarios where we will save our tasks to a file. When the application has been closed, and every 5 seconds after the last modification. To start, lets add a signal that waits 5 seconds before sending the SyncToDisk event:


#![allow(unused)]
fn main() {
pub fn modified(&mut self) {
    if let Some(id) = self.scheduled_write.take() {
        glib::source_remove(id);
    }

    let tx = self.tx.clone();
    self.scheduled_write = Some(glib::timeout_add_local(5000, move || {
        let tx = tx.clone();
        spawn(async move {
            let _ = tx.send(Event::SyncToDisk).await;
        });

        glib::Continue(false)
    }));
}
}

glib::timeout_add_local(5000, ...) will schedule the provided closure to execute on local context after 5 seconds. This function returns an ID which we're storing in the scheduled_write property of our App. If we receive the Modified event again before the 5 seconds have passed, the previous signal will be removed and a new one registered in its place. That'll ensure that it doesn't trigger until after 5 seconds of idle keyboard time has passed.

Next will be programming the SyncToDisk event. We're simply going to collect the text from each non-empty task widget in our slotmap, and combine it into a single string to pass to the background for saving. The fomat formatter from the fomat_macros crate provides a very intuitive means to achieve this.


#![allow(unused)]
fn main() {
pub async fn sync_to_disk(&mut self) {
    self.scheduled_write = None;

    let contents = fomat_macros::fomat!(
        for node in self.tasks.values() {
            if node.entry.get_text_length() != 0 {
                (node.entry.get_text()) "\n"
            }
        }
    );

    let _ = self.btx.send(BgEvent::Save("Task".into(), contents)).await;
}
}

Finally, we can handle that Closed event that was sent when the ApplicationWindow was destroyed:


#![allow(unused)]
fn main() {
pub async fn closed(&mut self) {
    self.sync_to_disk().await;
    let _ = self.btx.send(BgEvent::Quit).await;
}
}