.task
[ ] El span de time al cargar mas mensajes suele repetirse


/*
inicialmente los mnesajes cargan correctamente y encuentra y sabe cual es el primer mensaje de un hilo para agregar la información del usuario, pero el problema sucede al hacer scroll, como los mensajes tienen que invertirse para cargan en el orden correcto supongo, sucede esto:

hilo de mensajes del mismo usuario: 
mensaje 1 - se supone que este es el primer mensaje donde se tiene que colocar la información del usuario
mensaje 2
mensaje 3
mensaje 4
mensaje 5 - pero en realidad se suele colocar aqui
            

*/

async function manejarScrollColab(conversacion, contenedor = null) {
    const listaMensajes = (contenedor || document).querySelector('.listaMensajes');
    let puedeDesplazar = true,
        currentPage = 1,
        conversacion_id = conversacion;

    listaMensajes.addEventListener('scroll', async e => {
        if (e.target.scrollTop === 0 && puedeDesplazar) {
            puedeDesplazar = false;
            setTimeout(() => (puedeDesplazar = true), 2000);
            currentPage++;

            const data = await enviarAjax('obtenerChatColab', {conversacion_id, page: currentPage});
            if (!data?.success) {
                return console.error('Error al obtener más mensajes.');
            }

            let mensajes = data.data.mensajes;

            // Reverse the messages to process from oldest to newest
            mensajes.reverse();

            const remitentesUnicos = [...new Set(mensajes.map(m => m.remitente))];
            const userInfos = await obtenerInfoUsuarios(remitentesUnicos);

            let fechaAnterior = null;

            // Get the sender of the first message currently displayed
            const primerMensajeMostrado = listaMensajes.querySelector('.messageBlock');
            let prevEmisor = null;
            if (primerMensajeMostrado) {
                const primerMensajeElem = primerMensajeMostrado.querySelector('.mensajeText');
                if (primerMensajeElem) {
                    prevEmisor = primerMensajeElem.getAttribute('data-emisor') || null;
                }
            }

            // Process messages from oldest to newest
            for (let i = 0; i < mensajes.length; i++) {
                const mensaje = mensajes[i];

                // Determine if this message starts a new thread
                const esNuevoHilo = mensaje.remitente !== prevEmisor;

                const userInfo = userInfos.get(mensaje.remitente);

                agregarMensajeAlChat(
                    mensaje.mensaje,
                    mensaje.clase,
                    mensaje.fecha,
                    listaMensajes,
                    fechaAnterior,
                    true, // insertAtTop = true
                    mensaje.adjunto,
                    null,
                    mensaje.remitente,
                    esNuevoHilo,
                    userInfo,
                    'Colab'
                );

                fechaAnterior = new Date(mensaje.fecha);

                // Update prevEmisor after processing the message
                prevEmisor = mensaje.remitente;
            }

            // Adjust the scroll to maintain position after loading
            if (listaMensajes.firstChild) {
                listaMensajes.firstChild.scrollIntoView();
            }
        }
    });
}


codigos de referencias


function agregarMensajeAlChat(mensajeTexto, clase, fecha, listaMensajes = document.querySelector('.listaMensajes'), fechaAnterior = null, insertAtTop = false, adjunto = null, temp_id = null, msgEmisor = null, isFirstMessageOfThread = false, userInfo = null, tipoMensaje = null) {
    const fechaMensaje = new Date(fecha);
    fechaAnterior = fechaAnterior || obtenerFechaAnterior(listaMensajes, insertAtTop);

    manejarFecha(fechaMensaje, fechaAnterior, listaMensajes, insertAtTop);

    const esUsuarioActual = msgEmisor === emisor;
    const esColabPrimerMensaje = tipoMensaje === 'Colab' && isFirstMessageOfThread && userInfo && !esUsuarioActual;

    const messageBlock = crearElemento('div', 'messageBlock');
    const messageContainer = crearElemento('div', 'messageContainer');

    const mensajeElem = crearElemento('div', ['mensajeText', clase], {
        'data-fecha': fechaMensaje.toISOString(),
        'data-emisor': msgEmisor || undefined,
        'data-temp-id': temp_id || undefined
    });

    if (temp_id) mensajeElem.classList.add('mensajePendiente');

    if (esColabPrimerMensaje) {
        // Añadimos una clase identificadora al messageBlock
        messageBlock.classList.add('firstMessageOfThread');

        const userNameElem = crearElemento('span', 'userName', {textContent: userInfo.nombreUsuario});
        const avatarImg = crearElemento('img', 'avatarImage', {
            src: userInfo.imagenPerfil,
            alt: userInfo.nombreUsuario
        });
        messageBlock.appendChild(userNameElem);
        messageContainer.appendChild(avatarImg);
    }

    const messageTextElem = crearElemento('p', null, {textContent: mensajeTexto});
    mensajeElem.appendChild(messageTextElem);
    manejarAdjunto(adjunto, mensajeElem);

    messageContainer.appendChild(mensajeElem);
    messageBlock.appendChild(messageContainer);

    if (insertAtTop) {
        listaMensajes.insertBefore(messageBlock, listaMensajes.firstChild);
    } else {
        listaMensajes.appendChild(messageBlock);
        listaMensajes.scrollTop = listaMensajes.scrollHeight;
    }
}

function crearElemento(tag, clase, atributos = {}) {
    const elem = document.createElement(tag);
    if (Array.isArray(clase)) clase.forEach(c => elem.classList.add(c));
    else if (clase) elem.classList.add(clase);

    for (const [key, value] of Object.entries(atributos)) {
        if (key === 'textContent') {
            elem.textContent = value;
        } else if (value !== undefined) {
            elem.setAttribute(key, value);
        }
    }
    return elem;
}