mirror of
https://github.com/RetroShare/RSNewWebUI.git
synced 2026-09-12 19:50:04 +05:00
webui: the send and history callbacks the capture commits missed
The wave's capture fixes covered the network and distant send paths and the rooms' history -- three siblings kept reading the world at answer time. The room send echo read this.currentLobby and appended to the room on screen: after a room switch, the sent message landed in the wrong room, under the wrong identity, and scrolled it. The distant initiate's SUCCESS answer clobbered State.chatPid with no guard, defeating every downstream isCurrentChat check and merging the old contact's tunnel into the newly opened conversation (its refusal also answers a null pid, which the poll then chased into "conversation gone"). And loadChatMessages wrote its preview line -- or deleted one -- under whatever contact was selected when the answer landed, then scrolled it; loadOlderChatHistory fired its scroll-fixup done() into the new conversation. All four now capture and compare. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9a07e14489
commit
d411a6c1f1
@ -1200,6 +1200,11 @@ const ChatLobbyModel = {
|
||||
},
|
||||
sendMessage(msg, onsuccess) {
|
||||
const cid = this.chatId();
|
||||
// Captured now: the answer can land after a room switch, and the echo,
|
||||
// its sender identity and the target list must be the room the message
|
||||
// was typed in -- addMessages() writes into the room on screen.
|
||||
const askedLobbyId = this.lastLobbyId;
|
||||
const senderGxsId = this.currentLobby ? this.currentLobby.gxs_id : '';
|
||||
|
||||
rs.rsJsonApiRequest(
|
||||
'/rsChats/sendChat',
|
||||
@ -1209,11 +1214,18 @@ const ChatLobbyModel = {
|
||||
},
|
||||
(data, success) => {
|
||||
if (success) {
|
||||
if (this.lastLobbyId !== askedLobbyId) {
|
||||
// Another room is open: its message array is not this echo's
|
||||
// home. The message itself was sent; the sender's own line will
|
||||
// come back through the history on the next visit.
|
||||
if (onsuccess) onsuccess();
|
||||
return;
|
||||
}
|
||||
const echoMsg = {
|
||||
chat_id: cid,
|
||||
msg,
|
||||
sendTime: Math.floor(Date.now() / 1000),
|
||||
lobby_peer_gxs_id: this.currentLobby.gxs_id,
|
||||
lobby_peer_gxs_id: senderGxsId,
|
||||
};
|
||||
this.addMessages([echoMsg], true);
|
||||
if (onsuccess) onsuccess();
|
||||
|
||||
@ -528,6 +528,9 @@ function findLiveTunnelIdentity(peerGxsId, done) {
|
||||
}
|
||||
|
||||
function openDistantChat(session) {
|
||||
// Captured now: the initiate answer can land seconds later, after the
|
||||
// user moved to another contact.
|
||||
const askedFor = State.selectedId;
|
||||
session.pid = null;
|
||||
session.status = null;
|
||||
resetSessionMessages(session, [
|
||||
@ -558,9 +561,19 @@ function openDistantChat(session) {
|
||||
notify: true,
|
||||
},
|
||||
(res) => {
|
||||
if (res && res.pid) {
|
||||
const hexPid = rs.idToHex(res.pid);
|
||||
// A refused initiate (unknown own identity, for one) answers with a
|
||||
// null id: taking "000...0" for a tunnel makes the status poll chase
|
||||
// it and declare the conversation gone.
|
||||
const hexPid = res && res.pid ? rs.idToHex(res.pid) : '';
|
||||
if (hexPid && !/^0+$/.test(hexPid)) {
|
||||
// The session keeps its pid whatever is on screen by now; the
|
||||
// page-wide state and the loads/polls belong to the conversation
|
||||
// still being looked at. Without this, a late answer clobbered
|
||||
// State.chatPid and every downstream guard that compares against
|
||||
// it, merging the old contact's tunnel into the new one's view.
|
||||
session.pid = hexPid;
|
||||
if (State.selectedId !== askedFor) return;
|
||||
|
||||
State.chatPid = hexPid;
|
||||
State.distantChatStatus = null;
|
||||
drainBufferedChatMessages(session);
|
||||
@ -587,8 +600,10 @@ function loadChatMessages() {
|
||||
if (!State.chatPid) return;
|
||||
|
||||
// Captured now: the answer may come back after the user selected another
|
||||
// peer, and it must then land in the session it was asked for.
|
||||
const session = State.selectedId ? getDistantChatSession(State.selectedId) : null;
|
||||
// peer, and it must then land in the session -- and the Chats preview
|
||||
// line -- it was asked for.
|
||||
const askedFor = State.selectedId;
|
||||
const session = askedFor ? getDistantChatSession(askedFor) : null;
|
||||
// The current tunnel first, then whatever else the core holds with this
|
||||
// contact (other identities, direct chat), so the pane shows the whole
|
||||
// conversation and not only the file of the tunnel just opened.
|
||||
@ -611,23 +626,27 @@ function loadChatMessages() {
|
||||
// the live event handler share.
|
||||
addSessionMessages(session, data.msgs);
|
||||
if (session.pid === State.chatPid) State.chatMessages = session.messages;
|
||||
} else {
|
||||
} else if (State.selectedId === askedFor) {
|
||||
State.chatMessages = data.msgs;
|
||||
}
|
||||
// The preview line and the scroll belong to the contact this was
|
||||
// asked for: a late answer after a switch must not write the old
|
||||
// conversation's last message under the new contact's key -- nor
|
||||
// delete the new contact's entry when the old query was empty.
|
||||
const realUserMsgs = data.msgs.filter(
|
||||
(m) => !m.isSystem && !isSystemMsg(m.message || m.msg)
|
||||
);
|
||||
if (realUserMsgs.length > 0 && State.selectedId) {
|
||||
if (realUserMsgs.length > 0 && askedFor) {
|
||||
const last = realUserMsgs[realUserMsgs.length - 1];
|
||||
State.chatHistoryMap[State.selectedId] = {
|
||||
State.chatHistoryMap[askedFor] = {
|
||||
lastMsg: last.message || last.msg || '',
|
||||
lastTime: last.sendTime || last.recvTime || Math.floor(Date.now() / 1000),
|
||||
};
|
||||
} else if (State.selectedId) {
|
||||
delete State.chatHistoryMap[State.selectedId];
|
||||
} else if (askedFor) {
|
||||
delete State.chatHistoryMap[askedFor];
|
||||
}
|
||||
m.redraw();
|
||||
scrollChatToBottom();
|
||||
if (State.selectedId === askedFor) scrollChatToBottom();
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -1085,7 +1104,10 @@ function loadOlderChatHistory(done) {
|
||||
if (!anyFull) session.historyExhausted = true;
|
||||
if (session.pid === State.chatPid) State.chatMessages = session.messages;
|
||||
m.redraw();
|
||||
if (done) done();
|
||||
// done() restores a scroll position measured in the pane of the
|
||||
// conversation that asked; fired after a switch it would perturb the
|
||||
// new one (same rule as the rooms' loadOlderHistory).
|
||||
if (done && State.selectedId === gxsId) done();
|
||||
});
|
||||
});
|
||||
return true;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user