tenho seguinte código rust

libs.rs

mod log_app;
mod tray;
mod settings;
mod download;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init())
        .plugin(log_app::init_log_plugin().build())
        .setup(|app| {
            #[cfg(all(desktop))]
            {
                let handle = app.handle();
                tray::create_tray(handle)?;
                log::info!(target: "TrayIcon", "Aplicação configurada com sucesso!");
            }
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![download::start_downloads])
        .run(tauri::generate_context!())
        .expect("error while running application");
}

download.rs

use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use tauri::{AppHandle, Emitter};
use reqwest::{Client, Response};
use tokio::{
    fs::{self, File},
    io::AsyncWriteExt,
    time::{Duration, Instant},
};
use crate::settings::{read_rtales_config, write_rtales_config, RTalesConfig, Settings};

#[derive(Deserialize, Clone)]
struct PatchEntry {
    version: usize,
    file_name: String,
}

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

#[derive(Serialize, Clone)]
struct DownloadStatus {
    status: String,
    additional_info: Option<String>,
}

const SERVER_URL: &str = "https://hil-speed.hetzner.com/";
const EMIT_INTERVAL: Duration = Duration::from_millis(100);
const RECONNECT_DELAY: Duration = Duration::from_secs(15);

fn get_exe_dir() -> Result<PathBuf, std::io::Error> {
    std::env::current_exe()?.parent().map(|p| p.to_path_buf()).ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "Failed to get executable directory"))
}

async fn emit_download_status(app_handle: &AppHandle, status: &str, additional_info: Option<String>, ) -> Result<(), String> {
    app_handle.emit("download_status", DownloadStatus { status: status.to_string(), additional_info, },).map_err(|e| e.to_string())
}

async fn download_file(app_handle: &AppHandle, client: &Client, entry: &PatchEntry, download_dir: &Path, current_file: usize, total_files: usize,) -> Result<(), String> {
    let file_path = download_dir.join(&entry.file_name);

    loop {
        let url = format!("{}{}", SERVER_URL, entry.file_name);
        match client.get(&url).send().await {
            Ok(resp) if resp.status().is_success() => {
                process_download(app_handle, resp, &file_path, entry, current_file, total_files, ).await?;
                break;
            }
            Ok(resp) => {
                return Err(format!("Failed to download '{}': HTTP {}", entry.file_name, resp.status()));
            }
            Err(_) => {
                retry_connection(app_handle, client).await?;
            }
        }
    }

    Ok(())
}

async fn process_download( app_handle: &AppHandle, mut response: Response, file_path: &Path, entry: &PatchEntry, current_file: usize, total_files: usize,
) -> Result<(), String> {
    let total_bytes = response.content_length().unwrap_or(0);

    if file_path.exists() {
        fs::remove_file(&file_path).await.map_err(|e| e.to_string())?;
    }

    let mut file = File::create(&file_path).await.map_err(|e| e.to_string())?;

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

    emit_download_status(app_handle, "Downloading", None).await?;

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

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

            app_handle.emit( "download_info", DownloadInfo { current_file, total_files, file_name: entry.file_name.clone(), downloaded_bytes, total_bytes, speed,},).map_err(|e| e.to_string())?;
            last_emit_time = now;
        }
    }

    Ok(())
}

async fn retry_connection(app_handle: &AppHandle, client: &Client) -> Result<(), String> {
    let mut countdown = RECONNECT_DELAY.as_secs();
    while countdown > 0 {
        emit_download_status(app_handle, "Reconnecting", Some(countdown.to_string()),).await?;
        tokio::time::sleep(Duration::from_secs(1)).await;
        countdown -= 1;
    }

    emit_download_status(app_handle, "Reconnecting", None).await?;
    check_server_connection(client, SERVER_URL).await
}

async fn check_server_connection(client: &Client, url: &str) -> Result<(), String> {
    let response = client.get(url).send().await.map_err(|e| e.to_string())?;
    if response.status().is_success() {
        Ok(())
    } else {
        Err(format!(
            "Failed to connect to server: HTTP {}",
            response.status()
        ))
    }
}

#[tauri::command]
pub async fn start_downloads(app_handle: AppHandle) -> Result<(), String> {
    let exe_dir = get_exe_dir().map_err(|e| e.to_string())?;

    let patch_file_path = exe_dir.join("patch.json");
    let rtales_config_path = exe_dir.join("rTales.json");
    let download_dir = exe_dir.join("patches");

    let mut rtales_config = read_rtales_config(&rtales_config_path).await.unwrap_or_else(|_| RTalesConfig { settings: Settings { patch_version: 0 }, });

    let last_patch_version = rtales_config.settings.patch_version;
    let patch_content = fs::read_to_string(&patch_file_path).await.map_err(|e| e.to_string())?;
    let patches: Vec<PatchEntry> = serde_json::from_str(&patch_content).map_err(|e| e.to_string())?;
    let latest_version = patches.iter().map(|p| p.version).max().unwrap_or(0);

    if latest_version <= last_patch_version {
        emit_download_status(&app_handle, "Completed", None).await?;
        return Ok(());
    }

    fs::create_dir_all(&download_dir).await.map_err(|e| e.to_string())?;

    let patches_to_download: Vec<&PatchEntry> = patches.iter().filter(|entry| entry.version > last_patch_version).collect();
    let total_files = patches_to_download.len();

    let client = Client::new();

    emit_download_status(&app_handle, "Connecting", None).await?;

    if let Err(err) = check_server_connection(&client, SERVER_URL).await {
        emit_download_status(&app_handle, "Error", Some(err.clone())).await?;
        return Err(err);
    }

    emit_download_status(&app_handle, "Connected", None).await?;

    for (idx, entry) in patches_to_download.iter().enumerate() {
        let current_file = idx + 1;

        if let Err(err) = download_file(&app_handle, &client, entry, &download_dir, current_file, total_files,).await
        {
            emit_download_status(&app_handle, "Error", Some(err.clone())).await?;
            return Err(err);
        }
    }

    rtales_config.settings.patch_version = latest_version;
    write_rtales_config(&rtales_config_path, &rtales_config).await.map_err(|e| e.to_string())?;

    emit_download_status(&app_handle, "Completed", None).await?;

    Ok(())
}

No react eu tenho

import { useEffect, useState } from "react";
import { listen } from "@tauri-apps/api/event";
import { invoke } from "@tauri-apps/api/core";
import { getCurrentWindow, ProgressBarStatus } from "@tauri-apps/api/window";

function formatBytes(bytes: number) {
  if (bytes === 0) return "0 B";
  const k = 1024;
  const units = ["B", "KB", "MB", "GB", "TB", "PB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  const value = bytes / Math.pow(k, i);
  return `${value.toFixed(2)} ${units[i]}`;
}

enum DownloadStatusType {
  Connecting = "Connecting",
  Connected = "Connected",
  Reconnecting = "Reconnecting",
  Start = "Start",
  Downloading = "Downloading",
  Completed = "Completed",
  Error = "Error",
}

interface DownloadStatus {
  status: DownloadStatusType;
  additional_info?: string;
}

interface DownloadInfo {
  current_file: number;
  total_files: number;
  file_name: string;
  downloaded_bytes: number;
  total_bytes: number;
  speed: number;
}

const DownloadManager = () => {
  const [message, setMessage] = useState("");
  const [messageColor, setMessageColor] = useState("text-white");
  const [currentFile, setCurrentFile] = useState(0);
  const [totalFiles, setTotalFiles] = useState(0);
  const [fileName, setFileName] = useState("");
  const [downloadedBytes, setDownloadedBytes] = useState(0);
  const [totalBytes, setTotalBytes] = useState(0);
  const [downloadSpeed, setDownloadSpeed] = useState(0);
  const [isDownloading, setIsDownloading] = useState(false);

  // Memoized function to update the progress bar
  const updateProgressBar = async () => {
    try {
      const window = getCurrentWindow();
      if (isDownloading && downloadedBytes > 0 && totalBytes > 0) {
        const progressPercent = Math.floor((downloadedBytes / totalBytes) * 100);
        await window.setProgressBar({
          status: ProgressBarStatus.Normal,
          progress: progressPercent,
        });
      } else {
        await window.setProgressBar({
          status: ProgressBarStatus.None,
          progress: 0,
        });
      }
    } catch (error) {
      // Handle error if needed
      console.error("Failed to update progress bar:", error);
    }
  };

  useEffect(() => {
    updateProgressBar();
  }, [updateProgressBar]);

  useEffect(() => {
    let unlistenStatus: () => void;
    let unlistenInfo: () => void;

    const setupListeners = async () => {
      try {
        unlistenStatus = await listen<DownloadStatus>(
          "download_status",
          (event) => {
            const { status, additional_info } = event.payload;

            let newMessage = "";
            let newMessageColor = "text-white";

            switch (status) {
              case DownloadStatusType.Connecting:
                newMessage = "Conectando ao servidor...";
                break;
              case DownloadStatusType.Connected:
                newMessage = "Conexão estabelecida com sucesso";
                break;
              case DownloadStatusType.Reconnecting:
                newMessage = additional_info ? `Reconectando em ${additional_info} segundos...` : "Reconectando...";
                newMessageColor = "text-red-500";
                break;
              case DownloadStatusType.Start:
                newMessage = "Iniciando download...";
                break;
              case DownloadStatusType.Downloading:
                newMessage = "Baixando arquivo";
                break;
              case DownloadStatusType.Completed:
                newMessage = "Atualização do cliente concluída com sucesso";
                newMessageColor = "text-green-400";
                break;
              case DownloadStatusType.Error:
                newMessage = `Erro: ${additional_info}`;
                newMessageColor = "text-red-500";
                break;
              default:
                newMessage = "Status desconhecido";
            }

            setMessage(newMessage);
            setMessageColor(newMessageColor);

            setIsDownloading(status === DownloadStatusType.Downloading);
          }
        );

        unlistenInfo = await listen<DownloadInfo>(
          "download_info",
          (event) => {
            const {
              current_file,
              total_files,
              file_name,
              downloaded_bytes,
              total_bytes,
              speed,
            } = event.payload;

            setCurrentFile(current_file);
            setTotalFiles(total_files);
            setFileName(file_name);
            setDownloadedBytes(downloaded_bytes);
            setTotalBytes(total_bytes);
            setDownloadSpeed(speed);
          }
        );
      } catch (error) {
        // Handle error if needed
      }
    };

    setupListeners();
	startDownload();

    return () => {
      if (unlistenStatus) unlistenStatus();
      if (unlistenInfo) unlistenInfo();
    };
  }, []);

  const startDownload = async () => {
    if (isDownloading)
      return;

    // Reset state
    setMessage("");
    setMessageColor("text-white");
    setCurrentFile(0);
    setTotalFiles(0);
    setFileName("");
    setDownloadedBytes(0);
    setTotalBytes(0);
    setDownloadSpeed(0);

    try {
      await invoke("start_downloads");
    } catch (error) {
      setMessage(`Erro ao iniciar o download: ${error}`);
      setMessageColor("text-red-500");
      setIsDownloading(false);
    }
  };

  const progressPercent = downloadedBytes > 0 && totalBytes > 0 ? (downloadedBytes / totalBytes) * 100 : 0;

  return (
    <>
      <div className="absolute bottom-20 rounded-lg w-[71%] h-[8%] flex flex-col justify-between items-center">
      </div>
      <div className="absolute bottom-3 rounded-lg w-[71%] h-[8%] flex flex-col justify-between items-center">
        <div className="w-full flex items-center">
          <p className="text-[12px] font-bold text-opacity-[0.95] text-white flex-grow text-center tracking-wider antialiased">
            <span className={messageColor}>{message}</span>
            {isDownloading && totalFiles > 0 && downloadedBytes > 0 && totalBytes > 0 && (
                <>
                  <span className="mx-1">
                    (
                    <span className="text-blue-400">{currentFile}</span>{' / '}
                    {totalFiles})
                  </span>
                  : <span className="text-orange-500">{fileName}</span>
                  <span className="mx-1">
                    (
                    <span className="text-green-600">
                      {formatBytes(downloadedBytes)}
                    </span>{" "}
                    / {formatBytes(totalBytes)})
                  </span>
                </>
              )}
          </p>
        </div>
        {isDownloading && totalFiles > 0 && downloadedBytes > 0 && totalBytes > 0 && (
            <div className="w-[30%] absolute h-6 flex justify-end items-center right-6 top-2">
              <span className="text-[11px] font-bold text-opacity-[0.95] text-yellow-600 text-right">
                {formatBytes(downloadSpeed)}ps
              </span>
            </div>
          )}
        <div className="w-[95%] bg-[#0E1622]/[0.95] rounded-lg h-6 flex items-center">
          <div
            className="bg-gradient-to-r from-[#1164CA]/[0.95] to-cyan-500 mx-1 rounded-md h-4 shadow-[0_0_5px_#00BFFF,inset_0_0_5px_#00BFFF]"
            style={{ width: `${progressPercent}%` }}
          />
        </div>
      </div>
    </>
  );
};

export default DownloadManager;


Quando startDownload é executado, o downloadedBytes está bugando o valor ele fica indo para frente e voltando, eu tenho a seguinte saida de log  do downloadedBytes

Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 93028096, total_bytes: 104857600, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 93028096, totalBytes: 104857600, progress: 0.443592529296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 93028096, totalBytes: 104857600, progress: 0.443592529296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 93028096, totalBytes: 104857600, progress: 0.443592529296875, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 93634304, total_bytes: 104857600, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 93634304, total_bytes: 104857600, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 93634304, totalBytes: 104857600, progress: 0.446483154296875, …}currentFile: 1downloadedBytes: 93634304percent: 44.6483154296875progress: 0.446483154296875totalBytes: 104857600totalFiles: 2[[Prototype]]: Object
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 93634304, totalBytes: 104857600, progress: 0.446483154296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 93634304, totalBytes: 104857600, progress: 0.446483154296875, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 96567040, total_bytes: 104857600, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 96567040, total_bytes: 104857600, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 96567040, totalBytes: 104857600, progress: 0.460467529296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 96567040, totalBytes: 104857600, progress: 0.460467529296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 96567040, totalBytes: 104857600, progress: 0.460467529296875, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 95518464, total_bytes: 104857600, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 95518464, total_bytes: 104857600, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 95518464, totalBytes: 104857600, progress: 0.455467529296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 95518464, totalBytes: 104857600, progress: 0.455467529296875, …}
DownloadFile.tsx:58 Progress Calculation: {currentFile: 1, totalFiles: 2, downloadedBytes: 95518464, totalBytes: 104857600, progress: 0.455467529296875, …}
DownloadFile.tsx:167 Received download info: {current_file: 1, total_files: 2, file_name: '100MB.bin', downloaded_bytes: 100286208, total_bytes: 104857600, …}

Como posso corrigir esse problema ?