socket.io client not able to receive events stop working after some time. But when client emit it works i recive data on same socket id

I am working on chat app. where I use different socket events to send message from client to server through sockets. Here is how it works client send request with jwt on socket I check it is connected before or not if it is just delete that session and create new session and save it’s information in redies. Here is my server file code like this

require("dotenv").config();
const port = 8181;
const cluster = require("cluster");

const io_redis = require("socket.io-redis");
const num_processes = require("os").cpus().length;
import * as net from "net";
import cors from "cors";
import * as http from "http";
import router from "./routes";
import { PeerServer } from "peer";
import express from "express";
import * as socket from "socket.io";
import * as farmhash from "farmhash";
import cookieParser from "cookie-parser";
import { socketMain } from "./socket.io/socketMain";
import { inititalizeMongoDb } from "./database/mongoInstance";
import { isAuthSocket } from "./middlewares/isAuthSocket.middleware";
import { deleteOldMessageCron } from './services/deletemessagecron';
import { createClient, RedisClientType } from "redis";

// Create the Redis client using a URL
const redisClient: RedisClientType = createClient({ url: '' });
redisClient.connect();
(async () => {
  if (cluster.isMaster) {
    const workers: any = [];

    const spawn = (i: number) => {
      workers[i] = cluster.fork();
      workers[i].on("exit", () => {
        console.log("respawning worker", i);
        spawn(i);
      });
    };

    for (var i = 0; i < num_processes; i++) {
      spawn(i);
    }

    const worker_index = (ip: string, len: number) => {
      return farmhash.fingerprint32(ip) % len;
    };

    const server: net.Server = net.createServer(
      { pauseOnConnect: true },
      (connection: net.Socket) => {
        const worker =
          workers[worker_index(connection.remoteAddress, num_processes)];
        worker.send("sticky-session:connection", connection);
      }
    );

    server.listen(port);
    console.log(`Master listening on port ${port}`);
  } else {
    let app = express();
    app.use(express.json({ limit: '50mb' }));
    app.use(express.urlencoded({ limit: '50mb', extended: true }));

    app.use(cookieParser());
    app.use(
      cors({
        origin: [ "file://", "http://localhost", "http://localhost:3000"],
        credentials: true,
      })
    );

    app.use("/", router);

    const server: http.Server = app.listen(0, "localhost");
    console.log("Worker listening...");

    const io = new socket.Server(server, {
      cors: {
        origin: [ "file://", "http://localhost", "http://localhost:3000"],
        credentials: true,
      },
      pingTimeout: 120000,
      pingInterval: 25000,
    });

    io.adapter(io_redis({
      url: process.env.REDIS_URL,
      retryStrategy: (times: any) => {
        const delay = Math.min(times * 50, 2000);
        return delay;
      }
    }));

    await inititalizeMongoDb();
    deleteOldMessageCron();
    io.use(isAuthSocket);

    io.on("error", (err: any) => {
      console.log("Socket.io Error:", err);
    });
    io.on("connection", (socket: socket.Socket) => {
      console.log("connected to socket server", socket.id);
      socketMain(io, socket, redisClient);
      console.log(`connected to worker: ${cluster.worker.id}`);
    });

    process.on("message", (message, connection) => {
      if (message !== "sticky-session:connection") {
        return;
      }
      server.emit("connection", connection);
      //@ts-ignore
      connection.resume();
    });
  }
})();

my socketMain file where all events get handled

import { callOtherUser } from "./handlers/callOtherUser.handler";
import { disconnectVideoCall } from "./handlers/disconnectCall.handler";
import { getTotalUsers } from "./handlers/getTotalUsers.handler";
import { handleActiveSession } from "./handlers/handleActiveSession";
import { initialSocketConfig } from "./handlers/initialVerification";
import { iTextMessage } from "./handlers/iTextMessage.handler";
import { joinVideoRoom } from "./handlers/joinVideoRoom.handler";
import { rejectVideoCall } from "./handlers/rejectCall.handler";
import { socketDisconnect } from "./handlers/socketDisconnect.handler";
import { updateGroupInfo } from "./handlers/updateGroupInfo.handler";
import { updateOthersChats } from "./handlers/updateOthersChats.handler";
import { updateUserProfile } from "./handlers/updateUserProfile.handler";
import { userOnCall } from "./handlers/userOnCall.handler";
import { MarkAsReadMessage } from './handlers/MarkAsReadMessage.handler';
import { NickName } from './handlers/NickName.handler';
import { switchActiveChat } from "./handlers/switchActiveChat.handler";
import { RedisClientType } from "redis";
import { blockUser } from './blockUser.handler';

export const socketMain = async (io: any, socket: any, redisClient: RedisClientType) => {
  try {
    let heartbeatTimeout: NodeJS.Timeout;
    const { _id, db, userPayload } = await initialSocketConfig(
      io,
      socket
    );
    handleActiveSession(io, socket, _id, userPayload?.displayName, redisClient);

    socket.emit("signInSuccess", {
      objectId: _id,
      displayName: userPayload?.displayName,
      email: userPayload?.email,
      avatar: userPayload?.avatar,
      createdOn: userPayload?.createdOn,
      about: userPayload?.about,
      lastSeen: userPayload?.lastSeen,
    });

    socket.on("callOtherUser", (payload: any) =>
      callOtherUser(io, _id, db, payload)
    );

    socket.on("join-vc-room", (roomId: string, peerUserId: string) =>
      joinVideoRoom(socket, roomId, peerUserId)
    );

    socket.on("diconnect-from-call", (roomId: string, peerUserId: string) =>
      disconnectVideoCall(socket, roomId, peerUserId)
    );

    socket.on("reject-call", (roomId: string) =>
      rejectVideoCall(socket, roomId)
    );

    socket.on("user-on-call", (roomId: string) => userOnCall(socket, roomId));

    socket.on("getTotalUsers", () => getTotalUsers(db, socket, _id));

    socket.broadcast.emit("updateTotalUsers", {
      objectId: userPayload?._id,
      displayName: userPayload?.displayName,
      avatar: userPayload?.avatar,
      createdOn: userPayload?.createdOn,
      about: userPayload?.about,
      lastSeen: userPayload?.lastSeen,
    });

    socket.on(
      "updateUserProfile",
      async (payload: any) => await updateUserProfile(socket, _id, payload, db)
    );

    socket.on("updateGroupInfo", async (payload: any) =>
      updateGroupInfo(io, _id, payload, db)
    );

    socket.on("updateOthersChats", (payload: any) => {
      console.log("updateOthersChats", payload)
      updateOthersChats(db, io, _id, payload)
    }
    );

    socket.on("iTextMessage", async (payload: any) =>
      iTextMessage(io, socket, payload, db, _id)
    );

    socket.on("markAsReadMessage", async (payload: any) =>
      MarkAsReadMessage(io, socket, payload, db, _id)
    );

    socket.on("setNickname", async (payload: any) =>
      NickName(io, payload, db, _id)
    );

    socket.broadcast.emit("online", _id);

    socket.on("switchActiveChat", async (payload: any) =>
      switchActiveChat(io, socket, _id, db, payload)
    );
    socket.on("user-blocked", async (payload: any) => {
      blockUser(io, socket, _id, db, payload)
    })


    socket.on('heartbeat', (data: any) => {
      console.log('Client heartbeat:', socket.id);
      // Respond immediately to client
      socket.emit('heartbeat_received');

      // Clear existing timeout
      if (heartbeatTimeout) {
        clearTimeout(heartbeatTimeout);
      }

      // Set new timeout for missed heartbeat
      heartbeatTimeout = setTimeout(() => {
        console.log('Client heartbeat timeout:', socket.id);
        socket.disconnect(true);
      }, 90000); // 90 seconds (allowing for network delays)
    });
    socket.on("disconnect", async (reason: any) => {

      if (heartbeatTimeout) {
        clearTimeout(heartbeatTimeout);
      }
      console.log("DISCONNECT REASON:", reason);
      console.log("Socket Namespace:", socket.nsp.name);
      console.log("Socket ID:", socket.id);

      try {
        await socketDisconnect(socket, _id, db, redisClient);
      } catch (err) {
        console.error("Error during socket disconnect:", err);
      }
    });

  } catch (err) {
    console.log("MAIN SOCKET ERR", err);
  }
};

handleActiveSession file where user connections save or removed from redies

import * as socket from "socket.io";
import {
  getActiveUserByObjectId,
  removeActiveUserByObjectId,
  addToActiveUsers,
  getActiveUsers
} from "../../utils/activeUsers";
import { RedisClientType } from "redis";

export const handleActiveSession = async (
  io: socket.Server,
  socket: socket.Socket,
  _id: string,
  Name: string,
  redisClient: RedisClientType
) => {
  const userKey = `user:${_id}`;
  const userSession = {
    socketId: socket.id,
    objectId: _id,
    Name: Name
  };

  await redisClient.set(userKey, JSON.stringify(userSession));

  if (!getActiveUserByObjectId(_id)) {
    console.log("New session!");
    addToActiveUsers(userSession);
    console.log("Active Users: ", getActiveUsers());
  } else {
    console.log("Prev Disconnected, New session!");
    const prevSocketId = getActiveUserByObjectId(_id)?.socketId;
    if (io.sockets.sockets.get(prevSocketId)) {
      console.log(prevSocketId + "multipleSession disconnected");
      io.sockets.sockets.get(prevSocketId).emit("multipleSession");
      io.sockets.sockets.get(prevSocketId).disconnect(true);
    }
    removeActiveUserByObjectId(_id);
    addToActiveUsers(userSession);
  }
};

Pasting rows copied from excel into handsontable

Think of an excel with 15 rows, in this excel when I select and copy rows 2, 4, 7, 9, 11 and 12, it copies all rows between rows 2 and 12. When I paste it to Handsontable, it pastes it in the same way. I want to paste the rows I selected in handsontable.

Note: These rows are examples and I do not want to do any work in Excel, I want to do it in HandsonTable.

I tried this method:

 scope.hot.addHook('afterPaste', function (changes){}

All the lines I copied in the Changes parameter come as an array.

Ag-Grid custom dropdown component not working due to overflow:hidden

In React, using the Community version of Ag Grid, I want a custom dropdown component that looks richer than a plain . In particular, I would like to use react-select.

The problem is that the cell div has overflow:hidden on it (.ag-cell-value), so the dropdown options don’t show up.

https://youtu.be/AjU3eq3rpDU

https://codesandbox.io/p/sandbox/svnxk5

On the very bottom of the page you can see an example of the dropdown outside of Active Grid so you can see what the options are supposed to look like when expanded, not being cut off by overflow:hidden.

I noticed that it is possible to use the cellEditorPopup:true option in the column definition, but then the custom component won’t know the cell’s size, so width:"100%",height:"100%" wouldn’t work.

How best to achieve being able to use a custom dropdown component?

Onfido web sdk configuration for live feedback

I’m trying to integrate Onfido web sdk into one of my applications and I saw it has the capability to give live feedback during document and video capture.

I saw there is this useLiveDocumentCapture in the documentation but it’s already deprecated.

This document states that the smart capture sdk has the real time feedback feature.

I’ve integrated with the sandbox but it doesn’t do any real time feedbacks. Could someone please help me to figure why the real time feedback is not working.

Below is the init

Onfido.init({
    token: sdkToken,
    containerId: 'onfido-mount',
    onComplete(data) {
      alert('Capturing process complete');
    },
    steps: [
      {
        type: 'document',
        options: {
          useLiveDocumentCapture: true,
          uploadFallback: true,
        },
      },
    ],
    theme: {
      name: 'light', // or "dark",
      config: {
        colorBackgroundButtonPrimary: '#008000',
      },
    },
  });

I’m using onfido-sdk-ui : “^14.40.0”,

Why my dropdown from Bootstrap doesn’t close

I’m trying to use a dropdown menu from Bootstrap React and can’t make it work. It doesn’t close (and it’s not vertical, only if I use CSS with display: flex and flex-direction: column) :

enter image description here

It’s inside a div. When i click a second time on i, it turns like this:

enter image description here

Here is the code:

function DropdownMenu() {
    return (
        <Dropdown>
            <Dropdown.Toggle className={styles.dropdowntoggle} variant="success" id="dropdown-basic">
                Dropdown Button
            </Dropdown.Toggle>

            <Dropdown.Menu>
                <Dropdown.Item href="#/action-1">Action</Dropdown.Item>
                <Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
                <Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
            </Dropdown.Menu>
        </Dropdown>
    );
}

export default DropdownMenu;

The only css used is the background color on the Dropdown.Toggle.

I have tried using the simplified version. I’ve tried using onToggle and onClick with a “show” state, using the show prop. Doesn’t work.

I’ve installed React Bootstrap and Bootstrap.

Edit: styles.dropdowntoggle is for the use of CSS on this component.

How to resolve TS2305: Module ‘”react-dom/client”‘ has no exported member ‘createRoot’?

I am trying to display my code in the browser but I got this error:

“TS2305: Module ‘”react-dom/client”‘ has no exported member ‘createRoot'”

I am not sure what I am doing wrong in my code. The only files I have been edited, are these files below. I hope someone has an answer and if you need some more information about the project, let me know so I can add it.

index.tsx:

import { createRoot } from "react-dom/client"
import { App } from "./App"

const rootElement = document.getElementById("root")
const root = createRoot(rootElement)
root.render(<App />)

package.json:

  "dependencies": {
    "cra-template-typescript": "1.2.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-scripts": "5.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.26.0",
    "@babel/preset-env": "^7.26.0",
    "@babel/preset-react": "^7.26.3",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.26",
    "babel-loader": "^9.1.2",
    "css-loader": "^6.7.4",
    "style-loader": "^3.3.2",
    "ts-loader": "^9.4.1",
    "typescript": "^4.0.0",
    "webpack": "^5.97.1",
    "webpack-cli": "^6.0.1"
  },

react-dom-client.d.ts:

declare module "react-dom/client" {
  export function render(element: React.ReactNode, container: HTMLElement): void
}

Is there any way to delay beforePrint to allow for a postMessage to finish?

Problem

My problem is that after pressing CTRL + P or File -> Print, data from the iframe hasn’t been copied over to the top window for printing.

When the beforeprint event fires, the function ‘_beforePrinting’ is called, and if the current window is not the top window, there is a window.top.postMessage sent with the data. When the message is received, a function ‘_handleBeforePrint’ is called that is passed the data. This function handles moving data from the iframe to the top window for printing.

Extra Information

This method of capturing information and printing has been done to avoid a cross-domain error.

Code

beforePrinting function:

function _beforePrinting() {
    let isPrintIframe = document.getElementById(PRINT_IFRAME_ID);
    if (isPrintIframe) {
        return;
    }
    let pageContent = document.getElementsByClassName(CSS_TEMPLATE)[0],
        pageHeader = document.getElementById(PRINT_HEADER_TEMPLATE_ID);

    if (pageContent) {
        if (window !== window.top) {
            window.top.postMessage({ type: MESSAGE_BEFORE_PRINT, pageHeader: pageHeader.innerHTML, pageContent: pageContent.innerHTML }, window.popupProperties.topMostTargetOrigin);
        }
    } else {
        _handleBeforePrint(true, pageContent.cloneNode(true), 
        pageHeader.content.cloneNode(true));
    }
}

Message Event Listener that calls handleBeforePrint():

else if (event.data.type === MESSAGE_BEFORE_PRINT || event.data.type === MESSAGE_PRINTING_ACTION) {
    if (window === window.top) {
        _handleBeforePrint(false, event.data.pageContent, event.data.pageHeader);

        if (event.data.type === MESSAGE_PRINTING_ACTION) {
            window.print();
        }
    }
}

handleBeforePrint() function that handles moving data from iframe to top window for print:

function _handleBeforePrint(inTopMostWindow, pageContent, pageHeader) {
    let printHeader = document.getElementById(PRINT_HEADER_ID),
        printContent = document.getElementById(PRINT_CONTENT_ID);

    if (pageHeader) {
        document.body.classList.add(CSS_PRINTING_IFRAME);
        if (inTopMostWindow) {
            printHeader.replaceChildren(pageHeader);
            printContent.replaceChildren(pageContent);

        } else {
            printHeader.innerHTML = pageHeader;
            printContent.innerHTML = pageContent.replace(/(style=")/gm, 'data-style="');

            let elementsWithStyle = printContent.querySelectorAll("[data-style]");

            for (let index = 0; index < elementsWithStyle.length; index++) {
                let element = elementsWithStyle[index];

                element.style.cssText = element.getAttribute("data-style");
                element.removeAttribute("data-style");
            }
        }
    }

    _automateLandscapePrinting();
}

Question

Is there anyway for me to delay the beforeprint event so that the message is received, the functions are run and then the print happens? Or are there any other solutions that would allow this to work properly?

Tested

I have tried using a setTimeout to simulate a delay.

Expectations

The information from the iframe should be put into the elements, printHeader & printContent in the top window before the page is printed.

Knockout javascript radiobutton setting value programmatically

I have a custom control with the following code. I expect “Option 1” to be selected on page reload. But nothing is selected. But I can manually select either options.

HTML:

<ul class="list-group" data-bind="foreach: tempitems">
    <li>
        <input class="form-checkbox"
               type="radio"
               name="target"
               data-bind="attr: { 'id': guid }, rbChecked: $parent.tempitem, value: guid" />
        <span data-bind="text: name"></span>
        <span data-bind="text: $parent.tempitem"></span>
    </li>
</ul>

javascript knockout.js

this.tempitems = ko.observableArray([
    { guid: "abc", name: "Option 1" },
    { guid: "def", name: "Option 2" }
]);

this.tempitem = ko.observable("def"); // Initially selects "Option 2"
this.tempitem = ko.observable("abc");
console.log("Initial value of tempitem:", ko.unwrap(self.tempitem));

ko.bindingHandlers.rbChecked = {
    init: function (element, valueAccessor, allBindingsAccessor,
        viewModel, bindingContext) {
        var value = valueAccessor();

        // Handle the change event
        ko.utils.registerEventHandler(element, "change", function () {
            console.log(`Change event: Setting observable to ${element.value}`);
            value(element.value); // Update the observable
        });

        // Set the initial checked state
        if (ko.unwrap(value) === element.value) {
            console.log("Init: Setting element.checked = true");
            element.checked = true;
        }

        var newValueAccessor = function () {
            return {
                change: function () {
                    value(element.value);
                }
            }
        };

        ko.bindingHandlers.event.init(element, newValueAccessor, allBindingsAccessor, viewModel, bindingContext);

        if (value != undefined && $(element).val() == value()) {
            setTimeout(function () {
                var toggle = $(element).closest('.btn-toggle');
                $(toggle).children('.btn').removeClass('active');
                $(toggle).children('.btn').removeClass('btn-primary');
                $(toggle).children('.btn').addClass('btn-default');

                var btn = $(element).closest('.btn');
                $(btn).addClass('btn-primary');
                $(btn).addClass('active');


            }, 0);
        }
    },
    update: function (element, valueAccessor, allBindingsAccessor,
        viewModel, bindingContext) {
        const value = ko.unwrap(valueAccessor());
        console.log(`Update: Element value = ${element.value}, Observable value = ${value}`);

        // Ensure the checked state reflects the observable value
        element.checked = value === element.value;

        // If the radio button is checked, trigger the change event to update the observable
        if (element.checked) {
            element.dispatchEvent(new Event("change", { bubbles: true }));
        }

        if ($(element).val() == ko.unwrap(valueAccessor())) {

            setTimeout(function () {
                $(element).closest('.btn').toggleClass('active');

                var toggle = $(element).closest('.btn-toggle');
                $(toggle).children('.btn').removeClass('active');
                $(toggle).children('.btn').removeClass('btn-primary');
                $(toggle).children('.btn').addClass('btn-default');

                var btn = $(element).closest('.btn');
                $(btn).addClass('btn-primary');
                $(btn).addClass('active');

            }, 0);

        }
    }
};

Initially the output is
Element value = on, Observable value = abc

But after manually selecting the radio button,
Change event: Setting observable to abc
Change event: Setting observable to def
Update: Element value = abc, Observable value = def
Update: Element value = def, Observable value = def
Change event: Setting observable to def
Change event: Setting observable to abc
Update: Element value = abc, Observable value = abc
Change event: Setting observable to abc
Update: Element value = def, Observable value = abc

What is wrong is setting the initial value of the radio button?

Svelte mention like component isn’t working as expected

I am building a component where you can use a specific trigger to open a dropdown. After selection it will insert the given selection at the cursor, then moves the cursor. In theory it sounds simple, but I can’t get it working (one command nearly works, multiple are breaking totally).
REPL: https://svelte.dev/playground/edba5955c485403b86005b95a592c8c0?version=5.19.0

I just don’t get what I am doing wrong. It should work like mentioning somebody, referencing an issue or similar.

I think the main culprit is here:

 function handleOptionSelect(option) {
    const sel = window.getSelection();
    const range = sel.getRangeAt(0);
    const textNode = range.startContainer;
    const cursorPos = range.startOffset;
    const text = textNode.textContent;

    const beforeCursor = text.substring(0, cursorPos);
    const afterCursor = text.substring(cursorPos);
    const lastDollarIndex = beforeCursor.lastIndexOf('$');
    const start = lastDollarIndex === -1 ? beforeCursor.length : lastDollarIndex;

    const beforeText = document.createTextNode(beforeCursor.substring(0, start));
    const commandSpan = document.createElement('span');
    commandSpan.classList.add('command-span');
    commandSpan.contentEditable = false;
    commandSpan.textContent = option.name;

    const space = document.createTextNode('u00A0');
    const afterText = document.createTextNode(afterCursor);

    inputElement.textContent = '';
    inputElement.appendChild(beforeText);
    inputElement.appendChild(commandSpan);
    inputElement.appendChild(space);
    inputElement.appendChild(afterText);

    const newRange = document.createRange();
    newRange.setStart(afterText, 0);
    newRange.collapse(true);
    sel.removeAllRanges();
    sel.addRange(newRange);

    inputElement.focus();
    sel.removeAllRanges();
    sel.addRange(newRange);

    showDropdown = false;
    currentText = inputElement.textContent;
}

ValidationPipe complaining about empty fields when using a DTO in body

I am trying to implement validation for API requests to my project like documented here:
https://docs.nestjs.com/techniques/validation

It seems to work as when I leave out fields I get appropriate errors messages. Only it also complains when I don’t leave them out. Below is my code for the endpoint:

@Post('heatMap')
async getOrCreateHeatMap(@Body() heatMap: HeatMapGetOrCreate) {
    const getHeatMap = await this.graphService.getHeatMapByFields(heatMap);
    if (getHeatMap) {
        return getHeatMap;
    } else {
        // return this.graphService.createHeatMap(name, complexity, repositoryId);
    }
}

This is the DTO class I am using:

export class HeatMapGetOrCreate {
    @IsNotEmpty()
    name!: string;
    @IsNotEmpty()
    complexity!: number;
    @IsNotEmpty()
    repositoryId!: string;
}

I think it’s not a problem with the validation maybe, but instead with how I do the @Body part. Is what I’m trying to do possible or do I need to define each field separately?

Throttle Pattern Typescript

const throttle = <T extends unknown[]>(
  callback: (...args: T) => void,
  delay: number,
) => {
  // this is not a global variable, just a local variable ??
  let isWaiting = false;
 
  return (...args: T) => {
    if (isWaiting) {
      return;
    }
 
    callback(...args);
    // this just sets the local Variable to true ?? 
    isWaiting = true;
 
    setTimeout(() => {
      isWaiting = false;
    }, delay);
  };
};
// Delay is 2000ms   
window.addEventListener('resize', throttle(handleWindowResize, 2000));

I do not understand one thing.
When throttle function is called a second time let’s say after 100ms, why is the variable isWaiting still true, it should be just a local Variable and have no effect on the second function call?? That’s what I do not understand.

When I try to drag an image while clicking on the bottom corner, it drags multiple other images

Here is a video of the error which happens twice during the video:

https://youtu.be/nhaKyX9Qt28

This is a JS, HTML, CSS chess game I’m making. The things visible are a table element with trs and tds within the trs and imgs within the tds. The images are draggable, but everything else has the draggable attribute set to false. If there is any code you’d like to me show to help, or questions about it, I’m happy to show it. The following is my current CSS for the images:

td img {
    max-width: 100%;  
    max-height: 100%;  
    object-fit: contain; /* ensures the image scales within the td, maintaining aspect ratio */

    position: absolute; /* centering the image vertically */
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* adjusting the image back to the center */

    -khtml-user-select: none; /* stops it being highlightable */
    -o-user-select: none;
    -moz-user-select: none;
    -webkit-user-select: none;
    user-select: none;
    
}

In my android app, before the video is loaded, a picture like this appears, how can I prevent this?

I’m doing it like this now, but it doesn’t work very well, I don’t want it to be seen at all, how can I make this picture?

enter image description here

webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.settings.mediaPlaybackRequiresUserGesture = false

override fun onPageFinished(view: WebView?, url : String? ) {
  super.onPageFinished(view, url)
  webView.evaluateJavascript("""
    var remoteVideo = document.getElementById('remoteVideo'); 
    remoteVideo.style.display = 'none';
    var checkInterval = setInterval(function() {
      if (remoteVideo.networkState !== HTMLMediaElement.NETWORK_EMPTY) {
        remoteVideo.style.display = 'block';
        clearInterval(checkInterval);
      }
    }, 3200);
    """.trimIndent()
  ) {}
}

How to implement a Heikin Ashi chart using amCharts 5?

I am trying to create a Heikin Ashi chart using amCharts 5, but I’m not sure how to set it up correctly. I couldn’t find direct examples in the documentation.

Here’s what I’ve done so far:

  • I’m able to display a basic candlestick chart using XYChart and CandlestickSeries.
  • I understand that Heikin Ashi uses modified values for open, close, high, and low.

How can I modify my data or the series configuration to calculate and display Heikin Ashi candles? Should I preprocess the data or can it be done dynamically using amCharts 5 features?

Here’s a simplified version of my current code:

// Create chart
let chart = am5.Root.new("chartdiv").container.children.push(am5xy.XYChart.new(am5.Root.new(), {}));

// Add data (example format)
let data = [
  { date: "2023-01-01", open: 100, high: 110, low: 95, close: 105 },
  { date: "2023-01-02", open: 105, high: 115, low: 100, close: 110 },
  // more data...
];

// Create series
let series = chart.series.push(
  am5xy.CandlestickSeries.new(am5.Root.new(), {
    xAxis: chart.xAxes.push(am5xy.DateAxis.new(am5.Root.new(), { baseInterval: { timeUnit: "day", count: 1 } })),
    yAxis: chart.yAxes.push(am5xy.ValueAxis.new(am5.Root.new(), {})),
    openValueYField: "open",
    valueYField: "close",
    highValueYField: "high",
    lowValueYField: "low",
    categoryXField: "date",
  })
);

series.data.setAll(data);

Do I need to calculate the Heikin Ashi values (HA_open, HA_close, HA_high, HA_low) manually before passing the data to the chart? Or is there a built-in feature in amCharts 5 to handle this transformation?

Any example or guidance would be greatly appreciated!