diff options
Diffstat (limited to 'examples/download_progress/src/download.rs')
| -rw-r--r-- | examples/download_progress/src/download.rs | 142 | 
1 files changed, 55 insertions, 87 deletions
| diff --git a/examples/download_progress/src/download.rs b/examples/download_progress/src/download.rs index 08805f13..7db1206b 100644 --- a/examples/download_progress/src/download.rs +++ b/examples/download_progress/src/download.rs @@ -1,111 +1,79 @@ -use iced_futures::futures; -use std::hash::{Hash, Hasher}; +use iced_native::subscription; + +use std::hash::Hash;  // Just a little utility function -pub fn file<I: 'static + Hash + Copy + Send, T: ToString>( +pub fn file<I: 'static + Hash + Copy + Send + Sync, T: ToString>(      id: I,      url: T,  ) -> iced::Subscription<(I, Progress)> { -    iced::Subscription::from_recipe(Download { -        id, -        url: url.to_string(), +    subscription::unfold(id, State::Ready(url.to_string()), move |state| { +        download(id, state)      })  } +#[derive(Debug, Hash, Clone)]  pub struct Download<I> {      id: I,      url: String,  } -// Make sure iced can use our download stream -impl<H, I, T> iced_native::subscription::Recipe<H, I> for Download<T> -where -    T: 'static + Hash + Copy + Send, -    H: Hasher, -{ -    type Output = (T, Progress); - -    fn hash(&self, state: &mut H) { -        struct Marker; -        std::any::TypeId::of::<Marker>().hash(state); - -        self.id.hash(state); -    } +async fn download<I: Copy>( +    id: I, +    state: State, +) -> (Option<(I, Progress)>, State) { +    match state { +        State::Ready(url) => { +            let response = reqwest::get(&url).await; -    fn stream( -        self: Box<Self>, -        _input: futures::stream::BoxStream<'static, I>, -    ) -> futures::stream::BoxStream<'static, Self::Output> { -        let id = self.id; +            match response { +                Ok(response) => { +                    if let Some(total) = response.content_length() { +                        ( +                            Some((id, Progress::Started)), +                            State::Downloading { +                                response, +                                total, +                                downloaded: 0, +                            }, +                        ) +                    } else { +                        (Some((id, Progress::Errored)), State::Finished) +                    } +                } +                Err(_) => (Some((id, Progress::Errored)), State::Finished), +            } +        } +        State::Downloading { +            mut response, +            total, +            downloaded, +        } => match response.chunk().await { +            Ok(Some(chunk)) => { +                let downloaded = downloaded + chunk.len() as u64; -        Box::pin(futures::stream::unfold( -            State::Ready(self.url), -            move |state| async move { -                match state { -                    State::Ready(url) => { -                        let response = reqwest::get(&url).await; +                let percentage = (downloaded as f32 / total as f32) * 100.0; -                        match response { -                            Ok(response) => { -                                if let Some(total) = response.content_length() { -                                    Some(( -                                        (id, Progress::Started), -                                        State::Downloading { -                                            response, -                                            total, -                                            downloaded: 0, -                                        }, -                                    )) -                                } else { -                                    Some(( -                                        (id, Progress::Errored), -                                        State::Finished, -                                    )) -                                } -                            } -                            Err(_) => { -                                Some(((id, Progress::Errored), State::Finished)) -                            } -                        } -                    } +                ( +                    Some((id, Progress::Advanced(percentage))),                      State::Downloading { -                        mut response, +                        response,                          total,                          downloaded, -                    } => match response.chunk().await { -                        Ok(Some(chunk)) => { -                            let downloaded = downloaded + chunk.len() as u64; - -                            let percentage = -                                (downloaded as f32 / total as f32) * 100.0; - -                            Some(( -                                (id, Progress::Advanced(percentage)), -                                State::Downloading { -                                    response, -                                    total, -                                    downloaded, -                                }, -                            )) -                        } -                        Ok(None) => { -                            Some(((id, Progress::Finished), State::Finished)) -                        } -                        Err(_) => { -                            Some(((id, Progress::Errored), State::Finished)) -                        }                      }, -                    State::Finished => { -                        // We do not let the stream die, as it would start a -                        // new download repeatedly if the user is not careful -                        // in case of errors. -                        let _: () = iced::futures::future::pending().await; +                ) +            } +            Ok(None) => (Some((id, Progress::Finished)), State::Finished), +            Err(_) => (Some((id, Progress::Errored)), State::Finished), +        }, +        State::Finished => { +            // We do not let the stream die, as it would start a +            // new download repeatedly if the user is not careful +            // in case of errors. +            let _: () = iced::futures::future::pending().await; -                        None -                    } -                } -            }, -        )) +            unreachable!() +        }      }  } | 
