Update conversations.php

This commit is contained in:
Lizandro Guarnizo
2026-01-24 09:55:49 -05:00
parent 9045827760
commit 775b2c1c7f
+85 -1
View File
@@ -940,6 +940,9 @@
// Track whether the user is actively scrolling/reading to avoid forcing scroll-to-bottom
this._userScrolling = false;
this._userScrollTimer = null;
// Suspend periodic refresh while media playback or recording is active
this._suspendAutoRefresh = false;
this._pendingReloadAfterMedia = false;
// Removed: automatic "Nuevos mensajes" indicator — we always reload full conversation now
// this._lastRenderMessageCount = 0;
@@ -1535,9 +1538,17 @@
}, 30000);
// Actualizar mensajes del chat activo cada 10 segundos
// Use full reload (initial=true) — always fetch the full conversation and scroll to bottom
// Use full reload (initial=true) — always fetch the full conversation and scroll to bottom,
// but suspend while media playback or recording is active (to avoid interrupting)
setInterval(() => {
if (this.currentUserId) {
try {
if (typeof this.isMediaActive === 'function' && this.isMediaActive()) {
console.debug('Periodic load skipped: media active or recording in progress; scheduling reload after media ends');
this._pendingReloadAfterMedia = true;
return;
}
} catch (e) { console.warn('isMediaActive check failed', e); }
// full reload forces scroll-to-bottom
this.loadMessages(this.currentUserId, true).catch(err => console.warn('Periodic loadMessages failed', err));
}
@@ -2023,6 +2034,30 @@
});
chatContainer._infiniteScrollAdded = true;
}
// Media playback listeners: suspend auto-refresh while media is playing and resume when it stops
if (!chatContainer._mediaListenersAdded) {
const onMediaPlay = (ev) => {
try {
this._suspendAutoRefresh = true;
console.debug('Media play detected, suspending periodic reload');
} catch (e) { /* ignore */ }
};
const onMediaEnd = async (ev) => {
try {
this._suspendAutoRefresh = false;
console.debug('Media paused/ended, resuming periodic reload');
if (this._pendingReloadAfterMedia && this.currentUserId) {
this._pendingReloadAfterMedia = false;
await this.loadMessages(this.currentUserId, true);
}
} catch (e) { console.warn('media end handler failed', e); }
};
chatContainer.addEventListener('play', onMediaPlay, true);
chatContainer.addEventListener('pause', onMediaEnd, true);
chatContainer.addEventListener('ended', onMediaEnd, true);
chatContainer._mediaListenersAdded = true;
}
}
// Cargar respuestas rápidas y plantillas
await this.loadQuickReplies();
@@ -2588,6 +2623,26 @@
return !(hasContent || hasMedia || nonText);
}
// Helper: detect active media playback or recording to avoid interrupting with reloads
isMediaActive() {
// Recording in progress -> active
if (this._mediaRecorder && this._mediaRecorder.state === 'recording') return true;
// Explicit suspend flag
if (this._suspendAutoRefresh) return true;
try {
const container = document.getElementById('chat-conversations');
if (!container) return false;
const mediaEls = container.querySelectorAll('audio,video');
for (const el of mediaEls) {
if (!el.paused && !el.ended) return true;
if (el.readyState > 2 && !el.paused) return true;
}
} catch (e) {
console.warn('isMediaActive: failed to inspect media elements', e);
}
return false;
}
// Initialize recording handlers (so mic works before openConversation) and helper to manage recording state
initRecordingHandlers() {
if (this._recordingHandlersInitialized) return;
@@ -2598,6 +2653,8 @@
this.startRecording = async function() {
try {
// Suspend periodic reload while recording
this._suspendAutoRefresh = true;
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
this._mediaRecorder = new MediaRecorder(stream);
const chunks = [];
@@ -2628,6 +2685,15 @@
} catch(e) { /* ignore */ }
// Clear recorder reference to indicate stopped
this._mediaRecorder = null;
// Resume auto-refresh and trigger a reload if one was pending
try {
this._suspendAutoRefresh = false;
if (this._pendingReloadAfterMedia && this.currentUserId) {
this._pendingReloadAfterMedia = false;
await this.loadMessages(this.currentUserId, true);
}
} catch (e) { console.warn('Failed to resume reload after recording', e); }
};
this._mediaRecorder.start();
@@ -2667,6 +2733,15 @@
const ind = document.getElementById('recording-indicator'); if (ind) ind.style.display = 'none';
const micEl = document.getElementById('mic-btn'); if (micEl) micEl.classList.remove('recording');
if (this._updateSendMicVisibility) this._updateSendMicVisibility();
// Ensure we resume periodic reloads and trigger pending reload
try {
this._suspendAutoRefresh = false;
if (this._pendingReloadAfterMedia && this.currentUserId) {
this._pendingReloadAfterMedia = false;
this.loadMessages(this.currentUserId, true).catch(e => console.warn('Reload after stopRecording failed', e));
}
} catch (e) { console.warn('stopRecording resume failed', e); }
};
this.cancelRecording = function() {
@@ -2688,6 +2763,15 @@
// hide delete button if present
const delBtn = document.getElementById('delete-file-btn'); if (delBtn) delBtn.style.display = 'none';
if (this._updateSendMicVisibility) this._updateSendMicVisibility();
// Resume auto-refresh if it was suspended and trigger pending reload
try {
this._suspendAutoRefresh = false;
if (this._pendingReloadAfterMedia && this.currentUserId) {
this._pendingReloadAfterMedia = false;
this.loadMessages(this.currentUserId, true).catch(e => console.warn('Reload after cancelRecording failed', e));
}
} catch (e) { console.warn('cancelRecording resume failed', e); }
};
return true;