tenho seguinte código tauri v2 rust

use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};

use tauri::{AppHandle, Emitter};
use reqwest::Client;
use tokio::fs as tokio_fs;
use tokio::io::AsyncWriteExt;
use std::time::Instant;

#[derive(Debug, Deserialize)]
struct PatchEntry {
file_name: String,
}

#[derive(Debug, Serialize, Clone)]
struct DownloadMessage {
message: String,
}

#[derive(Debug, Serialize, Clone)]
struct DownloadInfo {
current_file: usize,
total_files: usize,
file_name: String,
downloaded_bytes: u64,
total_bytes: u64,
}

fn get_exe_dir() -> PathBuf {
std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.to_path_buf()
}

// Função de leitura de patches assíncrona
async fn read_patch_file(path: &Path) -> Result<Vec, Box> {
let content = tokio_fs::read_to_string(path).await?;
let patches: Vec = serde_json::from_str(&content)?;
Ok(patches)
}

async fn download_file(
app_handle: &AppHandle,
client: &Client,
entry: PatchEntry,
download_dir: &Path,
current_file: usize,
total_files: usize,
) -> Result<(), Box> {
let url = format!("https://hil-speed.hetzner.com/{}", entry.file_name);
let file_path = download_dir.join(&entry.file_name);


let mut response = client.get(&url).send().await?;
let total_bytes = response.content_length().unwrap_or(0);
let mut file = tokio_fs::OpenOptions::new()
    .write(true)
    .create(true)
    .open(file_path)
    .await?;

let mut downloaded_bytes = 0;
let start_time = Instant::now();

while let Some(chunk) = response.chunk().await? {
    file.write_all(&chunk).await?;
    downloaded_bytes += chunk.len() as u64;

    let elapsed_time = Instant::now().duration_since(start_time).as_secs_f64();
    let speed = if elapsed_time > 0.0 {
        downloaded_bytes as f64 / elapsed_time
    } else {
        0.0
    };

    app_handle.emit("download_message", DownloadMessage { message: "Baixando".to_string() })?;
    app_handle.emit("download_info", DownloadInfo {
        current_file,
        total_files,
        file_name: entry.file_name.clone(),
        downloaded_bytes,
        total_bytes,
    })?;
    app_handle.emit("download_speed", speed)?;
}

app_handle.emit("download_message", DownloadMessage { message: "Download concluído".to_string() })?;
Ok(())
}

async fn check_server_connection(client: &Client, url: &str) -> Result<(), Box> {
let response = client.get(url).send().await?;
if response.status().is_success() {
Ok(())
} else {
Err("Failed to connect to the server".into())
}
}

#[tauri::command]
pub async fn start_downloads(app_handle: AppHandle) -> Result<(), String> {
let exe_dir = get_exe_dir();
let patch_file_path = exe_dir.join("patch.json");
let download_dir = exe_dir.join("patchs");


if !download_dir.exists() {
    tokio_fs::create_dir_all(&download_dir).await.map_err(|e| e.to_string())?;
}

let patches = read_patch_file(&patch_file_path).await.map_err(|e| e.to_string())?;
let client = Client::new();
let total_files = patches.len();

app_handle.emit("download_message", DownloadMessage {
    message: "Conectando ao servidor...".to_string(),
}).map_err(|e| e.to_string())?;

let server_url = "https://hil-speed.hetzner.com/";
if let Err(err) = check_server_connection(&client, server_url).await {
    app_handle.emit("download_message", DownloadMessage {
        message: format!("Erro ao conectar ao servidor: {}", err),
    }).map_err(|e| e.to_string())?;
    return Err(format!("Erro ao conectar ao servidor: {}", err));
}

app_handle.emit("download_message", DownloadMessage {
    message: "Conexão estabelecida com sucesso. Iniciando download...".to_string(),
}).map_err(|e| e.to_string())?;

// Executando downloads sequencialmente
for (current_file, entry) in patches.into_iter().enumerate() {
    let current_file = current_file + 1; // Índice baseado em 1
    if let Err(err) = download_file(&app_handle, &client, entry, &download_dir, current_file, total_files).await {
        eprintln!("Erro ao baixar arquivo: {}", err);
        app_handle.emit("download_message", DownloadMessage {
            message: format!("Erro ao baixar arquivo: {}", err),
        }).map_err(|e| e.to_string())?;
    }
}

Ok(())
}

o while de download_file está travando o app, qual melhor forma de resolver isso ?