From fff333f89ba99f32171641f0e8d78c9cdfe291b4 Mon Sep 17 00:00:00 2001 From: Songtronix Date: Mon, 23 Mar 2020 15:54:23 +0100 Subject: Add example for download with progress tracking --- examples/download_progress/src/downloader.rs | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 examples/download_progress/src/downloader.rs (limited to 'examples/download_progress/src/downloader.rs') diff --git a/examples/download_progress/src/downloader.rs b/examples/download_progress/src/downloader.rs new file mode 100644 index 00000000..62f943fd --- /dev/null +++ b/examples/download_progress/src/downloader.rs @@ -0,0 +1,99 @@ +use iced_futures::futures; + +// Just a little utility function +pub fn file(url: T) -> iced::Subscription { + iced::Subscription::from_recipe(Downloader { + url: url.to_string(), + }) +} + +pub struct Downloader { + url: String, +} + +// Make sure iced can use our download stream +impl iced_native::subscription::Recipe for Downloader +where + H: std::hash::Hasher, +{ + type Output = DownloadMessage; + + fn hash(&self, state: &mut H) { + use std::hash::Hash; + std::any::TypeId::of::().hash(state); + } + + fn stream( + self: Box, + _input: futures::stream::BoxStream<'static, I>, + ) -> futures::stream::BoxStream<'static, Self::Output> { + use isahc::prelude::*; + + Box::pin(futures::stream::unfold( + DownloadState::Ready(self.url), + |state| async move { + match state { + DownloadState::Ready(url) => { + let resp = Request::get(&url) + .metrics(true) + .body(()) + .unwrap() + .send_async() + .await + .unwrap(); + let metrics = resp.metrics().unwrap().clone(); + // If you actually want to download: + /*let file = async_std::fs::File::create("download.bin") + .await + .unwrap();*/ + + async_std::task::spawn(async_std::io::copy( + resp.into_body(), + async_std::io::sink(), //file + )); + + Some(( + DownloadMessage::DownloadStarted, + DownloadState::Downloading(metrics), + )) + } + DownloadState::Downloading(metrics) => { + async_std::task::sleep( + std::time::Duration::from_millis(100), + ) + .await; + + let percentage = metrics.download_progress().0 * 100 + / metrics.download_progress().1; + + if percentage == 100 { + Some(( + DownloadMessage::Done, + DownloadState::Finished, + )) + } else { + Some(( + DownloadMessage::Downloading(percentage), + DownloadState::Downloading(metrics), + )) + } + } + DownloadState::Finished => None, + } + }, + )) + } +} + +#[derive(Debug)] +pub enum DownloadMessage { + DownloadStarted, + Downloading(u64), + Done, +} + +pub enum DownloadState { + Ready(String), + Downloading(isahc::Metrics), + Finished, +} -- cgit