diff --git a/examples/download_progress/src/main.rs b/examples/download_progress/src/main.rs index 8f59f1dc28..cc7a78006c 100644 --- a/examples/download_progress/src/main.rs +++ b/examples/download_progress/src/main.rs @@ -52,7 +52,7 @@ impl Example { let task = download.start(); - task.map(move |update| Message::DownloadUpdated(index, update)) + task.map_with(index, Message::DownloadUpdated) } Message::DownloadUpdated(id, update) => { if let Some(download) = diff --git a/examples/gallery/src/main.rs b/examples/gallery/src/main.rs index ab22679d92..441ad9245f 100644 --- a/examples/gallery/src/main.rs +++ b/examples/gallery/src/main.rs @@ -94,17 +94,15 @@ impl Gallery { return Task::none(); }; - Task::batch(vec![ - Task::perform( + Task::batch([ + Task::future( image.clone().blurhash(Preview::WIDTH, Preview::HEIGHT), - move |result| Message::BlurhashDecoded(id, result), - ), - Task::perform( - image.download(Size::Thumbnail { - width: Preview::WIDTH, - }), - move |result| Message::ThumbnailDownloaded(id, result), - ), + ) + .map_with(id, Message::BlurhashDecoded), + Task::future(image.download(Size::Thumbnail { + width: Preview::WIDTH, + })) + .map_with(id, Message::ThumbnailDownloaded), ]) } Message::ImageDownloaded(Ok(rgba)) => { diff --git a/futures/src/lib.rs b/futures/src/lib.rs index a874a6184c..317388234d 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -15,6 +15,7 @@ pub mod backend; pub mod event; pub mod executor; pub mod keyboard; +pub mod stream; pub mod subscription; pub use executor::Executor; diff --git a/runtime/src/task.rs b/runtime/src/task.rs index bfc36d75e0..1a1ef6990f 100644 --- a/runtime/src/task.rs +++ b/runtime/src/task.rs @@ -98,6 +98,50 @@ impl Task { self.then(move |output| Task::done(f(output))) } + /// Combines a prefix value with the result of the [`Task`] using + /// the provided closure. + /// + /// Sometimes you will want to identify the source or target + /// of some [`Task`] in your UI. This can be achieved through + /// normal means by using [`map`]: + /// + /// ```rust + /// # use iced_runtime::Task; + /// # let task = Task::none(); + /// # enum Message { TaskCompleted(u32, ()) } + /// let id = 123; + /// + /// # let _ = { + /// task.map(move |result| Message::TaskCompleted(id, result)) + /// # }; + /// ``` + /// + /// Quite a mouthful. [`map_with`] lets you write: + /// + /// ```rust + /// # use iced_runtime::Task; + /// # let task = Task::none(); + /// # enum Message { TaskCompleted(u32, ()) } + /// # let id = 123; + /// # let _ = { + /// task.map_with(id, Message::TaskCompleted) + /// # }; + /// ``` + /// + /// Much nicer! + pub fn map_with( + self, + prefix: P, + mut f: impl FnMut(P, T) -> O + MaybeSend + 'static, + ) -> Task + where + T: MaybeSend + 'static, + P: MaybeSend + Clone + 'static, + O: MaybeSend + 'static, + { + self.map(move |result| f(prefix.clone(), result)) + } + /// Performs a new [`Task`] for every output of the current [`Task`] using the /// given closure. /// diff --git a/src/lib.rs b/src/lib.rs index 79992a3e04..e4649938af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -478,6 +478,7 @@ use iced_winit::core; use iced_winit::runtime; pub use iced_futures::futures; +pub use iced_futures::stream; #[cfg(feature = "highlighter")] pub use iced_highlighter as highlighter;