MetaMask Not Prompting Transaction Approval via WalletConnect in Mobile Chrome Browser

I’m building a decentralized application (dApp) using Web3Modal, WalletConnect, and ethers.js. The goal is to enable users to connect their mobile wallets (e.g., MetaMask, Trust Wallet) via WalletConnect and approve transactions directly from the mobile browser (Chrome).

Here’s what I’ve implemented:

WalletConnect Configuration: I disabled the QR code and configured the dApp to prompt the WalletConnect modal for mobile wallets.
Transaction Logic: After the wallet connects, I prepare and send a simple ETH transfer transaction using ethers.js.
However, MetaMask or Trust Wallet is not prompting for transaction approval after connecting. Here is my code:

import WalletConnectProvider from "@walletconnect/web3-provider";
import { ethers } from "ethers";
import { getAccount } from '@wagmi/core';

async function deposit() {
  try {
    console.log("calling deposit from wallet connect");

// Ensure the user is connected via Web3Modal
const account = getAccount(config);
console.log("account", account);

if (account.status === 'connected') {
  // Manually create a WalletConnect provider with QR code disabled
  const walletConnectProvider = new WalletConnectProvider({
    infuraId: 'YOUR_INFURA_PROJECT_ID', // Replace with your Infura Project ID
    qrcode: false, // Disable QR code
    qrcodeModalOptions: {
      mobileLinks: ["metamask", "trust"], // Supported mobile wallets
    },
  });

  // Enable session (this opens the mobile wallet modal)
  await walletConnectProvider.enable();

  // Use WalletConnect provider with ethers.js
  const web3Provider = new ethers.BrowserProvider(walletConnectProvider);
  const signer = await web3Provider.getSigner();
  const userAddress = await signer.getAddress(); // Ensure we get the user address

  console.log("Signer address:", userAddress);

  // Prepare and send the transaction (example: sending 0.01 ETH)
  const tx = {
    to: "0x8230aF7feCd83a49732854eDe52A466E949d6992", // Replace with recipient address
    value: ethers.parseEther("0.01") // Transaction amount (0.01 ETH)
  };

  // Send the transaction and wait for the wallet to prompt the user
  const transactionResponse = await signer.sendTransaction(tx);

  console.log("Transaction sent:", transactionResponse.hash);

  // Wait for the transaction to be confirmed
  await transactionResponse.wait();
  console.log("Transaction confirmed");

} else {
  console.error("No connected wallet. Please connect a wallet first.");
}


} catch (error) {
    console.error("Error sending transaction:", error);
    }
      }

   // Example usage: Call deposit when the button is clicked
   document.getElementById('deposit-button').addEventListener('click', async () => {
     await deposit();
  });

What I’ve Tried:

  1. Ensured that the WalletConnect modal opens correctly, but the
    transaction approval is never prompted.
  2. The mobile wallet (MetaMask, Trust Wallet) is connected properly,
    and I can retrieve the address, but the transaction does not prompt
    for approval.
  3. Verified that signer.getAddress() works and the signer is obtained
    correctly. Checked network settings (currently using Sepolia
    testnet).

Expected Behavior:
After connecting via WalletConnect on mobile Chrome, the connected wallet (e.g., MetaMask, Trust Wallet) should prompt the user to approve the transaction.

Actual Behavior:

  1. The wallet connects successfully, but no prompt appears for
    transaction approval. The transaction is not sent, and there are no
    errors in the console.
  2. If I remove qrcode: false, the qr code modal pops up but this doesn’t make sense for a mobile browser as the user would currently be busy using their phone on the dapp.

I’ve been stuck with this issue for over a week. I am using vanilla js unfortunately so I cannot use the react implementations

Blockquote

Seeking Advice on Optimizing the Tech Stack for My SaaS Web Project [closed]

I’m working on a SaaS-based web app project and could use some insights from the community. Here’s a quick rundown of my stack:

Frontend: Next.js
Backend: Node.js (TypeScript) REST APIs
Database: PostgreSQL
Real-time: Socket.io for chat and notifications
Other Tech: Planning to integrate Kafka and Redis soon
The app operates on a multi-tenant architecture, where companies register and I provide each company with separate databases and domains for their services. Everything is subscription-based. Now, I’m looking for advice on a few key areas:

Single API Endpoint for Multi-Tenant System: Should I stick with a single API block to serve all platforms, or could this approach become overloaded? Could it create bottlenecks or other issues at scale? I’m hosting on KVM v4 VPS with Hostinger, so I’m conscious of the limitations.

Tech Stack Adjustments: Do I need to rethink my current stack? I’ve had suggestions to adopt Docker for containerization—could this be beneficial for managing microservices? If so, how would it improve the current setup?

Subscription Management: What’s the best way to handle blocking access when a company’s subscription expires or goes unpaid? Should I disable API access, or is there a more effective method you’d recommend for this kind of scenario?

Kafka and Nginx: On the VPS, I’m running Nginx and planning to integrate Apache Kafka. I’ve been told that Nginx can act as a reverse proxy for Kafka (for example, using Kafka REST Proxy). Could someone explain the setup for this or point me to the best approach for handling it?

I appreciate any guidance or best practices you can share.

Thanks in advance!

Moeez Ahmed

I’m in the process of refurbishing my project and want to first confirm if my current tech stack is solid, especially since I’m planning to add Kafka and Redis for better performance. Additionally, I’m trying to understand how Docker can help improve my setup.

I’m also debating whether to use a single API to serve all tenants or provide each tenant with their own APIs to better handle workload and boost performance. Finally, regarding subscription control, on the API side, should I block API responses for tenants with expired subscriptions, and if so, what’s the best approach for implementing this?

Disable button for 5 seconds with different label and change after it

I’m trying to create an intro in my shiny app using the rintrojs package with the introjs function. My goal is to create an intro where the first next button is disabled for 5 seconds and has a different label like ‘Wait 5 seconds…’. It currently waits 5 seconds and changes from label but it isn’t disabled during the 5 seconds. So you can still click on it. Here is a reproducible example:

library(shiny)
library(rintrojs)

ui <- fluidPage(
  introjsUI(),
  actionButton("start_intro", "Start Intro"),
  h1("Welcome to the Shiny App"),
  p("This is some description of the app.")
)

server <- function(input, output, session) {
  
  steps <- reactive({
    data.frame(
      element = c(NA, "#start_intro"),
      intro = c("Welcome to the app! This first step has a custom button.",
                "This is the start button for the intro tour."),
      position = c("bottom", "bottom")
    )
  })
  
  observeEvent(input$start_intro, {
    introjs(session, 
            options = list(
              steps = steps(),
              nextLabel = "Wait 5 seconds..." 
            ),
            events = list(
              "onbeforechange" = I("
                if (this._currentStep === 0) {
                  var that = this;
                  var nextButton = document.querySelector('.introjs-nextbutton');
                  
                  if (nextButton) {
                    nextButton.innerHTML = 'Wait 5 seconds...';  // Initial label
                    nextButton.disabled = true;                  // Disable the button
                  }
                  
                  setTimeout(function() {
                    that._options.nextLabel = 'next'; // Change label after 5 seconds
                    that._introItems[0].nextLabel = 'next';
                    var nextButton = document.querySelector('.introjs-nextbutton');
                    if (nextButton) {
                      nextButton.innerHTML = 'next';  // Update the label to 'next'
                      nextButton.disabled = false;    // Enable the button after 5 seconds
                    }
                  }, 5000); // 5 seconds delay
                }
              ")
            )
    )
  })
}
 
shinyApp(ui = ui, server = server)

Output:

enter image description here

As you can see it create the ‘Wait 5 seconds…’ button which is also shown for 5 seconds, but it is not disabled during the 5 seconds. So I was wondering how we can create a button which changes from label after 5 seconds and is disabled during the 5 seconds?

Outlook calendar don’t render with FullCalendar

I am developing an app to see the events on my Outlook calendar using fullcalendar, the problem is that I log in to Microsoft, in principle everything is correct, I return to my website but the calendar is not generated, what’s more, if I click again The login button displays a message that the login is still in progress (errorCode === "interaction_in_progress") and i get the console log ‘im inside the else (accounts.length)’ .

This is my code, I can’t find what is causing the calendar and events to not load.

<div id="calendar"></div>

<script>
    let msalInstance;
    const loginRequest = {
        scopes: ["User.Read", "Calendars.Read", "Calendars.Read.Shared"]
    };

    async function mostrarCalendarioOutlook() {
        console.log('I am inside of mostrarCalendarioOutlook');
        try {
            if (!msalInstance) {
                throw new Error("msalInstance is not initialized");
            }
            const accounts = msalInstance.getAllAccounts();
            if (accounts.length > 0) {
                console.log('Dentro del if (accounts.length > 0)');
                const account = accounts[0];
                const tokenResponse = await msalInstance.acquireTokenSilent({
                    account,
                    scopes: ["User.Read", "Calendars.Read", "Calendars.Read.Shared"]
                });
                const events = await getCalendarEvents(tokenResponse.accessToken);
                console.log('initializing render calendar function');
                renderCalendar(events);
            } else {                
                console.log('im inside the else (accounts.length)');
                await msalInstance.loginRedirect(loginRequest);
            }
        } catch (error) {                        
            handleError(error);            
        }
    }

    function handleError(error) {
        if (error.errorCode === "interaction_in_progress") {
            Swal.fire({
                    icon: 'info',
                    title: 'Proceso en progreso',
                    text: 'El proceso de inicio de sesión está en progreso. Por favor, espera a que se complete.',
                    allowOutsideClick: false
                });
        } else if (error.errorCode === "consent_required" || error.errorCode === "interaction_required") {
            Swal.fire({
                icon: 'error',
                title: 'Permisos necesarios',
                text: 'El administrador debe conceder los permisos necesarios para acceder a los calendarios. Contacta al administrador.'
            });
        } else if (error.errorCode === "access_denied") {
            Swal.fire({
                icon: 'error',
                title: 'Acceso denegado',
                text: 'No se pudo acceder a los datos solicitados. Verifica los permisos y vuelve a intentarlo.'
            });
        } else {
            Swal.fire({
                icon: 'error',
                title: 'Error de autenticación',
                text: 'Ocurrió un error durante la autenticación. Por favor, inténtalo de nuevo más tarde.'
            });
            console.error('Error durante la autenticación:', error);
        }
    }    

    document.addEventListener('DOMContentLoaded', async function() {                
        try {
            const msalConfig = {
                auth: {
                    clientId: "Client_ID", 
                    authority: "https://login.microsoftonline.com/common",                    
                    redirectUri: "redirect_Uri",
                    popUp: true
                }
            };

            msalInstance = new msal.PublicClientApplication(msalConfig);            

            //EVENTS
            async function getCalendarEvents(accessToken) {
                console.log('im inside of getCalendarEvents');
                const response = await fetch('https://graph.microsoft.com/v1.0/me/events', {
                    headers: {
                        'Authorization': `Bearer ${accessToken}`
                    }
                });

                if (!response.ok) {
                    const errorText = await response.text();
                    console.error(`Error al obtener los eventos del calendario: ${response.status} ${response.statusText}`, errorText);
                    throw new Error('Error al obtener los eventos del calendario');
                }

                const data = await response.json();
                const events = [];

                function adjustToLocalTime(dateTime) {
                    const date = new Date(dateTime);
                    const timeZoneOffset = date.getTimezoneOffset() * 60000;
                    return new Date(date.getTime() - timeZoneOffset).toISOString();
                }

                const recurringEvents = data.value.filter(event => event.recurrence && event.recurrence.pattern);

                recurringEvents.forEach(event => {
                    const startDate = new Date(event.start.dateTime);
                    const endDate = new Date(event.end.dateTime);
                    const recurrence = event.recurrence.pattern;
                    let instanceDate = new Date(startDate);
                    const endRecurrenceDate = event.recurrence.range && event.recurrence.range.endDate ? new Date(event.recurrence.range.endDate) : null;

                    while (!endRecurrenceDate || instanceDate <= endRecurrenceDate) {
                        if (!recurrence.daysOfWeek) {
                            const adjustedStartDate = new Date(instanceDate);
                            adjustedStartDate.setHours(startDate.getHours());
                            adjustedStartDate.setMinutes(startDate.getMinutes());

                            const adjustedEndDate = new Date(instanceDate);
                            adjustedEndDate.setHours(endDate.getHours());
                            adjustedEndDate.setMinutes(endDate.getMinutes());

                            if (adjustedStartDate <= endRecurrenceDate || !endRecurrenceDate) {
                                events.push({
                                    title: event.subject,
                                    start: adjustToLocalTime(adjustedStartDate.toISOString()),
                                    end: adjustToLocalTime(adjustedEndDate.toISOString()),
                                    allDay: event.isAllDay
                                });
                            }

                            switch (recurrence.type) {
                                case "daily":
                                    instanceDate.setDate(instanceDate.getDate() + recurrence.interval);
                                    break;
                                case "absoluteMonthly":
                                    instanceDate.setMonth(instanceDate.getMonth() + recurrence.interval);
                                    break;
                                case "absoluteYearly":
                                    instanceDate.setFullYear(instanceDate.getFullYear() + recurrence.interval);
                                    break;
                            }

                            continue;
                        }

                        const daysOfWeekIndices = (recurrence.daysOfWeek || []).map(day => {
                            switch (day.toLowerCase()) {
                                case "monday":
                                    return 1;
                                case "tuesday":
                                    return 2;
                                case "wednesday":
                                    return 3;
                                case "thursday":
                                    return 4;
                                case "friday":
                                    return 5;
                                case "saturday":
                                    return 6;
                                case "sunday":
                                    return 0;
                            }
                        });

                        daysOfWeekIndices.forEach(dayIndex => {
                            let tempDate = new Date(instanceDate);
                            while (tempDate.getDay() !== dayIndex) {
                                tempDate.setDate(tempDate.getDate() + 1);
                            }

                            if (tempDate >= startDate && (!endRecurrenceDate || tempDate <= endRecurrenceDate)) {
                                const adjustedStartDate = new Date(tempDate);
                                adjustedStartDate.setHours(startDate.getHours());
                                adjustedStartDate.setMinutes(startDate.getMinutes());

                                const adjustedEndDate = new Date(tempDate);
                                adjustedEndDate.setHours(endDate.getHours());
                                adjustedEndDate.setMinutes(endDate.getMinutes());

                                if (adjustedStartDate <= endRecurrenceDate || !endRecurrenceDate) {
                                    events.push({
                                        title: event.subject,
                                        start: adjustToLocalTime(adjustedStartDate.toISOString()),
                                        end: adjustToLocalTime(adjustedEndDate.toISOString()),
                                        allDay: event.isAllDay
                                    });
                                }
                            }
                        });

                        instanceDate.setDate(instanceDate.getDate() + 7 * recurrence.interval);
                    }

                    if (endRecurrenceDate && recurrence.daysOfWeek) {
                        const tempDate = new Date(endRecurrenceDate);
                        const endRecurrenceDay = tempDate.toLocaleString('en-US', {
                            weekday: 'long'
                        }).toLowerCase();
                        if (recurrence.daysOfWeek.includes(endRecurrenceDay)) {
                            const adjustedStartDate = new Date(tempDate);
                            adjustedStartDate.setHours(startDate.getHours());
                            adjustedStartDate.setMinutes(startDate.getMinutes());

                            const adjustedEndDate = new Date(tempDate);
                            adjustedEndDate.setHours(endDate.getHours());
                            adjustedEndDate.setMinutes(endDate.getMinutes());

                            if (adjustedStartDate.getTime() !== endRecurrenceDate.getTime()) {
                                events.push({
                                    title: event.subject,
                                    start: adjustToLocalTime(adjustedStartDate.toISOString()),
                                    end: adjustToLocalTime(adjustedEndDate.toISOString()),
                                    allDay: event.isAllDay
                                });
                            }
                        }
                    }
                });

                const singleEvents = data.value.filter(event => !event.recurrence);
                singleEvents.forEach(event => {
                    events.push({
                        title: event.subject,
                        start: adjustToLocalTime(event.start.dateTime),
                        end: adjustToLocalTime(event.end.dateTime),
                        allDay: event.isAllDay
                    });
                });

                //console.log("Eventos procesados FINAL:", events);

                return events;
            }

            async function handleLogoutClick() {
                console.log('Cerrando sesion Microsoft...');
                Swal.fire({
                    title: 'Cerrando sesión...',
                    allowOutsideClick: false,
                    didOpen: () => {
                        Swal.showLoading();
                    },
                });

                try {
                    const accounts = await msalInstance.getAllAccounts();
                    if (accounts.length === 0) {
                        Swal.close();
                        return;
                    }

                    const respuesta = await msalInstance.logoutPopup({
                        account: accounts[0],
                    });

                    if (respuesta) {
                        localStorage.setItem('logoutCompleted', 'true');
                        console.log('Sesión Microsoft cerrada correctamente');
                    } else {
                        localStorage.setItem('logoutCompleted', 'false');
                        console.log('No se cerró sesión');
                    }

                    Swal.close();

                } catch (error) {
                    Swal.fire({
                        icon: 'error',
                        title: 'Error al cerrar sesión',
                        text: 'Ocurrió un error al intentar cerrar sesión. Por favor, inténtalo de nuevo más tarde.'
                    });
                    console.log('Error al cerrar sesión Microsoft', error);
                } finally {
                    Swal.close();
                }
            }

            function renderCalendar(events) {
                console.log('Entro a la funcion renderCalendar');
                const calendarEl = document.getElementById('calendar');
                const calendar = new FullCalendar.Calendar(calendarEl, {
                    customButtons: {
                        myCustomButton: {
                            text: 'Refrescar',
                            click: async function() {
                                console.log('Refrescando calendario...');
                                Swal.fire({
                                    title: 'Actualizando Calendario...',
                                    allowOutsideClick: false,
                                    didOpen: () => {
                                        Swal.showLoading();
                                    }
                                });

                                try {
                                    const accounts = await msalInstance.getAllAccounts();
                                    if (accounts.length === 0) {
                                        await msalInstance.loginRedirect(loginRequest);
                                        return;
                                    }

                                    const response = await msalInstance.acquireTokenSilent({
                                        account: accounts[0],
                                        scopes: ["User.Read", "Calendars.Read", "Calendars.Read.Shared"]
                                    });

                                    if (response !== null) {
                                        const accessToken = response.accessToken;
                                        const events = await getCalendarEvents(accessToken);
                                        renderCalendar(events);
                                        Swal.close();
                                        console.log('Calendario refrescado correctamente');
                                    } else {
                                        console.error('No se pudo obtener el token de acceso.');
                                        console.log('Calendario NO refrescado');
                                        Swal.close();
                                    }
                                } catch (error) {
                                    console.log('Error al refrescar calendario');
                                    handleError(error);
                                }
                            }
                        },
                        logout: {
                            text: 'Cerrar Sesión',
                            click: function() {
                                handleLogoutClick();
                            }
                        }
                    },
                    headerToolbar: {
                        left: 'prev,next today myCustomButton logout',
                        center: 'title',
                        right: 'dayGridMonth,timeGridWeek,timeGridDay'
                    },
                    buttonText: {
                        today: 'Hoy',
                        month: 'Mes',
                        week: 'Semana',
                        day: 'Día',
                        list: 'Lista'
                    },
                    initialView: 'dayGridMonth',
                    locale: <?php echo '"' . session('language') . '"'; ?>, //He añadido la seleccion automatica de locale
                    firstDay: 1,
                    events: events,
                    dayMaxEvents: true,
                    eventClick: function(info) {
                        const event = info.event;
                        const title = event.title;
                        const start = event.start;
                        const end = event.end;
                        const allDay = event.allDay;
                        const location = event.extendedProps.location;

                        const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

                        const startFormatted = start.toLocaleString('es-ES', {
                            timeZone: timeZone
                        });
                        const endFormatted = end ? end.toLocaleString('es-ES', {
                            timeZone: timeZone
                        }) : 'Evento de todo el día';

                        let content = `<h2>${title}</h2>`;
                        if (!allDay) {
                            content += `<p><strong>Inicio:</strong> ${startFormatted}</p>`;
                            content += `<p><strong>Fin:</strong> ${endFormatted}</p>`;
                        } else {
                            content += `<p><strong>Evento de todo el día</strong></p>`;
                        }
                        if (location) {
                            content += `<p><strong>Ubicación:</strong> ${location}</p>`;
                        }

                        Swal.fire({
                            title: 'Información del Evento',
                            html: content,
                            icon: 'info'
                        });

                        console.log('Infomacion:' + info.event);
                        console.log('Titulo:' + title);
                        console.log('Inicio:' + start);
                        console.log('Fin:' + end);
                        console.log('Evento Diario:' + allDay);
                    }
                });
                calendar.render();
            }
        } catch (error) {
            console.error('Error during initialization:', error);
            Swal.fire({
                icon: 'error',
                title: 'Error de inicialización',
                text: 'Ocurrió un error al cargar la configuración. Por favor, inténtalo de nuevo más tarde.'
            });
        }
    });
</script>

Thank you very much!!

Prism js AutoLoader does not work when i’m getting text to be rendered in realtime via a websocket

So i’m trying to implement my own ai code assistant chat in vscode,so i used marked js for parsing the text output i get from the backend via openAI api and stream those values to the frontend which works well and good,but i’m having issues with prism js for syntax highlighting because it’s not working at all and i can’t debug why,it actually worked when i added a code block statically to my html page but hasn’t since i have been getting values to be parsed from the server. because the entire html script is long i will divide the snippets into smaller reader chunks that’s most important.
so here’s where i’m adding prism js cdns needed :

<!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
                <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
                <!-- Prism.js Core CSS -->
                <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet">
                <!-- Prism.js Core JS -->
                <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js" integrity="sha512-7Z9J3l1+EYfeaPKcGXu3MS/7T+w19WtKQY/n+xzmw4hZhJ9tyYmcUS+4QqAlzhicE5LAfMQSF3iFTK9bQdTxXg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
                <!-- Prism.js Autoloader Plugin -->
                <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js" integrity="sha512-SkmBfuA2hqjzEVpmnMt/LINrjop3GKWqsuLSSB3e7iBmYK7JuWw4ldmmxwD9mdm2IRTTi0OxSAfEGvgEi0i2Kw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
                

                <title>Chat UI</title>

This is my script section where i basically do all the parsing :

<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
                <script>
                    
                    const vscode = acquireVsCodeApi();
                    //const chatInput = document.getElementById('chat-input');
                    //const sendButton = document.querySelector('.send-btns');
                    const chatBox = document.querySelector('.chatbox');

                    function generateUUID() {
                        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                            var r = Math.random() * 16 | 0,
                                v = c === 'x' ? r : (r & 0x3 | 0x8);
                            return v.toString(16);
                        });
                    }

                    function typeText(element, text, speed = 20) {
                        let index = 0;
                        let html = '';
                        
                        function type() {
                            if (index < text.length) {
                                if (text.charAt(index) === '<') {
                                    // Handle HTML tags
                                    let tag = '';
                                    while (text.charAt(index) !== '>' && index < text.length) {
                                        tag += text.charAt(index);
                                        index++;
                                    }
                                    tag += '>';
                                    html += tag;
                                    index++;
                                } else {
                                    // Handle text
                                    html += text.charAt(index);
                                    index++;
                                }
                                element.innerHTML = html;
                                setTimeout(type, speed);
                            }
                        }
                    
                        type();
                    }

                    function sendMessage(){
                        const chatBox = document.getElementById('chatbox');
                        const chatInput = document.getElementById('chat-input');
                        const message = chatInput.value;
                        if (message.trim()) {
                            vscode.postMessage({ command: 'sendMessage', value:{
                                "project_path":"random",
                                "storage_name":"PreciousKent8Storage",
                                "user_prompt":message,
                                "thread_id":"thread_YiYMOcOKifXsKbAYRbAXuZGF",
                                "attachments":[
                                    {
                                      "file_id": "file-gXrvfXdCGAbCy2uswrEwCUoY",
                                      "tools": [
                                        {
                                          "type": "file_search"
                                        }
                                      ]
                                    }
                                  ]}
                            })
                            const userMessageDiv = document.createElement('div');
                            userMessageDiv.classList.add('user-message-div');
                            userMessageDiv.innerHTML = `
                                <div class="profile-img-div">
                                    <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi67elRmCcCkrdJ36cRr6NJCKslrOl7eMTotxXVvBCaYJuBadcb5PxaYm8k9wnmOw8CgoAS9jVAVA1aA7uTcNMa1fhhOXaSX_eucNfmpomSZLPSezm_TH9qa4jYcB54DlOhZdjA3UZz1r3SGnc1uQCd5IQJtwV7Ubm_suNz0U6xHNb5cg/s220/IMG_20240415_205336_841.jpg" alt="User Image"/>
                                </div>
                                <div id="user-message-${generateUUID()}" class="user-message-box">
                                    ${message}
                                </div>
                            `;
                            chatbox.appendChild(userMessageDiv);
                            chatInput.value='';
                        }
                    }

                    function ParseMessage(text){
                        const renderer = new marked.Renderer();
                        renderer.code = (code, language) => {
                            // Define a base class for all code blocks
                            let langBlock="language-"+code.lang
                            
                
                            
                            //console.log("let's see lang",code);
                
                            // Return custom HTML for the code block
                            
                            return `<div class="code-block">
                                            <div class="code-toolbar">
                                                <div class="language-name">${code.lang}</div>
                                                <div class="toolbar-actions">
                                                    <button id="copy-code"><i class="fas fa-clipboard"></i> &nbsp; Copy Code</button>
                                                    <button id="add-to-file"><i class="fa-solid fa-file"></i> &nbsp; Add to File</button>
                                                    <button id="create-new-file"><i class="fa-solid fa-file"></i> &nbsp;Create New File</button>
                                                </div>
                                            </div>
                                            <pre class="scroll-container"><code class=langBlock>${code.text}</code></pre>
                                    </div>`
                        };
                
                        // Set options for marked.js with custom renderer
                        marked.setOptions({
                            renderer: renderer,
                            langPrefix: '' // Prevent marked.js from adding its own lang class
                        });
                        const htmlContent = marked.parse(text);
                        return htmlContent;
                    }

                    // Handle messages from the extension
                    window.addEventListener('message', event => {
                        const message = event.data; // The message sent from the extension
                        switch (message.command) {
                            case 'receiveMessage':
                                const questionId=message.data.question_id;
                                if(localStorage.getItem(questionId)==null){
                                    const aiMessageDiv = document.createElement('div');
                                    aiMessageDiv.classList.add('message-div');
                                    aiMessageDiv.innerHTML = `
                                        <div class="ai-profile-img-div">
                                            <img src="../ai-image" alt="AI Image"/>
                                        </div>
                                        <div id="ai-reply-${message.data.question_id}" class="ai-message-box">
                                            ${ParseMessage(message.data.message.value)}
                                        </div>
                                    `;
                                    document.querySelector('.chatbox').appendChild(aiMessageDiv);
                                    localStorage.setItem(questionId, questionId);
                                }else{
                                    current_message=document.getElementById(`ai-reply-${questionId}`);
                                    current_message.innerHTML='';
                                    typeText(current_message,ParseMessage(message.data.message.value))

                                }
                                
                                
                                break;
                        }
                    });

                    document.addEventListener('DOMContentLoaded', () => {
                        vscode.postMessage({ 
                            command: 'sendMessage', 
                            value: {
                                "project_path":"random",
                                "storage_name":"PreciousKent8Storage"
                            }
                        });
                    });

                    function addScrollListener(scrollElement) {
                        let isScrolling;
                      
                        // Event listener to show the scrollbar thumb on scroll
                        scrollElement.addEventListener('scroll', () => {
                          scrollElement.classList.add('show-scroll');
                      
                          // Clear the timeout for continuous scrolling
                          clearTimeout(isScrolling);
                      
                          // Remove the class after scrolling stops
                          isScrolling = setTimeout(() => {
                            scrollElement.classList.remove('show-scroll');
                          }, 1000); // 1 second delay after scroll stops
                        });
                      }

                    const scrollElements = document.querySelectorAll('.scroll-container');
                    scrollElements.forEach(scrollElement=>{
                        addScrollListener(scrollElement);
                    });

                    
                </script>

so this part of the code :

// Handle messages from the extension
                    window.addEventListener('message', event => {
                        const message = event.data; // The message sent from the extension
                        switch (message.command) {
                            case 'receiveMessage':
                                const questionId=message.data.question_id;
                                if(localStorage.getItem(questionId)==null){
                                    const aiMessageDiv = document.createElement('div');
                                    aiMessageDiv.classList.add('message-div');
                                    aiMessageDiv.innerHTML = `
                                        <div class="ai-profile-img-div">
                                            <img src="../ai-image" alt="AI Image"/>
                                        </div>
                                        <div id="ai-reply-${message.data.question_id}" class="ai-message-box">
                                            ${ParseMessage(message.data.message.value)}
                                        </div>
                                    `;
                                    document.querySelector('.chatbox').appendChild(aiMessageDiv);
                                    localStorage.setItem(questionId, questionId);
                                }else{
                                    current_message=document.getElementById(`ai-reply-${questionId}`);
                                    current_message.innerHTML='';
                                    typeText(current_message,ParseMessage(message.data.message.value))

                                }
                                
                                
                                break;
                        }
                    });

is basically the entry point where i get the values from my websocket server.
my current css styles for the code blocks are below(the ones to change the token styles do not work at all) :

               .code-block {
                        position: relative;
                        background: black; 
                        border-radius: 8px; /* Rounded corners */
                        margin-top:0.6rem;
                        margin-bottom:0.6rem;
                        margin-right:1rem;
                        overflow: hidden;
                        padding-top:2rem!important;
                        box-sizing: border-box;
                    }
            
                    .code-toolbar {
                        position: absolute;
                        top: 0;
                        left: 0;
                        right: 0;
                        background: #333;
                        color: #fff;
                        display: flex;
                        justify-content: space-between;
                        align-items: center;
                        padding: 0.5rem;
                        font-family: 'Roboto', sans-serif;
                        z-index: 10;
                        box-sizing: border-box;
                    }
            
                    .code-toolbar .toolbar-actions {
                        display: flex;
                        gap: 0.5rem;
                        box-sizing: border-box;
                    }
            
                    .code-toolbar button {
                        background: transparent;
                        display:flex;
                        color: #fff;
                        border: none;
                        border-radius: 4px;
                        padding: 0.5rem;
                        cursor: pointer;
                        box-sizing: border-box;
                    }
            
                    .code-toolbar button:hover {
                        background: transparent;
                    }
            
                    .code-toolbar .language-name {
                        font-weight: 400;
                        color:#a3a2a2;
                    }
            
                    pre {
                        margin: 0;
                        background-color:transparent!important;
                        padding: 1rem;
                    }
            
                    code {
                        display: block;
                        background-color:transparent!important;
                    }

                    /* Custom styles for specific tokens */
                    .token.function {
                    color: #ffcc00;  /* Custom color for function names */
                    }

                    .token.class-name {
                    color: #ff6b6b;  /* Custom color for class names */
                    }

                    .token.variable {
                    color: #5ccfe6;  /* Custom color for variables */
                    }

                    .token.comment {
                    color: #6a9955;  /* Custom color for comments */
                    }

                    .token.keyword {
                    color: #569cd6;  /* Custom color for keywords */
                    }

                    .token.string {
                    color: #ce9178;  /* Custom color for strings */
                    }

How to resolve “useFipsEndpoint: options.useFipsEndpoint ?? false, SyntaxError: Unexpected token ‘?’ “

Before today everything was working fine but somehow now I am getting this error:

useFipsEndpoint: options.useFipsEndpoint ?? false, SyntaxError: Unexpected token ‘?’

My current node version of the project is 12.18.3.

I tried to change the ?? to || as suggested by many posts but there are many packages which uses that and at each time the error occurs in different files.

I also tried to upgrade the Node version, but that is currently not possible. Below is one of the examples :

Debugger attached.
Waiting for the debugger to disconnect...
/Users/abc/Desktop/Projectname/modules/winston-helper/node_modules/@aws-sdk/client-s3/dist-cjs/index.js
    useFipsEndpoint: options.useFipsEndpoint ?? false;
/Users/abc/Desktop/Projectname/modules/winston-helper/node_modules/@smithy/smithy-client/dist-cjs/index.js:323
    this.input = input ?? {};
                        ^

How can i make a select start at a specific point without using selected

We have this select to select year of birth.
Looking at the statistics of last couple of years, most users (close to 70%) are between the ages of 26-34.
When the user opens the select, We want it to start at around 1994 (or age 30), but without selecting ‘1994’ as a default, we can’t seem to make this work.

I do not want 1994 selected by default, as I want to check if the select is actually selected.

This is our current setup for the select:

<select name="year" required>
   <option value="" disabled selected> - </option>
   <?php for ($i = date('Y') - 110; $i <= date('Y'); $i++) : ?>
      <option value="<?php echo $i; ?>" <?php if ($i == $year) echo 'selected'; ?>>
         <?php echo $i; ?>
      </option>
    <?php endfor; ?>
</select>

I’ve looked for a javascript/jquery solution. Found and tried this:

$(document).ready(function() {
            
            const yearToScroll = 1994;
            const birthYearSelect = $('#geboortedatum_jaar');

            // Find the option index of 1994
            const optionIndex = birthYearSelect.find('option[value="' + yearToScroll + '"]').index();

            // Set the scroll position of the dropdown to show 1994
            birthYearSelect.prop('selectedIndex', -1); // Ensures no option is selected
            birthYearSelect[0].selectedIndex = optionIndex;
            
});

But this still selects the ‘1994’ option, making it no different from just putting selected on the 1994 option and not just scroll to that position when opening the select.

How to override a behavior of __webpack_require__ function?

I encountered a problem with my project. For sharing modules, I use the require() function, which, as I know, evaluates the entire code of the module and encapsulates it in another function. However, I would like to reduce the amount of code that is evaluated in order to not include components if they are not used in the template.

For example, I have components Page, Button1, Button2. The Page component has 2 dependencies: Button1 and Button2, but only Button1 is used in the template of the Page component. Therefore, I would like not to include the dependency Button2 in the Page component.

I’d like to change the logic of function webpack_require for cancel component code evaluation if this component isn’t used.

I used DefinePlguin and ProvidePlugin of webpack for overriding the webpack_require function, but it didn’t work 🙁

Can I make the browser default handler run before the event propagates?

The browser does not process keystrokes in a textbox (<input type="text">) until after all JS event handlers are finished.

In my app, though, I have a textbox nested inside an outer widget. The outer widget is not aware of the textbox’s existence, but I want to block it from processing keystrokes if the textbox is able to handle the same keystrokes. So I want to do something like this:

function onInputKeyDown(e) {
  const textbox = e.target as HTMLInputElement;
  const selStart = textbox.selectionStart, selEnd = textbox.selectionEnd;
  const content = textbox.textContent;

  e.invokeDefault() // doesn't exist

  if (selStart !== textbox.selectionStart || selEnd !== textbox.selectionEnd
      || content !== textbox.textContent)
    e.stopPropagation();
}

I tried simulating “invokeDefault” with e.preventDefault(); e.target.dispatchEvent(new KeyboardEvent('keydown', e)) but it turns out that dispatchEvent doesn’t cause default behavior, it just calls event handlers (the current event handler is re-entered) so the text field doesn’t change. Is there another way?

DiscordJS V14 Marriage Command Not Responding with no Error in Console [closed]

So, for context, this is the only command that is currently doing this. It is giving absolutely nothing in the console and it says on Discord “The application did not respond.”. It seems to be correct, I’m just not sure why it isn’t working. Here is the code:

const family = require("../../schemas/familySchema.js");
const {
  SlashCommandBuilder,
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  EmbedBuilder,
  ComponentType,
} = require("discord.js");
const mongoose = require("mongoose");

module.exports = {
  cooldown: 10,
  data: new SlashCommandBuilder()
    .setName("family")
    .setDescription("Handle all Family related tasks.")
    .addSubcommand((subcommand) =>
      subcommand
        .setName("marry")
        .setDescription("Lets you propose to another user.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to Marry.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("divorce")
        .setDescription("Divorce you from one of your partners.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to Divorce.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("adopt")
        .setDescription("Adopt another user into your family.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to Adopt.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("disown")
        .setDescription("Removes someone from being your child.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to Disown.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("makeparent")
        .setDescription("Picks a user that you want to be your parent.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to be your Parent.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("runaway")
        .setDescription("Removes your parent.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to remove as your parent.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("partner")
        .setDescription("Tells you who a user is married to.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to know the partners of.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("children")
        .setDescription("Tells you who a user's children are.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to know the children of.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("sibling")
        .setDescription("Tells you who a user's siblings are.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to know the siblings of.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("parent")
        .setDescription("Tells you who someone's parents are.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick who you want to know the parents of.")
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("familytree")
        .setDescription("Gets the full family tree of a user.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription(
              "Pick who you want to know the family tree of.",
            )
            .setRequired(true),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName("relationship")
        .setDescription("Gets the relationship between two users.")
        .addUserOption((option) =>
          option
            .setName("target")
            .setDescription("Pick the first user.")
            .setRequired(true),
        )
        .addUserOption((option) =>
          option
            .setName("othertarget")
            .setDescription("Pick the second user.")
            .setRequired(true),
        ),
    ),

  async execute(interaction) {
    const target = interaction.options.getUser("target");
    const user = await interaction.guild.members.fetch(
      interaction.user.id,
    );
    const check = family.findOne({ userid: user.id });
    const checkTarget = family.findOne({ userid: target.id });

    switch (interaction.options.getSubCommand) {
      case "marry": {
        if (!check) {
          check = new family({
            _id: new mongoose.Types.ObjectId(),
            userid: user.id,
            partnerids: [],
            childrenids: [],
            parentids: [],
            siblingids: [],
          });
        }

        if (!checkTarget) {
          check = new family({
            _id: new mongoose.Types.ObjectId(),
            userid: target.id,
            partnerids: [],
            childrenids: [],
            parentids: [],
            siblingids: [],
          });
        }

        const ido = new ButtonBuilder()
          .setCustomId("ido")
          .setLabel("I do")
          .setStyle(ButtonStyle.Success);

        const no = new ButtonBuilder()
          .setCustomId("no")
          .setLabel("No")
          .setStyle(ButtonStyle.Danger);

        const marryRow = new ActionRowBuilder().addComponents(ido, no);

        await interaction.channel.send({
          content: `Will you marry <@${user.id}>? <@${target.id}>`,
          components: [marryRow],
        });

        const filter = (i) => i.user.id === target.id;

        const collector = reply.createMessageComponentCollector({
          ComponentType: ComponentType.Button,
          filter,
        });

        collector.on("collect", (interaction) => {
          if (interaction.customId === "ido") {
            try {
              check.partnerids.push(target.id);
              checkTarget.partnerids.push(user.id);
            } catch (e) {
              return console.log(`An error occured!`);
            }

            const embed = new EmbedBuilder()
              .setTitle(
                `${user.displayName} and ${target.displayName} got hitched!`,
              )
              .setColor(0x0099ff);

            interaction.channel.send({ embeds:  });
          }

          if (interaction.customId === "no") {
            const embed = new EmbedBuilder()
              .setTitle(
                `${target.displayName} declined ${user.displayName}!`,
              )
              .setColor(0x0099ff);

            interaction.channel.send({ embeds:  });
          }
        });

        await check.save().catch(console.error);
      }
    }
  },
};

I’ve tried looking around, but could not find any information that would help me resolve the issue. For reference, I’m not done. I am simply trying to test the first concept to see if it works.

Safari Page Load Animation Issue on First Access

I’m experiencing a challenging issue with Safari concerning the page load animation. Specifically, when I first open the main page, the load animation doesn’t initiate. However, if I navigate away to another page and then return to the main page, the animation starts functioning as expected.

I don’t believe the animation properties is the problem, as the animation plays correctly after navigating to another page and then returning to the main page.

Intriguingly, this problem does not occur in Chrome, where the page load animation works perfectly from the first visit.

Safari Version I am testing on: Safari 17.6 (19618.3.11.11.5)
I also checked on old safari versions on browserstack. The issue is consistent on all safari on all devices (ios, macOs, ipad).

Below is the animation properties I am using

.slideUp {
  animation: slide-up 20s alternate linear infinite;
  --webkit-animation: slide-up 20s alternate linear infinite;

}

@keyframes slide-up {
  0% {
    transform: translateY(0);
  }

  100% {
    transform: translateY(-50%);
  }
}

Error: Timeout – Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL) at

I am getting following error when ran the unit tests in pipeline for an angular app.

Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)
        at <Jasmine>

But when ran the same in local system dont see any issues. It works fine. All the tests pass without any issue.

Node version: v16.20.2
NPM version: 8.19.4

Package.json is

{
  "name": "abc",
  "private": true,
  "version": "1.0.0",
  "description": "abc",
  "scripts": {
    "ng": "ng",
    "update": "npm update --registry=https://registry.npmjs.org/",
    "audit": "npm audit --registry=https://registry.npmjs.org/",
    "start": "ng serve",
    "build": "ng build --configuration production",
    "build:dev": "ng build"
  },
  "dependencies": {
    "@amplitude/analytics-browser": "~1.3.0",
    "@angular/animations": "~15.2.9",
    "@angular/cdk": "~15.2.9",
    "@angular/common": "~15.2.9",
    "@angular/compiler": "~15.2.9",
    "@angular/core": "~15.2.9",
    "@angular/forms": "~15.2.9",
    "@angular/material": "~15.2.9",
    "@angular/material-moment-adapter": "~15.2.9",
    "@angular/platform-browser": "~15.2.9",
    "@angular/platform-browser-dynamic": "~15.2.9",
    "@angular/router": "~15.2.9",
    "@azure/storage-blob": "~10.5.0",
    "@jaames/iro": "~5.5.2",
    "@ngrx/effects": "~15.4.0",
    "@ngrx/store": "~15.4.0",
    "@ngrx/store-devtools": "~15.4.0",
    "@ngx-translate/core": "~14.0.0",
    "@ngx-translate/http-loader": "~7.0.0",
    "class-transformer": "~0.5.1",
    "class-validator": "~0.14.0",
    "d3": "~7.9.0",
    "file-saver": "~2.0.5",
    "jwt-decode": "~3.1.2",
    "lodash": "~4.17.21",
    "moment": "~2.29.4",
    "moment-timezone": "~0.5.43",
    "rxjs": "~7.5.7",
    "rxjs-compat": "~6.6.7",
    "sha.js": "~2.4.11",
    "typescript-collections": "~1.3.3",
    "zone.js": "~0.11.8"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~15.2.8",
    "@angular-eslint/builder": "15.2.1",
    "@angular-eslint/eslint-plugin": "15.2.1",
    "@angular-eslint/eslint-plugin-template": "15.2.1",
    "@angular-eslint/schematics": "15.2.1",
    "@angular-eslint/template-parser": "15.2.1",
    "@angular/cli": "~15.2.8",
    "@angular/compiler-cli": "~15.2.9",
    "@angular/language-service": "~15.2.9",
    "@types/bingmaps": "7.0.20",
    "@types/d3": "~7.4.0",
    "@types/file-saver": "~2.0.7",
    "@types/jasmine": "~4.3.4",
    "@types/lodash": "~4.14.195",
    "@types/moment-timezone": "~0.5.30",
    "@types/node": "~20.3.1",
    "@typescript-eslint/eslint-plugin": "~5.43.0",
    "@typescript-eslint/parser": "~5.43.0",
    "codelyzer": "~6.0.2",
    "concurrently": "~7.4.0",
    "eslint": "~8.28.0",
    "jasmine-core": "~4.4.0",
    "jasmine-expect": "~5.0.0",
    "jasmine-marbles": "~0.9.2",
    "jasmine-spec-reporter": "~7.0.0",
    "karma": "~6.4.3",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~3.0.3",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "karma-junit-reporter": "~2.0.1",
    "reflect-metadata": "~0.1.13",
    "tslint": "~6.1.3",
    "typescript": "~4.9.5"
  }
}

Following is the karma.config.json

module.exports = function (config) {
    config.set({
        basePath: '../',
        frameworks: ['jasmine', '@angular-devkit/build-angular'],
        plugins: [
            require('karma-jasmine'),
            require('karma-coverage'),
            require('karma-chrome-launcher'),
            require('karma-jasmine-html-reporter'),
            require('karma-coverage-istanbul-reporter'),
            require('karma-junit-reporter'),
            require('@angular-devkit/build-angular/plugins/karma'),
        ],
        client: {
            clearContext: false, // leave Jasmine Spec Runner output visible in browser,
            jasmine: {
                random: false,
            },
        },
        coverageIstanbulReporter: {
            dir: require('path').join(__dirname, '../coverage'),
            reports: ['lcov', 'json', 'cobertura'],
            fixWebpackSourcePaths: true,
        },
        reporters: ['coverage-istanbul', 'progress', 'kjhtml', 'junit'],
        junitReporter: {
            outputDir: '',
            outputFile: 'abc.xml',
        },
        files: [
            {
                pattern: 'src/assets/**/*.json',
                watched: true,
                served: true,
                included: false,
            },
        ],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['ChromeHeadless'],
        captureTimeout: 100000,
        browserDisconnectTimeout: 10000,
        browserDisconnectTolerance: 3,
        browserNoActivityTimeout: 100000,
        flags: ['--disable-gpu', '--no-sandbox'],
        singleRun: true,
    });
};

Any one facing the same issue?
Stuck with this issue from few days.

Progress indicator in oracle apex shows multiple time

In oracle apex button click when i press button sevrel times, progress indicator shows multiple progress inditators how can we control it on just one. When click on more then one time it multiply by every click. thnx in advance

As above mentioned, I just want one indicator even I click several times…

URL search params showing as object in browser [duplicate]

The code is as follows

newParams = new URLSearchParams({...{sort:{title: "desc"}}})

But it is showing as object in the url.

On debugging when i convert newParams to string it outputs 'sort=%5Bobject+Object%5D' and this is exactly what is displayed on browserl url.

enter image description here

newParams.toString() = 'sort=%5Bobject+Object%5D'

I am expecting the url to be something like "sort%5Btitle%5D=desc"

Can somebody tell what is the issue here?

Any help would be appreciated.