Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel page loading when page is closed #8

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/cancelled.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::{error, fmt};

/// Indicates that the user cancelled the operation.
#[derive(Debug)]
pub struct Cancelled;

impl fmt::Display for Cancelled {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Task cancelled")
}
}

impl error::Error for Cancelled {}
64 changes: 33 additions & 31 deletions src/document.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{future::Future, pin::Pin};
use std::pin::Pin;

use anyhow::{ensure, Result};
use futures_util::{join, Stream, StreamExt};
Expand All @@ -10,7 +10,7 @@ use gtk::{
};
use gtk_source::{prelude::*, subclass::prelude::*};

use crate::utils;
use crate::{cancelled::Cancelled, utils};

/// Unmarks the document as busy on drop.
struct MarkBusyGuard<'a> {
Expand All @@ -29,7 +29,10 @@ const FILE_SAVER_FLAGS: gtk_source::FileSaverFlags =
.union(gtk_source::FileSaverFlags::IGNORE_MODIFICATION_TIME);

mod imp {
use std::{cell::Cell, marker::PhantomData};
use std::{
cell::{Cell, RefCell},
marker::PhantomData,
};

use glib::subclass::Signal;
use once_cell::sync::Lazy;
Expand All @@ -51,6 +54,7 @@ mod imp {
pub(super) is_busy: Cell<bool>,

pub(super) source_file: gtk_source::File,
pub(super) load_cancellable: RefCell<Option<gio::Cancellable>>,
}

#[glib::object_subclass]
Expand Down Expand Up @@ -201,9 +205,16 @@ impl Document {

let _guard = self.mark_busy();

let cancellable = gio::Cancellable::new();
imp.load_cancellable.replace(Some(cancellable.clone()));

let loader = gtk_source::FileLoader::new(self, &imp.source_file);
self.handle_file_io(loader.load_future(FILE_IO_PRIORITY))
.await?;
let (io_fut, progress_stream) = loader.load_future(FILE_IO_PRIORITY);
let (io_res, _) = join!(
gio::CancellableFuture::new(io_fut, cancellable),
self.handle_progress_stream(progress_stream)
);
io_res.map_err(|_| Cancelled)??;

self.emit_text_changed();

Expand All @@ -223,8 +234,9 @@ impl Document {
.file(&imp.source_file)
.flags(FILE_SAVER_FLAGS)
.build();
self.handle_file_io(saver.save_future(FILE_IO_PRIORITY))
.await?;
let (io_fut, progress_stream) = saver.save_future(FILE_IO_PRIORITY);
let (io_res, _) = join!(io_fut, self.handle_progress_stream(progress_stream));
io_res?;

self.set_modified(false);

Expand All @@ -245,8 +257,9 @@ impl Document {
.file(&imp.source_file)
.flags(FILE_SAVER_FLAGS)
.build();
self.handle_file_io(saver.save_future(FILE_IO_PRIORITY))
.await?;
let (io_fut, progress_stream) = saver.save_future(FILE_IO_PRIORITY);
let (io_res, _) = join!(io_fut, self.handle_progress_stream(progress_stream));
io_res?;

self.notify_file();
self.notify_title();
Expand Down Expand Up @@ -345,29 +358,18 @@ impl Document {
title_start.visible_text(&title_end).to_string()
}

#[allow(clippy::type_complexity)]
async fn handle_file_io(
async fn handle_progress_stream(
&self,
(io_fut, mut progress_stream): (
impl Future<Output = Result<(), glib::Error>>,
Pin<Box<dyn Stream<Item = (i64, i64)>>>,
),
) -> Result<()> {
let progress_fut = async {
while let Some((current_n_bytes, total_n_bytes)) = progress_stream.next().await {
let progress = if total_n_bytes == 0 || current_n_bytes > total_n_bytes {
1.0
} else {
current_n_bytes as f64 / total_n_bytes as f64
};
self.set_busy_progress(progress);
}
};

let (io_ret, _) = join!(io_fut, progress_fut);
io_ret?;

Ok(())
mut progress_stream: Pin<Box<dyn Stream<Item = (i64, i64)>>>,
) {
while let Some((current_n_bytes, total_n_bytes)) = progress_stream.next().await {
let progress = if total_n_bytes == 0 || current_n_bytes > total_n_bytes {
1.0
} else {
current_n_bytes as f64 / total_n_bytes as f64
};
self.set_busy_progress(progress);
}
}

fn update_style_scheme(&self) {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

mod about;
mod application;
mod cancelled;
mod config;
mod document;
mod drag_overlay;
Expand Down
16 changes: 2 additions & 14 deletions src/save_changes_dialog.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cell::RefCell, error, fmt, rc::Rc};
use std::{cell::RefCell, rc::Rc};

use adw::prelude::*;
use anyhow::Result;
Expand All @@ -8,24 +8,12 @@ use gtk::{
glib::{self, clone},
};

use crate::{document::Document, i18n::gettext_f, utils, window::Window};
use crate::{cancelled::Cancelled, document::Document, i18n::gettext_f, utils, window::Window};

const CANCEL_RESPONSE_ID: &str = "cancel";
const DISCARD_RESPONSE_ID: &str = "discard";
const SAVE_RESPONSE_ID: &str = "save";

/// Indicates that the user cancelled the operation.
#[derive(Debug)]
struct Cancelled;

impl fmt::Display for Cancelled {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Task cancelled")
}
}

impl error::Error for Cancelled {}

struct SaveFileItem<'a> {
document: &'a Document,
check_button: gtk::CheckButton,
Expand Down
Loading