Fixed the room invite was missed before

This commit is contained in:
defnax 2026-08-27 18:16:45 +02:00
parent b2c4bb703c
commit df9cd7d24e
4 changed files with 142 additions and 22 deletions

View File

@ -1202,12 +1202,20 @@ const ChatRoomJoinView = () => {
m('.detail-section', [
m('h3', 'Join Room'),
m('p.join-description', 'Select an identity to join this chat room:'),
ChatRoomsModel.joiningLobbyId === lobbyHexId &&
m('p.join-description', [m('i.fas.fa-spinner.fa-spin'), ' Joining…']),
ChatRoomsModel.joinError && m('p.error', ChatRoomsModel.joinError),
m(
'.identities-grid',
ownIds.map((nick) =>
m(
'.identity-card',
{ onclick: () => ChatLobbyModel.enterPublicLobby(lobbyHexId, nick) },
{
class: ChatRoomsModel.joiningLobbyId === lobbyHexId ? 'disabled' : '',
onclick: () => ChatRoomsModel.invitationIds.has(lobbyHexId)
? ChatRoomsModel.acceptInvitation(lobbyHexId, nick)
: ChatLobbyModel.enterPublicLobby(lobbyHexId, nick),
},
[
m('.identity-card__identity', [
m(peopleUtil.IdentityAvatar, {
@ -1299,6 +1307,13 @@ const Layout = {
.filter((info) => !ChatRoomsModel.subscribed(info))
.filter((info) => (info.lobby_name || '').toLowerCase().includes(search));
const invitedRooms = publicRooms.filter((info) =>
ChatRoomsModel.invitationIds.has(rs.idToHex(info.lobby_id))
);
const discoverableRooms = publicRooms.filter((info) =>
!ChatRoomsModel.invitationIds.has(rs.idToHex(info.lobby_id))
);
const isSelected = (info, type) =>
ChatHubState.selectedRoomId === rs.idToHex(info.lobby_id);
@ -1396,12 +1411,41 @@ const Layout = {
}),
],
publicRooms.length > 0 && [
invitedRooms.length > 0 && [
m('.rooms-section-title.invited-rooms-title', [
m('i.fas.fa-envelope'),
m('span', 'Invitations (' + invitedRooms.length + ')'),
]),
invitedRooms.map((info) => {
const hexId = rs.idToHex(info.lobby_id);
return m(
'.chat-room-list-item.public-room.invited-room' +
(isSelected(info, 'public') ? '.selected' : ''),
{
key: hexId,
onclick: () => {
ChatHubState.mobilePane = 'detail';
m.route.set('/chat/:lobby', { lobby: hexId });
},
},
[
m('.room-icon', m('i.fas.fa-envelope-open-text')),
m('.room-meta', [
m('.room-name', info.lobby_name || '<unnamed>'),
m('.room-topic', info.lobby_topic || 'You were invited to join'),
]),
m('.room-badge', { title: 'Chat room invitation' }, '!'),
]
);
}),
],
discoverableRooms.length > 0 && [
m('.rooms-section-title', [
m('i.fas.fa-globe'),
m('span', 'Public (' + publicRooms.length + ')'),
m('span', 'Public (' + discoverableRooms.length + ')'),
]),
publicRooms.map((info) => {
discoverableRooms.map((info) => {
const hexId = rs.idToHex(info.lobby_id);
const participantCount = info.total_number_of_peers || 0;
return m(
@ -1429,7 +1473,8 @@ const Layout = {
],
subscribedRooms.length === 0 &&
publicRooms.length === 0 &&
invitedRooms.length === 0 &&
discoverableRooms.length === 0 &&
m('p.no-rooms', 'No chat rooms found'),
]),
]),

View File

@ -404,6 +404,51 @@ const ChatRoomsModel = {
knownSubscrIds: [],
subscribedRooms: {},
unreadCount: {},
invitationIds: new Set(),
joiningLobbyId: null,
joinError: '',
invitationCount() {
return this.invitationIds.size;
},
loadPendingInvitations() {
rs.rsJsonApiRequest('/rsChats/getPendingChatLobbyInvites', {}, (data) => {
const invites = data && Array.isArray(data.invites) ? data.invites : [];
const previousInvitationIds = this.invitationIds;
this.invitationIds = new Set(invites.map((invite) => rs.idToHex(invite.lobby_id)));
const inviteIds = this.invitationIds;
const rooms = this.allRooms.filter((room) => {
const id = rs.idToHex(room.lobby_id);
return !previousInvitationIds.has(id) && !inviteIds.has(id);
});
this.allRooms = sortLobbies([...rooms, ...invites]);
m.redraw();
});
},
receiveAdministrativeEvent(event) {
// RsChatLobbyEventCode::CHAT_LOBBY_INVITE_RECEIVED
if (event && Number(event.mEventCode) === 4) this.loadPendingInvitations();
},
acceptInvitation(lobbyId, identity) {
this.joiningLobbyId = lobbyId;
this.joinError = '';
return rs.rsJsonApiRequest(
'/rsChats/acceptLobbyInvite',
{ id: { xstr64: lobbyId }, identity },
(data, success) => {
this.joiningLobbyId = null;
if (!success || !data || !data.retval) {
this.joinError = 'RetroShare rejected this identity. This room may require a signed identity.';
m.redraw();
return;
}
this.invitationIds.delete(lobbyId);
this.loadSubscribedRooms();
ChatHubState.selectedRoomType = 'subscribed';
ChatLobbyModel.loadLobby(lobbyId);
m.redraw();
}
);
},
loadPublicRooms() {
rs.rsJsonApiRequest(
'/rsChats/getListOfNearbyChatLobbies',
@ -417,14 +462,24 @@ const ChatRoomsModel = {
seen.add(id);
return true;
});
ChatRoomsModel.allRooms = sortLobbies(uniqueLobbies);
const inviteIds = ChatRoomsModel.invitationIds;
const pendingInvites = ChatRoomsModel.allRooms.filter((room) =>
inviteIds.has(rs.idToHex(room.lobby_id))
);
ChatRoomsModel.allRooms = sortLobbies([
...uniqueLobbies.filter((room) => !inviteIds.has(rs.idToHex(room.lobby_id))),
...pendingInvites,
]);
} else {
ChatRoomsModel.allRooms = [];
ChatRoomsModel.allRooms = ChatRoomsModel.allRooms.filter((room) =>
ChatRoomsModel.invitationIds.has(rs.idToHex(room.lobby_id))
);
}
}
);
},
loadSubscribedRooms(after = null) {
ChatRoomsModel.loadPendingInvitations();
rs.rsJsonApiRequest(
'/rsChats/getChatLobbyList',
{},
@ -432,6 +487,7 @@ const ChatRoomsModel = {
if (data && data.cl_list) {
const ids = [...new Set(data.cl_list.map((lid) => rs.idToHex(lid)))];
ChatRoomsModel.knownSubscrIds = ids;
ids.forEach((id) => ChatRoomsModel.invitationIds.delete(id));
Object.keys(ChatRoomsModel.subscribedRooms).forEach((id) => {
if (!ids.includes(id)) {
@ -886,6 +942,8 @@ const ChatLobbyModel = {
);
},
enterPublicLobby(lobbyId, nick) {
ChatRoomsModel.joiningLobbyId = lobbyId;
ChatRoomsModel.joinError = '';
rs.rsJsonApiRequest(
'/rsChats/joinVisibleChatLobby',
{
@ -893,7 +951,21 @@ const ChatLobbyModel = {
own_id: nick,
},
(data, success) => {
if (!success || !data || !data.retval) return;
ChatRoomsModel.joiningLobbyId = null;
if (!success || !data || !data.retval) {
const room = ChatHubState.selectedRoom || {};
const flags = Number(room.lobby_flags || 0);
if ((flags & 0x10) !== 0) {
ChatRoomsModel.joinError = 'This room requires a signed identity. Select a PGP-linked identity.';
} else if (Number(room.total_number_of_peers || 0) === 0) {
ChatRoomsModel.joinError = 'This room is no longer being advertised by an online participant. Try again when someone in the room is online.';
ChatRoomsModel.loadPublicRooms();
} else {
ChatRoomsModel.joinError = 'RetroShare could not join this room. It may no longer be available; refresh the room list and try again.';
}
m.redraw();
return;
}
// Keep the subscription in the RetroShare profile so the core joins
// this room again after a restart. Recent cores also enable this from
@ -909,13 +981,10 @@ const ChatLobbyModel = {
true
);
loadLobbyDetails(lobbyId, (info) => {
if (!info) return;
ChatRoomsModel.subscribedRooms[lobbyId] = info;
ChatRoomsModel.loadSubscribedRooms(() => {
m.route.set('/chat/:lobby', { lobby: rs.idToHex(info.lobby_id) });
});
});
ChatRoomsModel.loadSubscribedRooms();
ChatHubState.selectedRoomType = 'subscribed';
ChatLobbyModel.loadLobby(lobbyId);
m.redraw();
},
true
);

View File

@ -24,7 +24,9 @@ const sumCounts = (counts) => Object.values(counts || {})
function navigationCount(name) {
if (name === 'network') return sumCounts(networkState.State.unreadChatCount);
if (name === 'people') return sumCounts(peopleState.State.unreadChatCount);
if (name === 'chat') return sumCounts(ChatRoomsModel.unreadCount);
if (name === 'chat') {
return sumCounts(ChatRoomsModel.unreadCount) + ChatRoomsModel.invitationCount();
}
if (name === 'mail') return mail.Messages.unreadCount();
return 0;
}
@ -325,10 +327,14 @@ const Layout = () => {
rs.events[eventType].notify = () => mail.Messages.refreshSoon();
});
if (!rs.events[15]) return;
rs.events[15].notify = (message) => {
networkState.receiveDirectChatMessage(message);
peopleState.receiveDistantChatMessage(message);
receiveLobbyChatMessage(message);
rs.events[15].notify = (messageOrEvent) => {
if (messageOrEvent && messageOrEvent.mEventCode !== undefined) {
ChatRoomsModel.receiveAdministrativeEvent(messageOrEvent);
return;
}
networkState.receiveDirectChatMessage(messageOrEvent);
peopleState.receiveDistantChatMessage(messageOrEvent);
receiveLobbyChatMessage(messageOrEvent);
};
},
view: (vnode) =>

View File

@ -265,9 +265,9 @@ const eventQueue = {
r.push(event.mChatMessage);
owner.notify(event.mChatMessage);
});
} else if (event && event.mCid) {
} else if (event && (event.mCid || event.mEventCode !== undefined)) {
// Administrative chat event (e.g. lobby info change, peer join/leave)
// Silent for now to avoid console spam, as actual messages use mChatMessage
owner.notify(event);
}
},
notify: () => { },