Send extra user mode updates in backwards-compatible manner.
When multiple modes are received in IrcChannel::joinIrcUsers, call
addUserMode one time for each, then call ircuser->addUserModes() with
the new modes. Perhaps less efficient, but avoids breaking protocol.
Reduce excess network traffic by only syncing IrcUser::setUserModes
and IrcUser::addUserModes when changes are made.
Preliminary test results on Ubuntu (more testing always welcome!)
* New core, new client - works fine (as one might hope)
* New core, old client - client prints warning to console but works
(IrcChannel modes might internally get out of sync, but visible
channel list updates with mode changes, multiple modes, etc)
* New core, Quasseldroid alpha/NG - works fine
* Old core, new client - works fine
If desired, the warning and other potential risks could be avoided
entirely by implementing a new Feature flag and only sending the
additional mode information to clients that request it. However,
this seemed excessive to avoid what in limited testing was only a
warning in the client console log, normally hidden away from sight.
for (int i = 0; i < users.count(); i++) {
ircuser = users[i];
if (!ircuser || _userModes.contains(ircuser)) {
for (int i = 0; i < users.count(); i++) {
ircuser = users[i];
if (!ircuser || _userModes.contains(ircuser)) {
- addUserMode(ircuser, modes[i]);
+ if (modes[i].count() > 1) {
+ // Multiple modes received, do it one at a time
+ // TODO Better way of syncing this without breaking protocol?
+ for (int i_m = 0; i_m < modes[i].count(); ++i_m) {
+ addUserMode(ircuser, modes[i][i_m]);
+ }
+ } else {
+ addUserMode(ircuser, modes[i]);
+ }
// If you wonder why there is no counterpart to ircUserJoined:
// the joins are propagated by the ircuser. The signal ircUserJoined is only for convenience
// If you wonder why there is no counterpart to ircUserJoined:
// the joins are propagated by the ircuser. The signal ircUserJoined is only for convenience
+ // Also update the IRC user's record of modes; this allows easier tracking
+ ircuser->addUserModes(modes[i]);
+
newNicks << ircuser->nick();
newModes << modes[i];
newUsers << ircuser;
newNicks << ircuser->nick();
newModes << modes[i];
newUsers << ircuser;
if (!_userModes[ircuser].contains(mode)) {
_userModes[ircuser] += mode;
if (!_userModes[ircuser].contains(mode)) {
_userModes[ircuser] += mode;
+ // Also update the IRC user's record of modes; this allows easier tracking
+ ircuser->addUserModes(mode);
QString nick = ircuser->nick();
SYNC_OTHER(addUserMode, ARG(nick), ARG(mode))
emit ircUserModeAdded(ircuser, mode);
QString nick = ircuser->nick();
SYNC_OTHER(addUserMode, ARG(nick), ARG(mode))
emit ircUserModeAdded(ircuser, mode);
if (_userModes[ircuser].contains(mode)) {
_userModes[ircuser].remove(mode);
if (_userModes[ircuser].contains(mode)) {
_userModes[ircuser].remove(mode);
+ // Also update the IRC user's record of modes; this allows easier tracking
+ ircuser->removeUserModes(mode);
QString nick = ircuser->nick();
SYNC_OTHER(removeUserMode, ARG(nick), ARG(mode));
emit ircUserModeRemoved(ircuser, mode);
QString nick = ircuser->nick();
SYNC_OTHER(removeUserMode, ARG(nick), ARG(mode));
emit ircUserModeRemoved(ircuser, mode);
void IrcUser::setUserModes(const QString &modes)
{
void IrcUser::setUserModes(const QString &modes)
{
- _userModes = modes;
- SYNC(ARG(modes))
- emit userModesSet(modes);
+ if (_userModes != modes) {
+ _userModes = modes;
+ SYNC(ARG(modes))
+ emit userModesSet(modes);
+ }
if (modes.isEmpty())
return;
if (modes.isEmpty())
return;
+ // Don't needlessly sync when no changes are made
+ bool changesMade = false;
for (int i = 0; i < modes.count(); i++) {
for (int i = 0; i < modes.count(); i++) {
- if (!_userModes.contains(modes[i]))
+ if (!_userModes.contains(modes[i])) {
+ changesMade = true;
+ }
- SYNC(ARG(modes))
- emit userModesAdded(modes);
+ if (changesMade) {
+ SYNC(ARG(modes))
+ emit userModesAdded(modes);
+ }
// See: http://ircv3.net/specs/extensions/multi-prefix-3.1.html
while (e->network()->prefixes().contains(nick[0])) {
// Mode found in 1 left-most character, add it to the list.
// See: http://ircv3.net/specs/extensions/multi-prefix-3.1.html
while (e->network()->prefixes().contains(nick[0])) {
// Mode found in 1 left-most character, add it to the list.
- // FIXME Only allow one possible mode to avoid a warning in older clients
- if (mode.isEmpty())
- mode.append(e->network()->prefixToMode(nick[0]));
- //mode.append(e->network()->prefixToMode(nick[0]));
+ // Note: sending multiple modes may cause a warning in older clients.
+ // In testing, the clients still seemed to function fine.
+ mode.append(e->network()->prefixToMode(nick[0]));
// Remove this mode from the nick
nick = nick.remove(0, 1);
}
// Remove this mode from the nick
nick = nick.remove(0, 1);
}