Compress wav size in the javascript client

I am currently recording audio in wav from the browser in my Next application using an extension of the MediaRecorder.
I need the audio to be in wav format in order to use Azure speech services. However, I’d like to also store the audio in a bucket (S3 most likely) for the user to see listen to the audio later. For this I need to have the audio in a compressed format: mp3, webm whatever, because the wav files are too heavy

I was thinking in compressing server side, either in the plain backend or maybe on a lambda function, but it looked like overengineering or heavy processing on the backend.
So I was thinking on doing this compression in the client. How can I do that? The other solutions I found are really old. The only one kinda recent was Lamejs, but I’m not too sure on the state of that package.

JavaScript Array Object, return a keys value in new array [duplicate]

I have an array that contains an object. (I’ve simplified to explain);

playerDB_1 = [];
for(n=0; n<=1000; n++){ 
    playerDB_1[n] = {};
    playerDB_1[n].code = 1000+n;
};

I want to be create a new array with the values of each .code key, thus creating something, result_1 = [1000, 1001, 1002, 1003, 1004 etc.];

I have found this small snippet of code that explains how to do so:

const map = new Map([['key1', 'value1'], ['key2', 'value2']])
const valuesArray = Array.from(map.values())

console.log(valuesArray) // Output: ['value1', 'value2']

But I can’t figure out how to implement it on.

How can I detect if a browser is blocking a new tab or popup when using `window.open` with `noopener`?

Like suggested in the question How can I detect if a browser is blocking a popup? (2008), the return value of the JavaScript function call

window.open("https://example.com/", "_blank", "")

can be used to determine if the popup was blocked; as stated on MDN

null is returned if the browser fails to open the new browsing context, for example because it was blocked by a browser popup blocker.

However, this solution breaks due to the method always returning null when you use noopener under windowFeatures, which is also what you are generally almost always supposed to do when your project is intended for production. noopener is suggested in the question Use window.open but block use of window.opener (2016) to address a security concern.

So how can you still determine if a popup (e.g., opening a new tab) was blocked when calling the following in JavaScript:

window.open("https://example.com/", "_blank", "noopener")`

given that it always returns null?
(Tested in Chrome and Firefox, year 2025)

The MDN documentation doesn’t cover this case, so I fear this might be a bug / design flaw.

Motivation

To clarify an expected use-case, it’s typical for a web app’s functionality to break if any attempts to navigate a user to a different page/domain fail. Critical parts of a user flow may require developers to handle any failure by displaying a warning to the user and teaching them how to allow popups for the current site in their browser.

Note: you can also find this question in the form of a comment in:

Workaround:

This answer suggests a workaround, similar to what an the article Overcoming popup blocking issues (2023) also describes:

function dynamicallyCreateAnchorAndNavigate(url) {
  let a = document.createElement('a');
  a.href = url;
  a.target = "_blank"
  // Note: target="_blank" implies rel="noopener" behavior as per https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#browser_compatibility
  a.rel = "noopener"
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

By not using the window.open API, but instead creating a temporary anchor to use its click API, we may avoid some popup blockers.

I don’t know if this is currently a consistent solution across all typical environments and guarantees that no popup blockers will ever block the new page. If so, I think it would indicate a negligence of browsers’ implementations of popup blockers. I welcome any contributions/comments to please update these statements to reflect the current situation.

That said, I believe the Window API provides more functionality than <a>, so the window.open (being the topic of this question) may still be necessary for some use-cases. For example, the popup feature from windowFeatures, i.e. a “minimal popup window”, probably can’t be achieved via <a>.

Chrome extension’s content script trying to use MutationObserver but fails to detect nodes that i want to find

this Chrome extension content script is supposed to run on youtube and try to find elements with tagName YT-THUMBNAIL-VIEW-MODEL.
The script is injected at document_start so that it is executed and i catch every new element

but this is not detecting even a single node.
pls someone help

Note that given code is not wrapped in kind of evenListeners like load, DOMContentLoaded

Code:


function processNodes(nodes) {
    nodes.forEach(node => {
        if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "YT-THUMBNAIL-VIEW-MODEL") {
            console.log(node);
        }
    });
}
    const observer = new MutationObserver((mutationsList, observer) => {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                processNodes(mutation.addedNodes);
            }
        }
    });


    const targetNode = document.documentElement;
    const config = { childList: true, subtree: true };

    observer.observe(targetNode, config);

I tried a bunch and also asked ais but no help.
was expecting to see new elements that are getting added initially and after I scroll.

React state don’t rerender the component on change?

I’m building a simple chat app in React with a custom hook that fetches chats from a service once a WebSocket client is connected.

The fetch succeeds and I can see the data in the console, but the component still renders chat as null. It only shows the data after I trigger another state update by clicking a button.

here is the useChat hook :

import { useEffect, useState } from "react";
import ChatService from "../services/chat-service";
import { Client } from "@stomp/stompjs";
import Conversation from "../entities/chat/Conversation";
import Account from "../entities/user/Account";
import Message from "../entities/chat/Message";

export default function useChat(){
  const [loading,setLoading] = useState(true)
  const [client,setClient] = useState<Client | null>(null)
  const [chat,setChat] = useState<Conversation[] | null>(null);
  
  useEffect(()=>{
    const initSocket = async ()=>{
      const client = await ChatService.initialSocketConnnection((message)=>{
        console.log(message);
      })
      setClient(client)
    }
    initSocket()
    
    return ()=>{
      client?.deactivate();
      setClient(null);
    }
  },[])
  
  useEffect(()=>{
    if (!client) return;
    
    
    const initChat = async ()=>{
      const chats = await ChatService.getChat()
      console.log('Fetched chats:', chats);
      setChat(chats);
      setLoading(false)
    }
    
    initChat()
    
    return ()=>{
      setChat(null);
      setLoading(true)
    }
  }, [client])
  
  const sendMessage = (destination:Account,message:Message) => {
    if(!client) return
    ChatService.sendMessage(destination.username,message,client);
  }
  
  return {sendMessage,loading,chat}
}

and here is the Chat component

import { useState } from "react"
import Card from "../components/ui/Card"
import useChat from "../hooks/useChat"

export default function Chat(){
    const {sendMessage,loading,chat} = useChat()
    const [test,setTest]= useState<number | undefined>(0);
    
    if(loading) return <>Loading</>
    return <div className="w-full h-full bg-background-light dark:bg-background-dark flex ">
                <div className="w-2/6 h-full min-w-100 max-w-140 border-r border-border-light dark:border-border-dark flex flex-col">
                    <div className="w-full border-b border-border-light dark:border-border-dark p-4 flex items-center justify-between">
                        <h1 className="text-xl font-semibold ">Messages</h1>
                        <Card className="px-2 py-1 shadow-none border-none *:cursor-pointer">
                            <button  className="text-xl ">
                                <i className="fa-solid fa-plus"></i>
                            </button>
                        </Card>
                    </div>
                    <div className="flex-1 overflow-scroll ">
                        {loading?"loading":"not Loading"}
                        {Array.isArray(chat) && chat.length > 0 ? (
                            chat.map((element, index) => (
                                <h1 key={index}>{JSON.stringify(element)}</h1>
                            ))
                            ) : (
                            <p>No chats yet</p>
                            )}
                        
                        {test}
                        <br></br>
                        <button onClick={()=>{setTest(chat?.length)}}>
                            Increment
                        </button>
                    </div>
                </div>
                <div className="flex-1 h-full">
                  
                </div>

        </div>
}

When using this with and redirect back to the page after successful operation the ckeditor is not loading

I Am using ckeditor 5 and here is my configuration. which is working good when i first load the page but i click on the submit button and server redirect me on same page this is no longer working here.

<script type="importmap">
    {
        "imports": {
            "ckeditor5": "{{ asset('assets/ckeditor5/ckeditor5.js') }}",
            "ckeditor5/": "{{ asset('assets/ckeditor5/') }}"
        }
    }
</script>
<script type="module">
    import {
        ClassicEditor,
        AccessibilityHelp,
        Alignment,
        AutoLink,
        Autosave,
        BlockQuote,
        Bold,
        CodeBlock,
        Essentials,
        Font,
        GeneralHtmlSupport,
        Heading,
        HorizontalLine,
        Indent,
        IndentBlock,
        Italic,
        Link,
        Paragraph,
        SelectAll,
        Style,
        Table,
        TableCaption,
        TableCellProperties,
        TableColumnResize,
        TableProperties,
        TableToolbar,
        Undo
    } from 'ckeditor5';

    let ckEditors = document.querySelectorAll(".ckeditor");

    ckEditors.forEach((editor) => {
        ClassicEditor
            .create(editor, {
                plugins: [AccessibilityHelp, Alignment,
                    AutoLink,
                    Autosave,
                    BlockQuote,
                    Bold,
                    CodeBlock,
                    Essentials,
                    Font,
                    GeneralHtmlSupport,
                    Heading,
                    HorizontalLine,
                    Indent,
                    IndentBlock,
                    Italic,
                    Link,
                    Paragraph,
                    SelectAll,
                    Style,
                    Table,
                    TableCaption,
                    TableCellProperties,
                    TableColumnResize,
                    TableProperties,
                    TableToolbar,
                    Undo
                ],
                toolbar: {
                    items: ['undo',
                        'redo',
                        '|',
                        'bold',
                        'italic',
                        '|',
                        '|',
                        'heading',
                        '|',
                        'fontSize',
                        'fontFamily',
                        'fontColor',
                        'fontBackgroundColor',
                        '|',
                        'indent',
                        'outdent',
                        'alignment',
                        '|',
                        'horizontalLine',
                        'link',
                        'insertTable',
                        'blockQuote',
                        '|',


                    ]

                }
            })
            .then(editor => {
                window.editor = editor;
            })
            .catch(error => {
                console.error(error);
            });
    });
</script>

When redirect back to the page it gives me error

Error

Uncaught TypeError: The specifier “ckeditor5” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”.

How to do custom plugin with custom parameters?

We have a TypeDoc custom plugin called CustomPlugin and I wish to pass custom parameters into that plugin, therefore it appears I cannot add its name as a string to the plugin option.

After running Appplication.bootstrapWithPlugins, I call the plugin as a function CustomPlugin(params). The issue I am having is my plugin requires that the JSON output has already been written and is accessible for use inside the plugin. The JSON output can only be called after convert is called and the project instance becomes available.

app.convert.addUnknownSymbolResolver has to be set before app.convert() is called or the plugin will fail to resolve these unknown symbols. I have set this inside the CustomPlugin.

This is a NX Monorepo with multiply projects inside and TypeDoc is called against many of them in the right order using dependsOn in nx.json.

const app = await Application.bootstrapWithPlugins({
  { ...options },
  [...readers]
});

// I need the generated **my-path.json** available in here to access the symbolIdMap
// We actually also use other projects **my-path.json** as well in here
// We build the projects in the right order using dependOn in the nx.json file
load(params); // CustomPlugin

const project = app.convert();

await app.generateJson(project, 'my-path.json');

I have implemented a double pass which works fine but was looking for other solutions.

Sound delay on the npm module node-wav-player

I’m using a typewriter effect and want to make a sound for every letter like the movie letter sound. I want to use the CMD program in Windows 11 to make a chatbot that runs with the command node chatbot.js. I don’t want it to run in the browser but in node.js. I have tryed to ask the ChatGPT but with no luck. I’m using the node-wav-player and it works; but the sound is delayed and not stabile. On the repo on GitHub they mention the require method; but I want the import method.

İs C sufficient for learning for beginners

I began learning programming since this September and a lot of people ı saw online recommending C for learning as its closer to hardware and learning it would make learning high level languages much easier. Should ı give a shot on C?

Some people also recommended Javascript and Python as they’re high on demand in the job market.

React Aria FileTrigger onSelect not firing on first file selection in Chrome iOS, subsequent selections trigger cancel event

I’m encountering an inconsistent event behavior with the FileTrigger component from @react-aria/components in a React application. The issue is observed specifically in ​​Chrome on iOS (version 140)​​ based on user analytics, and is difficult to reproduce.

Problem Description​​

After a user selects an image file:

​​First selection​​: The onSelect event handler does not fire at all.

​​Second and subsequent selections​​: The file dialog opens, but immediately after a file is selected, a cancel event is triggered follow by the button click event. The selected files are not processed, which no triggered the onSelect event.

Environment​​

  • ​​React​​: 18.x

  • Library​​: @react-aria/components(1.2.1)

  • ​​Browser & Platform​​: Chrome 140, iOS (iPhone/iPad)
    ​​
    ​​Simplified Code Example​​
    Here is a simplified version of the component focusing on the event handling:

import React, { useEffect, useRef } from 'react';
import { FileTrigger } from 'react-aria-components';

const UploadComponent = ({ onFileSelected }) => {
  const uploadInputRef = useRef(null);

  // This handler does not fired at all
  const handleFileSelect = (fileList) => {
    console.log('onSelect fired', fileList);
    if (fileList) {
      onFileSelected(Array.from(fileList));
    }
  };

  // This event fires immediately on subsequent selections
  const handleCancel = () => {
    console.log('Cancel event fired from user selection');
  };

  useEffect(() => {
    const currentInput = uploadInputRef.current;

    // this code will run after second upload
    currentInput?.addEventListener('cancel', handleCancel);

    return () => {
      currentInput?.removeEventListener('cancel', handleCancel);
    };
  }, []);

  return (
    <FileTrigger
      // didn't triggered 
      onSelect={handleFileSelect}
      acceptedFileTypes={['image/*', 'image/heic', 'image/heif']}
      allowsMultiple={true}
      ref={uploadInputRef}
    >
      {/* we got the click logs from this button */}
      <button onClick={() => {console.log('clicked');}}>Select Images</button>
    </FileTrigger>
  );
};

export default UploadComponent;

onSelect can be triggered, and got the file from user.

How to remove header ‘Host’ using supertest

I have condiiton in my http server that check if req.headers["host"] is undefined or not. I am using supertest and mocha to send GET request. I tried to use unset("Host"), but supertest still send header “Host”

http server:

const http_server = http.createServer(function (req, res) {
  console.log("http", req.method, req.url, req.headers);

  const url_path = url.parse(req.url, true).pathname;
  const query = url.parse(req.url, true).query;

  if (req.method === "GET" && req.headers["host"] !== undefined) {
    // force create session
    const session = getSession(req);
    console.log(`HOST === ${req.headers["host"]}`)

    res.removeHeader("Date");
    res.removeHeader("Transfer-Encoding");

    res.writeHead(302, {
      Location: getNewLocation(req.headers["host"], url_path, query),
      Connection: "close",
    });

    res.end();
    return;
  }

  handler(req, res);
});

test

  it("should return index.html", (done) => {
    request(http_server)
      .get("/")
      .unset("Host")
      .expect(200)
      .expect("Connection", "close")
      .expect("Etag", '"167-110-5f0633df"')
      .expect("Last-Modified", "Wed, 08 Jul 2020 21:00:15 GMT")
      .expect("Date", date_regex)
      .expect("Cache-Control", "no-cache")
      .expect("Expires", "0")
      .expect("Content-Type", "text/html")
      .expect("Content-Length", `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="refresh" content="0; URL=/webpages/login.html" />
</head>
</html>
`.length)
      .expect(res => assert.strictEqual(res.text, `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="refresh" content="0; URL=/webpages/login.html" />
</head>
</html>
`))
      .end(done)
  })

I am trying to remove header “Host”, so code would not fall into condition where it sends 302 status code

how do i create a sort function on a table?

The page is here for reference: https://songscape-helgasonpete.replit.app/artist/clarencewilliams.html

I have two tables that are activated by hitting the two buttons. But I want to be able to sort the information within those two tables. So under the “songs as writer” button – I want to be able to sort the information under the “Song” “Writer” “Originally By” headers alphabetically and information under the “Original Release” header by date.

Likewise under the “Songs as Performer” button – I want to be able to sort the information under the “Title” and “Performer” headers alphabetically, the information under the “Release Date” by date and the information under the “Streamcount” header numerically.

I tried creating two tables of differing data similar to the table I did on this link here: https://songscape-helgasonpete.replit.app/artist/bessiesmith.html. The table would be button activated.

I was able to get the buttons work, but I was unable to sort the table once I clicked on it. Here is the code for reference:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Clarence Williams</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <style>
        th {
            color: white;
        }
    </style>


  </head>
  <body>

<h1>Clarence Williams</h1>
<img src="/images/clarencewilliams.jpg"><br>
Born: October 8, 1898<br>
Died: November 6, 1965<br>
Rankings: <br>
<a href="https://songscape-helgasonpete.replit.app/statistics/writers.html">1st</a> most streamed writer<br>
<a href="https://songscape-helgasonpete.replit.app/statistics/performers.html">2nd</a> most streamed performer<br>
    <button type="button" onclick="updateDisplay('demo')">Songs As Writer</button>
    <button type="button" onclick="updateDisplay('demo2')">Songs As Performer</button>


    <table id="demo" style="display:none" class="specialTable table table-striped">
      <tr class="bg-info">
      <th id="songCol">Song</th>
      <th id="writerCol">Writer</th>
      <th id="originalperformerCol">Originally By</th>
      <th id="releaseCol">Original Release</th>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/work/gulfcoastblues.html">Gulf Coast Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/clarencewilliams.html">Clarence Williams</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td>May 1923</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/work/babywontyoupleasecomehome.html">Baby, Won't You Please Come Home</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/charleswarfield.html">Charles Warfield</a> <a href="https://songscape-helgasonpete.replit.app/artist/clarencewilliams.html">Clarence Williams</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td>June 1923</td>
       </tr>

      </table>

      <table id="demo2" style="display:none" class="specialTable table table-striped">
      <tr class="bg-info">
      <th id="titleCol">Title</th>
      <th id="performerCol">Performer</th>
      <th id="releasetwoCol">Release Date</th>
      <th id="streamCol">Stream Count</th>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/downheartedblues.html">Down Hearted Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">May 1923</a></td>
      <td>1294462</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/gulfcoastblues.html">Gulf Coast Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">May 1923</a></td>
      <td>89052</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/babywontyoupleasecomehome.html">Baby Won't You Please Come Home Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">June 1923</a></td>
      <td>1832242</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/ohdaddyblues.html">Oh Daddy Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">June 1923</a></td>
      <td>37590</td>
       </tr>

      </table>




      <script>

      // Create a function to update your display area
      function updateDisplay(tableId) {

        // The function receives the id of the table to show (give each table a unique id, but the same class)

        // Set the display value of all tables with the target class to none
        document.querySelectorAll(".specialTable").forEach(el => {
          el.style.display = "none";
        });

        // Set the display value of the table with the target id to block
        document.getElementById(tableId).style.display = "block";

        $('#songCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Song";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#writerCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Writer";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#originalperformerCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Originally By";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#releaseCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Original Release";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#titleCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Title";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#performerCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Performer";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#releasetwoCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Release Date";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#streamCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Stream Count";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });
      }

      </script>

      </body>


</html>

Loader in conditional statements is not showing after navigation or making new API calls

I had an API call for fetch products for wishlist and cart however since both share same UI I decided to do in single page component and at first refresh the loader is showing but after I navigation loader is not showing and Header and Product is different components.

Loader is not showing when I navigation between components as it took 0.1s for get data and I can’t see loader when I navigation through it

"use client";

import { useState, useEffect } from "react";
import { useParams } from "next/navigation";
import axios from "axios";
import Image from "next/image";
import { CircularProgress } from "@mui/material";

export default function ViewResouce() {
  const { resource } = useParams();
  const [isCart, setIsCart] = useState(false);
  const [resourcesData, setResourcesData] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [dataFind, setDataFind] = useState(false);

  useEffect(() => {
    if (!resource) {
      return;
    }

    if (resource === "cart") {
      setIsCart(true);
      return;
    }

    setIsCart(false);
  }, [resource]);

  useEffect(() => {
    if (!resource) {
      setIsLoading(false);
      setDataFind(false);
      setResourcesData([]);
      return;
    }

    setIsLoading(true);
    setDataFind(false);
    setResourcesData([]);

    const abortController = new AbortController();

    async function getResource() {
      try {
        const res = await axios.get(
          `/api/client/manage?resource=${resource}`,
          { signal: abortController.signal }
        );
        setResourcesData(res.data.data || []);
      } catch (e) {
        setResourcesData([]);
      } finally {
        setIsLoading(false);
        setDataFind(true);
      }
    }

    getResource();

    return () => {
      abortController.abort();
    };
  }, [resource]);

  if (isLoading && !dataFind) {
    return (
      <div
        className="d-flex justify-content-center align-items-center"
        style={{ height: "50vh" }}
      >
        <CircularProgress size={80} />
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length <= 0) {
    return (
      <div className="no-product-card">
        {isCart && (
          <Image
            src="/assests/no-items-cart.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        {!isCart && (
          <Image
            src="/assests/no-items-wishlist.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        <h6>No {isCart ? "Cart" : "Wishlist"} Items Found</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Cart Items</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && !isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Wishlist Items</h6>
      </div>
    );
  }

  return null;
}

Loader in conditional statements is not showing after I navigation or new API calls in nextjs

I had an API call for fetch products for wishlist and cart however since both share same UI I decided to do in single page component and at first refresh the loader is showing but after I navigation loader is not showing and Header and Product is different components.

"use client";

import { useState, useEffect } from "react";
import { useParams } from "next/navigation";
import axios from "axios";
import Image from "next/image";
import { CircularProgress } from "@mui/material";

export default function ViewResouce() {
  const { resource } = useParams();
  const [isCart, setIsCart] = useState(false);
  const [resourcesData, setResourcesData] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [dataFind, setDataFind] = useState(false);

  useEffect(() => {
    if (!resource) {
      return;
    }

    if (resource === "cart") {
      setIsCart(true);
      return;
    }

    setIsCart(false);
  }, [resource]);

  useEffect(() => {
    if (!resource) {
      setIsLoading(false);
      setDataFind(false);
      setResourcesData([]);
      return;
    }

    setIsLoading(true);
    setDataFind(false);
    setResourcesData([]);

    const abortController = new AbortController();

    async function getResource() {
      try {
        const res = await axios.get(
          `/api/client/manage?resource=${resource}`,
          { signal: abortController.signal }
        );
        setResourcesData(res.data.data || []);
      } catch (e) {
        setResourcesData([]);
      } finally {
        setIsLoading(false);
        setDataFind(true);
      }
    }

    getResource();

    return () => {
      abortController.abort();
    };
  }, [resource]);

  if (isLoading && !dataFind) {
    return (
      <div
        className="d-flex justify-content-center align-items-center"
        style={{ height: "50vh" }}
      >
        <CircularProgress size={80} />
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length <= 0) {
    return (
      <div className="no-product-card">
        {isCart && (
          <Image
            src="/assests/no-items-cart.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        {!isCart && (
          <Image
            src="/assests/no-items-wishlist.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        <h6>No {isCart ? "Cart" : "Wishlist"} Items Found</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Cart Items</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && !isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Wishlist Items</h6>
      </div>
    );
  }

  return null;
}

Thymeleaf page not rendering correctly on iOS when using LIFF SDK

Now I am having a problem:
I am building a chat application, when from the LINE app click on the start chat button, it will transfer the user to the chat website dedicated to them. Currently when processing on Android, everything is still displayed normally, but when I build on iOS, nothing is displayed.

Regarding the technology used, I use spring boot, thymeleaf combined with jQuery + LIFF SDK.

The process when init the screen I am processing: When init the screen for the first time, the backend will check the isInit variable passed is null, then it will return the html of that screen.
My Server:

  public String init(
      @RequestParam(value = "liffChannelId") String liffChannelId,
      @RequestParam(value = "messageChannelId") String messageChannelId,
      @RequestParam(value = "isInit", required = false) String isInit,
      @RequestParam(value = "idToken", required = false) String idToken,
      HttpServletRequest request, Model model) {
    if (Objects.isNull(isInit)) {
      return "s2013_chat";
    }

    ChatForm form = chatHelper.init(liffChannelId, messageChannelId, idToken, page, request);

    return "s2013_chat";
  }

And in my js:

$(document).ready(function () {
  const urlParams = new URLSearchParams(window.location.search);
  const isInit = urlParams.get("isInit");
  if (!isInit) {
    initLiffApp();
  }
});

function initLiffApp() {
  const messageChannelId = new URLSearchParams(window.location.search).get("messageChannelId");
  if (!messageChannelId) {
    alert("MessageChannelId is missing");
    return;
  }

  const liffChannelId = new URLSearchParams(window.location.search).get("liffChannelId");
  if (!liffChannelId) {
    alert("LiffChannelId is missing");
    return;
  }

  const liffId = new URLSearchParams(window.location.search).get("liffId");
  if (!liffId) {
    alert("LiffId is missing");
    return;
  }

  liff
    .init({
      liffId: liffId
    })
    .then(() => {
      const idToken = liff.getIDToken();
      if (!idToken) {
        alert("Failed to get ID Token");
        return;
      }
      sendToServer(liffChannelId, messageChannelId, idToken);
    })
    .catch(err => {
      console.error("LIFF init error", err);
    });
}

function sendToServer(liffChannelId, messageChannelId, idToken) {
  const redirectUrl = `/counseling/chat/client?liffChannelId=${encodeURIComponent(liffChannelId)}&messageChannelId=${encodeURIComponent(messageChannelId)}&isInit=1&idToken=${encodeURIComponent(idToken)}`;
  window.location.href = redirectUrl;
}

When returning for the first time, in js make a call to the liff server to get idToken and at this time will call back to the server 1 more time with isInit is true. At this time the backend will start processing. However, when building on iOS, I noticed that when init for the first time, it returns the screen UI without displaying anything (I think it’s due to the processing when isInit is null, it returns without calling liff anymore).

I tried commenting out the isInit variable check, and now the UI is displayed but does not receive any css and js events.

//if (Objects.isNull(isInit)) {
//   return "s2013_chat";
//}

I used Web Inspector on Safari browser to check and saw that the css and js files were loaded successfully, but the console log is reporting an error as shown.

enter image description here
enter image description here
enter image description here

Please help me with this problem, I have been trying to solve it for 3 days but still don’t know the reason why?