Use Task::run in download_progress example
This commit is contained in:
parent
53b7f507f8
commit
6ccc828607
2 changed files with 44 additions and 43 deletions
|
|
@ -1,24 +1,13 @@
|
||||||
use iced::futures::{SinkExt, Stream, StreamExt};
|
use iced::futures::{SinkExt, Stream, StreamExt};
|
||||||
use iced::stream::try_channel;
|
use iced::stream::try_channel;
|
||||||
use iced::Subscription;
|
|
||||||
|
|
||||||
use std::hash::Hash;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
// Just a little utility function
|
pub fn download(
|
||||||
pub fn file<I: 'static + Hash + Copy + Send + Sync, T: ToString>(
|
url: impl AsRef<str>,
|
||||||
id: I,
|
) -> impl Stream<Item = Result<Progress, Error>> {
|
||||||
url: T,
|
|
||||||
) -> iced::Subscription<(I, Result<Progress, Error>)> {
|
|
||||||
Subscription::run_with_id(
|
|
||||||
id,
|
|
||||||
download(url.to_string()).map(move |progress| (id, progress)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn download(url: String) -> impl Stream<Item = Result<Progress, Error>> {
|
|
||||||
try_channel(1, move |mut output| async move {
|
try_channel(1, move |mut output| async move {
|
||||||
let response = reqwest::get(&url).await?;
|
let response = reqwest::get(url.as_ref()).await?;
|
||||||
let total = response.content_length().ok_or(Error::NoContentLength)?;
|
let total = response.content_length().ok_or(Error::NoContentLength)?;
|
||||||
|
|
||||||
let _ = output.send(Progress::Downloading { percent: 0.0 }).await;
|
let _ = output.send(Progress::Downloading { percent: 0.0 }).await;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
mod download;
|
mod download;
|
||||||
|
|
||||||
|
use download::download;
|
||||||
|
|
||||||
|
use iced::task;
|
||||||
use iced::widget::{button, center, column, progress_bar, text, Column};
|
use iced::widget::{button, center, column, progress_bar, text, Column};
|
||||||
use iced::{Center, Element, Right, Subscription};
|
use iced::{Center, Element, Right, Task};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
iced::application(
|
iced::application(
|
||||||
|
|
@ -9,7 +12,6 @@ pub fn main() -> iced::Result {
|
||||||
Example::update,
|
Example::update,
|
||||||
Example::view,
|
Example::view,
|
||||||
)
|
)
|
||||||
.subscription(Example::subscription)
|
|
||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,7 +25,7 @@ struct Example {
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
Add,
|
Add,
|
||||||
Download(usize),
|
Download(usize),
|
||||||
DownloadProgressed((usize, Result<download::Progress, download::Error>)),
|
DownloadProgressed(usize, Result<download::Progress, download::Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Example {
|
impl Example {
|
||||||
|
|
@ -34,32 +36,38 @@ impl Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::Add => {
|
Message::Add => {
|
||||||
self.last_id += 1;
|
self.last_id += 1;
|
||||||
|
|
||||||
self.downloads.push(Download::new(self.last_id));
|
self.downloads.push(Download::new(self.last_id));
|
||||||
|
|
||||||
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::Download(index) => {
|
Message::Download(index) => {
|
||||||
if let Some(download) = self.downloads.get_mut(index) {
|
let Some(download) = self.downloads.get_mut(index) else {
|
||||||
download.start();
|
return Task::none();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let task = download.start();
|
||||||
|
|
||||||
|
task.map(move |progress| {
|
||||||
|
Message::DownloadProgressed(index, progress)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Message::DownloadProgressed((id, progress)) => {
|
Message::DownloadProgressed(id, progress) => {
|
||||||
if let Some(download) =
|
if let Some(download) =
|
||||||
self.downloads.iter_mut().find(|download| download.id == id)
|
self.downloads.iter_mut().find(|download| download.id == id)
|
||||||
{
|
{
|
||||||
download.progress(progress);
|
download.progress(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task::none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
|
||||||
Subscription::batch(self.downloads.iter().map(Download::subscription))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
let downloads =
|
let downloads =
|
||||||
Column::with_children(self.downloads.iter().map(Download::view))
|
Column::with_children(self.downloads.iter().map(Download::view))
|
||||||
|
|
@ -90,7 +98,7 @@ struct Download {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum State {
|
enum State {
|
||||||
Idle,
|
Idle,
|
||||||
Downloading { progress: f32 },
|
Downloading { progress: f32, _task: task::Handle },
|
||||||
Finished,
|
Finished,
|
||||||
Errored,
|
Errored,
|
||||||
}
|
}
|
||||||
|
|
@ -103,14 +111,28 @@ impl Download {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self) {
|
pub fn start(
|
||||||
|
&mut self,
|
||||||
|
) -> Task<Result<download::Progress, download::Error>> {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Idle { .. }
|
State::Idle { .. }
|
||||||
| State::Finished { .. }
|
| State::Finished { .. }
|
||||||
| State::Errored { .. } => {
|
| State::Errored { .. } => {
|
||||||
self.state = State::Downloading { progress: 0.0 };
|
let (task, handle) = Task::stream(download(
|
||||||
|
"https://huggingface.co/\
|
||||||
|
mattshumer/Reflection-Llama-3.1-70B/\
|
||||||
|
resolve/main/model-00001-of-00162.safetensors",
|
||||||
|
))
|
||||||
|
.abortable();
|
||||||
|
|
||||||
|
self.state = State::Downloading {
|
||||||
|
progress: 0.0,
|
||||||
|
_task: handle.abort_on_drop(),
|
||||||
|
};
|
||||||
|
|
||||||
|
task
|
||||||
}
|
}
|
||||||
State::Downloading { .. } => {}
|
State::Downloading { .. } => Task::none(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +140,7 @@ impl Download {
|
||||||
&mut self,
|
&mut self,
|
||||||
new_progress: Result<download::Progress, download::Error>,
|
new_progress: Result<download::Progress, download::Error>,
|
||||||
) {
|
) {
|
||||||
if let State::Downloading { progress } = &mut self.state {
|
if let State::Downloading { progress, .. } = &mut self.state {
|
||||||
match new_progress {
|
match new_progress {
|
||||||
Ok(download::Progress::Downloading { percent }) => {
|
Ok(download::Progress::Downloading { percent }) => {
|
||||||
*progress = percent;
|
*progress = percent;
|
||||||
|
|
@ -133,20 +155,10 @@ impl Download {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subscription(&self) -> Subscription<Message> {
|
|
||||||
match self.state {
|
|
||||||
State::Downloading { .. } => {
|
|
||||||
download::file(self.id, "https://huggingface.co/mattshumer/Reflection-Llama-3.1-70B/resolve/main/model-00001-of-00162.safetensors")
|
|
||||||
.map(Message::DownloadProgressed)
|
|
||||||
}
|
|
||||||
_ => Subscription::none(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view(&self) -> Element<Message> {
|
pub fn view(&self) -> Element<Message> {
|
||||||
let current_progress = match &self.state {
|
let current_progress = match &self.state {
|
||||||
State::Idle { .. } => 0.0,
|
State::Idle { .. } => 0.0,
|
||||||
State::Downloading { progress } => *progress,
|
State::Downloading { progress, .. } => *progress,
|
||||||
State::Finished { .. } => 100.0,
|
State::Finished { .. } => 100.0,
|
||||||
State::Errored { .. } => 0.0,
|
State::Errored { .. } => 0.0,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue