Ext JS dynamically select build profile failed

I want to know why building 2 sets of applications with different themes failed. I followed the official tutorial and run sencha app build : https://docs.sencha.com/cmd/7.8.0/guides/microloader.html#microloader_-_dynamic_manifest
But in the end, Logon.json and Logon-A.json was not automatically generated.

{
    /**
     * The toolkit to use. Select either "classic" or "modern".
     */
    "toolkit": "classic",

    /**
     * The application's namespace.
     */
    "name": "Logon",

    /**
     * Comma-separated string with the paths of directories or files to search. Any classes
     * declared in these locations will be available in your class "requires" or in calls
     * to "Ext.require". The "app.dir" variable below is expanded to the path where the
     * application resides (the same folder in which this file is located).
     */
    "classpath": "${app.dir}/app",

    /**
     * The Sencha Framework for this application: "ext" or "touch".
     */
    "framework": "ext",

    /**
     * The name of the theme for this application.
     */
    "theme": "ext-theme-neptune",
    "builds": {
        "Logon": {
                    "theme": "ext-theme-neptune"
                },
    "Logon-A": {
                    "theme": "theme-1"
                }
    }
}

<!DOCTYPE HTML>
<html manifest="">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=10, user-scalable=yes">
    <title>Logon</title>
    <script type="text/javascript">
        window.GLOBAL_CONTEXTROOT = '<%= com.SystemConfig.getContextRoot() %>';
    </script>
    <script type="text/javascript">
    var Ext = Ext || {};
    Ext.beforeLoad = function (tags) {
        var theme = location.href.match(/theme=([w-]+)/);

        theme  = (theme && theme[1]) || 'Logon';

        Ext.manifest = theme ;
        console.log(Ext.manifest);
    };
</script>


    <!-- The line below must be kept intact for Sencha Cmd to build your application -->
    <script id="microloader" type="text/javascript" src="bootstrap.js"></script>

</head>
<body></body>
</html>

How to show other info from my file JSON using JavaScript to html

I had learn some fetch for get data from file JSON but I still confused about how to get other info by click image. I have file data JSON like this. This file contain name, image, url and brand of some product

{
    "products": [
        {
            "id": "11",
            "name": "panda",
            "brand": "blue",
            "jenis": "cool panda",
            "deskripsi": "cute panda",
            "image": "a8205ca774a533e0053e6fe969443510.jpg",
            "url": "http://localhost:5000/images/a8205ca774a533e0053e6fe969443510.jpg",
            "createdAt": "2024-11-28 03:34:22",
            "updatedAt": "2024-11-29 06:37:36"
        },
        {
            "id": "13",
            "name": "fox",
            "brand": "crowd",
            "jenis": "fox samurai",
            "deskripsi": "strongest samurai",
            "image": "c87dcede772ef2d0fbdd5ceb65237937.jpg",
            "url": "http://localhost:5000/images/c87dcede772ef2d0fbdd5ceb65237937.jpg",
            "createdAt": "2024-11-28 14:12:39",
            "updatedAt": "2024-11-29 06:39:41"
        },
        {
            "id": "14",
            "name": "panda",
            "brand": "digital",
            "jenis": "samurai",
            "deskripsi": "its panda samurai",
            "image": "167748215ed489e0f363d5be562026dd.jpg",
            "url": "http://localhost:5000/images/167748215ed489e0f363d5be562026dd.jpg",
            "createdAt": "2024-11-29 03:39:16",
            "updatedAt": "2024-11-29 06:38:10"
        }
    ]
}

I have Code Java Script Like This to show card for image, name and button.

const data = "../php/data.json";
const jenisList = document.querySelector('.content');
var urlParams = new URLSearchParams(window.location.search);
var jenis = urlParams.get("jenis");
const modalDetail = document.querySelectorAll('.btn-primary');

const getProducts = ()=>{  
    fetch(data)                   
    .then(response =>{              
        return response.json();     
    }).then(responseJson =>{        
        if(jenis == null){
            showProduct(responseJson.products);  
        }else
        {
            jenisProduct(responseJson.products);
        } 
    }).catch(error=>{                     
        console.log(error);
    });
    
}

const showProduct = product =>{      
    jenisList.innerHTML = '';
        product.forEach(agen =>{
            jenisList.innerHTML += 
            `<div class="product-list">
            <div class="flex-div">
            <a href="" class="foto-product"><img src="${agen.url}" class="product-img"></a>
                <div class="product-info">
                    <p>${agen.name}</p>
                </div>
                <a href="#" class="btn-primary" data-toggle="modal" 
                data-target="#movieDetailModal" data-imdbid="${agen.id}">Show Detail</a>
            </div>
        </div>`
    });
}

const jenisProduct = product =>{
    jenisList.innerHTML = '';
    product.forEach(agen =>{
        if(agen.jenis === jenis){
            jenisList.innerHTML += 
            `<div class="product-list">
            <div class="flex-div">
            <a href="" class="foto-product"><img src="${agen.url}" class="product-img"></a>
                <div class="product-info">
                    <p>${agen.name}</p>
                </div>
                <a href="${agen.id}" class="btn btn-primary modal-detail-button" data-toggle="modal" 
                data-target="#movieDetailModal" data-imdbid="${agen.id}">Show Detail</a> 
            </div>
        </div>`
        }
});

}
document.addEventListener('DOMContentLoaded', getProducts);

And i still confused how to get other data like “id”, “name”, “image”, “url”, “brand”, “jenis”, “deskripsi” from JSON that specific what image or what button I click and it will show other data from JSON?.

to get other data like “id”, “name”, “image”, “url”, “brand”, “jenis”, “deskripsi” from JSON that specific what image or what button I click and it will show other data from JSON. I just Learn about fetch

How to correctly set host for MultiUp.io API?

I’m trying to upload to MultiUp.io via the API, but when it comes to selecting the host for the upload, it doesn’t work correctly. However, the upload process still proceeds.

file uploded

result

async function uploadMagnetOrTorrent({
    user,
    magnet = null,
    name,
    archive = true,
    archiveMaxSize = 5242880, // Default: 5120 MB
    archivePassword = null,
    noSeed = true,
    rename = false,
    files = [],
    hostList = ['vikingfile.com'],

}) {

    try {
        const fastestServer = await getFastestServer();
        if (!fastestServer) {
            throw new Error('Could not retrieve the fastest server.');
        }

        const url = `${fastestServer}/upload/torrent.php`;

        // Create form data
        const formData = new FormData();
        formData.append('user', user);
        if (magnet) formData.append('magnet', magnet);
        formData.append('name', name);
        formData.append('archive', archive.toString());
        formData.append('archive-max-size', archiveMaxSize.toString());
        if (archivePassword) formData.append('archive-password', archivePassword);
        formData.append('no-seed', noSeed.toString());
        formData.append('rename', rename.toString());

        files.forEach((file, index) => {
            formData.append(`files[]`, file);
        });

        hostList.forEach((host, index) => {
            formData.append(`host${index + 1}`, host);
        });

        // Send the POST request
        const response = await axios.post(url, formData, {
            headers: formData.getHeaders(),
        });

Link for documentation Multiup api Documentation

I checked the API documentation to ensure the parameters are correct, but I am still stuck. I want the file to be uploaded to the correct host

Unable to get old and new rule id on dragNdrop

import { QueryBuilderDnD } from '@react-querybuilder/dnd'; 
import * as ReactDnD from 'react-dnd'; 
import * as ReactDndHtml5Backend from 'react-dnd-html5-backend'; 
import { add, QueryBuilder, formatQuery } from 'react-querybuilder'; 

I am using these query builder and I am using this twice in code

<QueryBuilderDnD dnd={{ ...ReactDnD, ...ReactDndHtml5Backend }}> 
    <QueryBuilder {...prop} > 
    </QueryBuilder> 
</QueryBuilderDnD > 

<QueryBuilderDnD dnd={{ ...ReactDnD, ...ReactDndHtml5Backend }}> 
    <QueryBuilder {...prop} > 
    </QueryBuilder> 
</QueryBuilderDnD > 

so when I drag a query from one to another QueryBuilder I want to get previous and updated rule ID of dragged rule not the query builder id only the rule id which is draged and droped

I am not able to find any handleDrop, isDroped, onDragEnd kind of prop for any of this to get these values

Reproduction:
Create 2 in a single component and move rule from one to another

Expected behavior:
There should be a prop which returns me which rule id is changed and return me old and new id of that rule on dragging from one QueryBuilder to another QueryBuilder

VSCode – Intellisense not working in (.jsx React)

I have problem when using JSX the autocomplete didn’t show on VSCode when I want to produce event.preventDefault() but didn’t show any javascript autocompletion
enter image description here

I already enabled the JavaScript and TypeScript Nightly extension, but still not working

This is my vscode settings, is there something I need to change to make the autocomplete work?

"html.autoClosingTags": true,
  "[html]": {
    "editor.defaultFormatter": "vscode.html-language-features",
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": "explicit"
    }
  },
  "emmet.includeLanguages": {
    "django-html": "html",
    "javascript": "javascriptreact",
    "edge": "html",
    "vue-html": "html",
    "vue": "html",
  },
  "[css][scss][less]": {
    "editor.defaultFormatter": "vscode.css-language-features"
  },
  "javascript.suggest.paths": false,
  "javascript.format.semicolons": "remove",
  "typescript.suggest.paths": false,
  "typescript.format.semicolons": "remove",
  "[javascript][javascriptreact][typescript][typescriptreact]": {
    "editor.tabSize": 2,
    "javascript.suggest.enabled": true,
    "javascript.preferences.quoteStyle": "single",
    "typescript.preferences.quoteStyle": "single",
    "typescript.suggest.enabled": true,
    "editor.hover.enabled": true,
    "editor.hover.above": false,
    "editor.defaultFormatter": "vscode.typescript-language-features",
    "editor.codeActionsOnSave": {
      "source.fixAll": "explicit"
    }
  },
  "[json][jsonc]": {
    "editor.tabSize": 2,
    "editor.defaultFormatter": "vscode.json-language-features"
  },
  "[vue]": {
    "editor.defaultFormatter": "Vue.volar",
    "editor.hover.enabled": true,
    "editor.hover.above": false
  },
  "php.stubs": [
    "*",
    "pgsql"
  ],
  "eslint.useFlatConfig": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "svelte"
  ],
  "javascript.referencesCodeLens.showOnAllFunctions": true`

VSCode – JSX React Intellisense not working

I have problem when using JSX the autocomplete didn’t show on VSCode when I want to produce event.preventDefault() but didn’t show any javascript autocompletion
enter image description here

I already enabled the JavaScript and TypeScript Nightly extension, but still not working

This is my vscode settings, is there something I need to change to make the autocomplete work?

"html.autoClosingTags": true,
  "[html]": {
    "editor.defaultFormatter": "vscode.html-language-features",
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": "explicit"
    }
  },
  "emmet.includeLanguages": {
    "django-html": "html",
    "javascript": "javascriptreact",
    "edge": "html",
    "vue-html": "html",
    "vue": "html",
  },
  "[css][scss][less]": {
    "editor.defaultFormatter": "vscode.css-language-features"
  },
  "javascript.suggest.paths": false,
  "javascript.format.semicolons": "remove",
  "typescript.suggest.paths": false,
  "typescript.format.semicolons": "remove",
  "[javascript][javascriptreact][typescript][typescriptreact]": {
    "editor.tabSize": 2,
    "javascript.suggest.enabled": true,
    "javascript.preferences.quoteStyle": "single",
    "typescript.preferences.quoteStyle": "single",
    "typescript.suggest.enabled": true,
    "editor.hover.enabled": true,
    "editor.hover.above": false,
    "editor.defaultFormatter": "vscode.typescript-language-features",
    "editor.codeActionsOnSave": {
      "source.fixAll": "explicit"
    }
  },
  "[json][jsonc]": {
    "editor.tabSize": 2,
    "editor.defaultFormatter": "vscode.json-language-features"
  },
  "[vue]": {
    "editor.defaultFormatter": "Vue.volar",
    "editor.hover.enabled": true,
    "editor.hover.above": false
  },
  "php.stubs": [
    "*",
    "pgsql"
  ],
  "eslint.useFlatConfig": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "svelte"
  ],
  "javascript.referencesCodeLens.showOnAllFunctions": true`

reaviz/reaflow – [v5.3] [Bug] importing anything from the library results in error – Keys is not a function

The recent version of reaviz/reaflow (reaflow) brings breaking changes to my web app. I wanted to use the latest exposed function where we can zoom in on a particular node of tree which can be useful for user to find out any particular tree node in a large tree.
Bug Image on code sandbox

Issue occurs as soon as you import anything from library version 5.3.1

Normally, the error should not come. So far we were using version 5.1.0 which did not cause any issue with our project. recently there was a requirement which could be easily resolved by a function exposed in latest version of this library (fitNodes) but due to this error we cannot upgrade the library.
Any help provided will be appreciated

Issue reported on github as well https://github.com/reaviz/reaflow/issues/265

code sandbox link -> https://codesandbox.io/p/sandbox/reaflow-demo-ptbgs9

Minimal reproduction of the problem with instructions

Step 1 -> Setup a react project with following library versions ->

  • React@18
  • React-dom@18
  • React-scripts@5
    Step 2 -> Install [email protected] and simply import Canvas component exposed by this library.
    Step 3 -> Run the server and you will see an error on console
  • Node version: have tried with v15, v18, v22
  • Platform: Mac
  • IDE: VS code and Codesandbox env as well

Libs:

  • react version: 18.0.0
  • react-dom: 18.0.0
  • react-scripts: 5.0.0
  • reaflow: 5.3.1

The issue happens with both webpack and react-scripts compiler

Is it possible to use the Spotify API to display what I’m currently listening to as part of my website?

I want to know if it is possible for me to have a banner on my personal website that says “I am currently listening to : [insert track]” where [insert track] is sourced from the Spotify dev API. I know that the Spotify API has an endpoint called currently_playing, but after investigating I found out it uses the OAuth_2 flow and, though maybe I’m wrong, I think that means that anytime you want to call and display api information you have to have the person viewing the website log into THEIR account, so it will display THEIR info, not mine, which defeats the whole point (the point is to broadcast to everyone what I am listening to). Is there any way around this, or even better, am I misunderstanding OAuth_2? It’s kind of a simple concept so I would really love it if I could bring it together.

I tried this:

async function fetchCurrentlyPlaying(token) {
    try {
      const response = await fetch("https://api.spotify.com/v1/me/player/currently-playing", {
        method: 'GET', 
        headers: {'Authorization' : 'Bearer ' + token}
      });
      if (response.data && response.data.item) {
        const { name, artists, album, external_urls } = response.data.item;
        return response.status(200).json({
          name,
          artists: artists.map((artist) => artist.name),
          album: album.name,
          image: album.images[0]?.url,
          url: external_urls.spotify,
        });
      } else {
        return response.status(204).json({ message: 'No song is currently playing.' });
      }
    }catch(error){
      console.error(error);
      return ({ error: 'Error fetching currently playing track' });
    }
  }

where token is a token I generate using client credential flow (I believe), however it gave me back:

{
  "error" : {
    "status" : 404,
    "message" : "Invalid username"
  }
}

Which is why I started digging and found out about OAuth_2 (which I previously skipped over I think)

Clicking HTML table row button opens forms for every single row

Beginner here. I have an HTMl table with buttons and I want a button to toggle open a form with the values from that row. Problem is, if I have multiple rows in my table, it opens multiple forms for each row with the values pre-filled. How can I make it so that it only opens a single form for that row only?

my HTML, shortened for clarity

<div class="table-responsive my-5">
    <table id="table-address-book" class="display table table-striped table-hover">
        <thead>
            <tr style="text-align: center;">
                <th style="width: 150px;">insert headers here</th>
                <th style="width: 150px;">Actions</th>
            </tr>
        </thead>
        <tbody>
        {% for address in addressInfo %}
            <tr class="row-address-book" style="text-align: center; vertical-align: middle;">
                <td>
                   insert table data here
                </td>
                <td>
                    <div class="d-flex align-items-center justify-content-center" style="display: inline; vertical-align: baseline;">
                        <button
                        class="btn btn-sm mx-1 btn-black"
                        type="button"
                        hidden=""
                        >
                            <i class="fa fa-chevron-down"></i>
                        </button>
                        <button
                        class="btn-edit-address btn btn-sm mx-1"
                        type="button"
                        style="color: rgb(24, 115, 184);"
                        >
                            <i class="fa fa-edit"></i>
                        </button>
                        <form action="{{ url_for('homepage.deleteBuyerAddress', addressBookID=address.0 ) }}" class="form-delete-address" method="POST">
                            <button
                            class="btn-delete-address btn btn-sm mx-1"
                            type="submit"
                            style="color: red;"
                            >
                                <i class="fa fa-times"></i>
                            </button>
                        </form>
                    </div>
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
</div>

{% for address in addressInfo %}
<form action="#" method="POST" class="form-edit-address" style="display: none; margin-top: 50px;">
    <div class="input-group mb-3">
        input groups here
    </div>
        
    <div class="d-flex align-items-center justify-content-center">
        <button 
        class="btn btn-primary me-2" 
        type="submit" 
        style="margin-top: 25px;"
        >
        Edit address
        </button>
        <button 
        class="btn btn-warning ms-2" 
        type="button" 
        style="margin-top: 25px;"
        onclick="closeEditAddressForm()"
        >
        Cancel
        </button>
    </div>
</form>
{% endfor %}

my JS:

$(".btn-edit-address").click(function () {
    $('.form-edit-address').toggle('fast');
});

function closeEditAddressForm () {
    $('.form-edit-address').toggle('fast');
}

I have already gone from IDs to classes, but still it wouldn’t work.

Tampermonkey use Library

I created a simple calendar in TamperMonkey and created a button to apply details, but the GM library is not imported with @grant and other APIs cannot be used. What is the reason? Simple JavaScript code and CSS are applied, but the GM library cannot be used. I have obtained example sources through GitHub and GTP, but the library does not apply to any of them. Has anyone experienced a similar problem?

Exsample, Source Code

I can’t understand why I can’t push files into an INPUT[type=”file”]

I searched, and I saw many answers about that.

Plenty of them are “You can’t. Because of security.”

However, are there plenty of ways to send data to the server without using INPUT[type=”file”] Tag?

If your JavaScript code can grab the client’s important files or data, then is it just game over at that point?

Making the INPUT[type=”file”] tag “read-only” would do NOTHING in my opinion.

For instance, you can just use AJAX to send that data or file or whatever it is.

There are plenty of ways to sneakily send data to the server.

So I think that the real matter is to prevent the JavaScript code inside the browser can reaching out the client’s local data without permission.

And making the “Input type = file” tag “read-only” is meaningless in my thought.

But I might be wrong.

I am pretty new to this field.

So if my thought is wrong, could you tell me exactly what part of my thought is wrong?

It would be really helpful.

How to send Shift+Enter when pressing Enter in a webpage?

I tried to intercept all enters in a page and send Shift+enter, but it creates an endless loop of shift enters. Unable to find the issue. may be the simulated enter is treated as another enter. How to handle this?

document.addEventListener('keydown', function(event) {
    if (event.key === 'Enter' && !event.shiftKey) {
        event.preventDefault();
        
        const myevent = new KeyboardEvent('keydown', {
            key: 'Enter',
            shiftKey: true,
            bubbles: true
        });
        
        //  alert('Test Enter');
        event.target.dispatchEvent(myevent);
    }
});

Please note: I use ‘User JavaScript and CSS’ to load this js to work on any webpage, especially in chatgpt website.

Is there a good way to circumvent the frequency limitation of mousemove events?

Mousemove events only fire at a limited frequency, which is determined by the implementation. I think in most browsers it depends on the speed of movement, and caps out at 70hz or so. This causes visible lag if you’re trying to render something at the location of the mouse.

I attempted to circumvent this limitation by covering the screen with a grid of invisible divs with mouseenter event listeners. Unfortunately it looks like Chrome will start dropping mouseenter events if they’re fired too frequently. Make the grid cells too large and the mouse isn’t crossing boundaries frequently enough, make them too small and events start getting dropped. I found that a cell edge length of around 10px was best, which slightly increased dispatch frequency up to around 110hz, but this was not sufficient to eliminate the visible lag.

I suspect there are better ways to cheat browsers into giving me more fine-grained movement data, but it likely depends on implementation details that I don’t know about. Any ideas?

How to send a base64 image to Bedrock via ConverseCommand as bytes

I’m trying to upload an image to AWS Bedrock Claude model using the ConverseCommand (in @aws-sdk/client-bedrock-runtime 3.699.0).

I have the base64 version of image (eg https://yulvil.github.io/gopherjs/02/)

According to the documentation, it requires the bytes as a Uint8Array, so I’ve tried

  1. bytes: new Uint8Array(Buffer.from(img, 'utf-8'))
  2. bytes: Buffer.from(img, 'utf-8')
  3. bytes: new TextEncoder().encode(ing)

None seem to work having error ValidationException: The model returned the following errors: messages.0.content.1.image.source.bytes: Invalid image input

What am I missing?

const {
  BedrockRuntimeClient,
  ConverseCommand,
} = require("@aws-sdk/client-bedrock-runtime");

const modelId = "anthropic.claude-3-haiku-20240307-v1:0";

let conversation = [];

const describeImage = async () => {
  const client = new BedrockRuntimeClient({
    region: "us-east-1",
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    },
  });

  let content = [];

  const img = “data:image/png;base64,...”

  content.push({
    image: {
      format: "png",
      source: {
        bytes: img,
      },
    },
  });
  content.push({ text: “Describe the given image” });
  conversation.push({
    role: "user",
    content,
  });

  try {
    const response = await client.send(
      new ConverseCommand({
        modelId,
        messages: conversation,
      })
    );
    return response.output.message.content[0].text;
  } catch (err) {
    console.log(`ERROR: Can't invoke '${modelId}'. Reason: ${err}`);
  }

describeImage();

How can I send information from the tauri backend to the react front end without causing graphical lag?

I’m writing a Tauri app, which uses Rust and ReactJS

However, when sending information messages about file downloads, my app has a slight graphical lag

I have the following Tauri Rust code

use serde::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, Serialize, Clone)]
struct DownloadMessage {
    message: String,
}

#[derive(Debug, Serialize, Clone)]
struct DownloadProgress {
    downloaded_bytes: u64,
    total_bytes: u64,
}

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

async fn read_patch_file_async(path: &Path) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let content = tokio_fs::read_to_string(path).await?;
    let patches: Vec<String> = serde_json::from_str(&content)?;
    Ok(patches)
}

async fn download_patch_file(
    app_handle: &AppHandle,
    client: &Client,
    file_name: String,
    download_dir: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
    let url = format!("https://hil-speed.hetzner.com/{}", file_name);
    let file_path = download_dir.join(&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: "Downloading...".to_string() })?;
        app_handle.emit("download_progress", DownloadProgress {
            downloaded_bytes,
            total_bytes,
        })?;
        app_handle.emit("download_speed", speed)?;
    }

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

async fn verify_server_connection(client: &Client, url: &str) -> Result<(), Box<dyn std::error::Error>> {
    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_file_downloads(app_handle: AppHandle) -> Result<(), String> {
    let exe_dir = get_exe_directory();
    let patch_file_path = exe_dir.join("file.json");
    let download_dir = exe_dir.join("files");

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

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

    app_handle.emit("download_message", DownloadMessage {
        message: "Connecting to server...".to_string(),
    }).map_err(|e| e.to_string())?;

    let server_url = "https://meysite/";
    if let Err(err) = verify_server_connection(&client, server_url).await {
        app_handle.emit("download_message", DownloadMessage {
            message: format!("Error connecting to server: {}", err),
        }).map_err(|e| e.to_string())?;
        return Err(format!("Error connecting to server: {}", err));
    }

    app_handle.emit("download_message", DownloadMessage {
        message: "Connection successful. Starting downloads...".to_string(),
    }).map_err(|e| e.to_string())?;

    for file_name in patches {
        if let Err(err) = download_patch_file(&app_handle, &client, file_name, &download_dir).await {
            eprintln!("Error downloading file: {}", err);
            app_handle.emit("download_message", DownloadMessage {
                message: format!("Error downloading file: {}", err),
            }).map_err(|e| e.to_string())?;
        }
    }

    Ok(())
}

in my React to show the information I have

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

const DownloadTest = () => {
  const [message, setMessage] = useState("");
  const [progress, setProgress] = useState<{ downloaded_bytes: number; total_bytes: number }>({
    downloaded_bytes: 0,
    total_bytes: 0,
  });
  const [downloadSpeed, setDownloadSpeed] = useState(0);
  const [isDownloading, setIsDownloading] = useState(false);

  useEffect(() => {
    const unlistenMessage = listen<{ message: string }>("download_message", (event) => {
      setMessage(event.payload.message);
    });

    const unlistenProgress = listen<{ downloaded_bytes: number; total_bytes: number }>(
      "download_progress",
      (event) => {
        setProgress(event.payload);
      }
    );

    const unlistenSpeed = listen<number>("download_speed", (event) => {
      setDownloadSpeed(event.payload);
    });

    return () => {
      unlistenMessage.then((unlisten) => unlisten());
      unlistenProgress.then((unlisten) => unlisten());
      unlistenSpeed.then((unlisten) => unlisten());
    };
  }, []);

  const progressPercentage = progress.total_bytes
    ? ((progress.downloaded_bytes / progress.total_bytes) * 100).toFixed(2)
    : 0;

  const startDownload = async () => {
    try {
      setIsDownloading(true);
      setMessage("Starting download...");
      await invoke("start_file_downloads");
    } catch (error) {
      console.error("Error starting download:", error);
      setMessage("Failed to start download. Check the logs.");
    } finally {
      setIsDownloading(false);
    }
  };

  return (
    <div>
      <h1>Download Manager</h1>
      <button onClick={startDownload} disabled={isDownloading}>
        {isDownloading ? "Downloading..." : "Start Download"}
      </button>
      <p>{message}</p>
      <div>
        <h2>Progress</h2>
        <p>Downloaded: {progress.downloaded_bytes} bytes</p>
        <p>Total: {progress.total_bytes} bytes</p>
        <p>Progress: {progressPercentage}%</p>
      </div>
      <p>Download Speed: {downloadSpeed.toFixed(2)} bytes/sec</p>
    </div>
  );
};

export default DownloadTest;

What should I do so that the download doesn’t affect the UI performance?