fix(messages): tempId-based dedup (not content) + clickable profile in chat header
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Dedup: sendContent passes tempId through queue to _doSend, which replaces optimistic msg by matching tempId (not content). Eliminates false negatives from HTML sanitization differences. Profile: clicking avatar or name in chat header opens /profil/<user_id>. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3931b1466c
commit
a52c52863e
@ -388,6 +388,21 @@
|
||||
var other = details.members.find(function (m) {
|
||||
return m.user_id !== window.__CURRENT_USER__.id;
|
||||
});
|
||||
if (other) {
|
||||
// Make avatar and name clickable to profile
|
||||
var headerAvatar = document.getElementById('headerAvatar');
|
||||
var headerName = document.getElementById('headerName');
|
||||
var profileUrl = '/profil/' + other.user_id;
|
||||
if (headerAvatar) {
|
||||
headerAvatar.style.cursor = 'pointer';
|
||||
headerAvatar.onclick = function() { window.location.href = profileUrl; };
|
||||
}
|
||||
if (headerName) {
|
||||
headerName.style.cursor = 'pointer';
|
||||
headerName.onclick = function() { window.location.href = profileUrl; };
|
||||
headerName.title = 'Otwórz profil';
|
||||
}
|
||||
}
|
||||
if (other && other.is_online) {
|
||||
subtitle.innerHTML = '<span class="online-status-dot"></span> online';
|
||||
subtitle.classList.add('is-online');
|
||||
@ -1295,12 +1310,14 @@
|
||||
sendContent: function (html, text) {
|
||||
if (!state.currentConversationId) return;
|
||||
// Add to queue with current state snapshot
|
||||
var tempId = 'temp-' + Date.now() + '-' + Math.random();
|
||||
Composer._sendQueue.push({
|
||||
convId: state.currentConversationId,
|
||||
html: html,
|
||||
text: text,
|
||||
replyTo: state.replyToMessage,
|
||||
files: state.attachedFiles.slice()
|
||||
files: state.attachedFiles.slice(),
|
||||
tempId: tempId
|
||||
});
|
||||
state.attachedFiles = [];
|
||||
state.replyToMessage = null;
|
||||
@ -1308,7 +1325,6 @@
|
||||
if (replyPreview) replyPreview.style.display = 'none';
|
||||
Composer.renderAttachments();
|
||||
// Show optimistic message immediately
|
||||
var tempId = 'temp-' + Date.now() + '-' + Math.random();
|
||||
ChatView.appendMessage({
|
||||
id: tempId,
|
||||
conversation_id: state.currentConversationId,
|
||||
@ -1327,7 +1343,7 @@
|
||||
Composer._queueProcessing = true;
|
||||
while (Composer._sendQueue.length > 0) {
|
||||
var item = Composer._sendQueue.shift();
|
||||
await Composer._doSend(item.convId, item.html, item.text, item.replyTo, item.files);
|
||||
await Composer._doSend(item.convId, item.html, item.text, item.replyTo, item.files, item.tempId);
|
||||
}
|
||||
Composer._queueProcessing = false;
|
||||
},
|
||||
@ -1355,7 +1371,7 @@
|
||||
return Composer._doSend(convId, html, text, savedReplyTo, savedFiles);
|
||||
},
|
||||
|
||||
_doSend: async function (convId, html, text, savedReplyTo, savedFiles) {
|
||||
_doSend: async function (convId, html, text, savedReplyTo, savedFiles, tempId) {
|
||||
// Optimistic message already shown by sendContent() — just do the API call
|
||||
try {
|
||||
var fd = new FormData();
|
||||
@ -1368,18 +1384,15 @@
|
||||
|
||||
var result = await api('/api/conversations/' + convId + '/messages', 'POST', fd);
|
||||
|
||||
// Update optimistic message in state with real data (for dedup)
|
||||
// Replace optimistic message with real data (match by tempId)
|
||||
var msgs = state.messages[convId];
|
||||
if (msgs) {
|
||||
var stripped = (html || '').replace(/<[^>]*>/g, '').trim();
|
||||
if (msgs && tempId) {
|
||||
for (var i = msgs.length - 1; i >= 0; i--) {
|
||||
if (msgs[i]._optimistic && msgs[i].sender_id === result.sender_id) {
|
||||
var mc = (msgs[i].content || '').replace(/<[^>]*>/g, '').trim();
|
||||
if (mc === stripped) {
|
||||
msgs[i].id = result.id;
|
||||
msgs[i]._optimistic = false;
|
||||
break;
|
||||
}
|
||||
if (msgs[i].id === tempId) {
|
||||
msgs[i].id = result.id;
|
||||
msgs[i]._optimistic = false;
|
||||
msgs[i].content = result.content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user