Ensure implicit room-members are real

If a message/event is sent to a room that's tied to a user that hasn't
been formally declared (through IM_ROOM_PARTICIPANTS or
IM_ROOM_PARTICIPANT_JOINED), that user won't be unconditionally kept
anymore.

Now, after adding an implicit user, the participant list will be
requested again― upon receiving the list, all implicitly-defined users
will be removed. If they really existed to begin with, they should be
re-added quickly through this re-sending of IM_ROOM_PARTICIPANTS.

Ghosts should be treated as ghosts, not users.
This commit is contained in:
Jaidyn Ann 2021-08-18 14:18:24 -05:00
parent 0bab0a89a8
commit 5e0782b553
3 changed files with 51 additions and 36 deletions

View File

@ -10,7 +10,6 @@
#include <Locale.h> #include <Locale.h>
#include <Notification.h> #include <Notification.h>
#include <StringFormat.h> #include <StringFormat.h>
#include <StringList.h>
#include "AppPreferences.h" #include "AppPreferences.h"
#include "Cardie.h" #include "Cardie.h"
@ -199,6 +198,28 @@ Conversation::ImMessage(BMessage* msg)
_CacheRoomFlags(); _CacheRoomFlags();
break; break;
} }
case IM_ROOM_PARTICIPANTS:
{
// Get rid of implicity-defined users rq
for (int i = 0; i < fGuests.CountStrings(); i++) {
RemoveUser(UserById(fGuests.StringAt(i)));
fGuests.Remove(i);
}
BStringList ids;
BStringList names;
msg->FindStrings("user_name", &names);
if (msg->FindStrings("user_id", &ids) != B_OK)
break;
for (int i = 0; i < ids.CountStrings(); i++) {
BMessage user;
user.AddString("user_name", names.StringAt(i));
user.AddString("user_id", ids.StringAt(i));
_EnsureUser(&user, false);
}
break;
}
case IM_ROOM_PARTICIPANT_JOINED: case IM_ROOM_PARTICIPANT_JOINED:
{ {
BString user_id; BString user_id;
@ -206,7 +227,7 @@ Conversation::ImMessage(BMessage* msg)
break; break;
if (UserById(user_id) == NULL) { if (UserById(user_id) == NULL) {
_EnsureUser(msg); _EnsureUser(msg, false);
GetView()->MessageReceived(msg); GetView()->MessageReceived(msg);
} }
break; break;
@ -437,10 +458,12 @@ Conversation::UserById(BString id)
void void
Conversation::AddUser(User* user) Conversation::AddUser(User* user)
{ {
if (user == NULL)
return;
BMessage msg; BMessage msg;
msg.AddString("user_id", user->GetId()); msg.AddString("user_id", user->GetId());
msg.AddString("user_name", user->GetName()); msg.AddString("user_name", user->GetName());
_EnsureUser(&msg); _EnsureUser(&msg, false);
_SortConversationList(); _SortConversationList();
} }
@ -448,6 +471,8 @@ Conversation::AddUser(User* user)
void void
Conversation::RemoveUser(User* user) Conversation::RemoveUser(User* user)
{ {
if (user == NULL)
return;
fUsers.RemoveItemFor(user->GetId()); fUsers.RemoveItemFor(user->GetId());
user->UnregisterObserver(this); user->UnregisterObserver(this);
GetView()->UpdateUserList(fUsers); GetView()->UpdateUserList(fUsers);
@ -473,7 +498,8 @@ Conversation::SetRole(BString id, Role* role)
fRoles.RemoveItemFor(id); fRoles.RemoveItemFor(id);
delete oldRole; delete oldRole;
} }
fRoles.AddItem(id, role); if (role != NULL)
fRoles.AddItem(id, role);
} }
@ -579,7 +605,7 @@ Conversation::_EnsureCachePath()
User* User*
Conversation::_EnsureUser(BMessage* msg) Conversation::_EnsureUser(BMessage* msg, bool implicit)
{ {
BString id = msg->FindString("user_id"); BString id = msg->FindString("user_id");
BString name = msg->FindString("user_name"); BString name = msg->FindString("user_name");
@ -589,19 +615,27 @@ Conversation::_EnsureUser(BMessage* msg)
User* serverUser = fLooper->UserById(id); User* serverUser = fLooper->UserById(id);
// Not here, but found in server // Not here, but found in server
if (user == NULL && serverUser != NULL) { if (user == NULL && serverUser != NULL)
fUsers.AddItem(id, serverUser);
user = serverUser; user = serverUser;
GetView()->UpdateUserList(fUsers);
_UpdateIcon(user);
NotifyInteger(INT_ROOM_MEMBERS, fUsers.CountItems());
}
// Not anywhere; create user // Not anywhere; create user
else if (user == NULL) { else if (user == NULL) {
user = new User(id, _GetServer()->Looper()); user = new User(id, _GetServer()->Looper());
user->SetProtocolLooper(fLooper); user->SetProtocolLooper(fLooper);
fLooper->AddUser(user); fLooper->AddUser(user);
}
// It's been implicitly defined (rather than explicit join), shame!
if (UserById(id) == NULL && implicit == true) {
fGuests.Add(id);
// The response to this will be used to determine if this guest stays
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_GET_ROOM_PARTICIPANTS);
msg.AddString("chat_id", fID);
fLooper->MessageReceived(&msg);
}
if (UserById(id) == NULL) {
fUsers.AddItem(id, user);
fUsers.AddItem(id, user); fUsers.AddItem(id, user);
GetView()->UpdateUserList(fUsers); GetView()->UpdateUserList(fUsers);
_UpdateIcon(user); _UpdateIcon(user);

View File

@ -8,6 +8,7 @@
#include <DateTimeFormat.h> #include <DateTimeFormat.h>
#include <Messenger.h> #include <Messenger.h>
#include <Path.h> #include <Path.h>
#include <StringList.h>
#include <libsupport/KeyMap.h> #include <libsupport/KeyMap.h>
@ -83,7 +84,7 @@ private:
void _LoadRoomFlags(); void _LoadRoomFlags();
void _EnsureCachePath(); void _EnsureCachePath();
User* _EnsureUser(BMessage* msg); User* _EnsureUser(BMessage* msg, bool implicit = true);
Role* _GetRole(BMessage* msg); Role* _GetRole(BMessage* msg);
void _UpdateIcon(User* user = NULL); void _UpdateIcon(User* user = NULL);
@ -113,7 +114,8 @@ private:
int32 fRoomFlags; int32 fRoomFlags;
int32 fDisallowedFlags; int32 fDisallowedFlags;
UserMap fUsers; UserMap fUsers; // For defined, certain members of the room
BStringList fGuests; // IDs of implicitly-defined users
RoleMap fRoles; RoleMap fRoles;
}; };

View File

@ -458,7 +458,6 @@ Server::ImMessage(BMessage* msg)
chat->AddUser(user); chat->AddUser(user);
chat->ShowView(false, true); chat->ShowView(false, true);
} }
break; break;
} }
case IM_JOIN_ROOM: case IM_JOIN_ROOM:
@ -466,27 +465,6 @@ Server::ImMessage(BMessage* msg)
SendProtocolMessage(msg); SendProtocolMessage(msg);
break; break;
} }
case IM_ROOM_PARTICIPANTS:
{
Conversation* chat = _EnsureConversation(msg);
BStringList ids;
BStringList name;
msg->FindStrings("user_name", &name);
if (msg->FindStrings("user_id", &ids) != B_OK)
break;
ProtocolLooper* protoLooper = _LooperFromMessage(msg);
for (int i = 0; i < ids.CountStrings(); i++) {
User* user = _EnsureUser(ids.StringAt(i), protoLooper);
if (name.CountStrings() >= i && !name.StringAt(i).IsEmpty())
user->SetNotifyName(name.StringAt(i));
chat->AddUser(user);
}
break;
}
case IM_MESSAGE_RECEIVED: case IM_MESSAGE_RECEIVED:
if (msg->HasString("chat_id") == false) { if (msg->HasString("chat_id") == false) {
ProtocolLooper* looper = _LooperFromMessage(msg); ProtocolLooper* looper = _LooperFromMessage(msg);
@ -499,6 +477,7 @@ Server::ImMessage(BMessage* msg)
case IM_ROOM_CREATED: case IM_ROOM_CREATED:
case IM_ROOM_METADATA: case IM_ROOM_METADATA:
case IM_ROOM_ROLECHANGED: case IM_ROOM_ROLECHANGED:
case IM_ROOM_PARTICIPANTS:
case IM_ROOM_PARTICIPANT_JOINED: case IM_ROOM_PARTICIPANT_JOINED:
case IM_ROOM_PARTICIPANT_LEFT: case IM_ROOM_PARTICIPANT_LEFT:
case IM_ROOM_PARTICIPANT_BANNED: case IM_ROOM_PARTICIPANT_BANNED: