Bug 1176958 - Update participants list when a nick is changed in XMPP MUC. r=aleth,clokep

This commit is contained in:
Abdelrhman Ahmed 2015-08-29 13:59:03 +02:00
Родитель 125618e3cd
Коммит 0b0b3abde6
7 изменённых файлов: 106 добавлений и 114 удалений

Просмотреть файл

@ -56,6 +56,17 @@ topicChanged=%1$S has changed the topic to: %2$S.
# %1$S is the user who cleared the topic. # %1$S is the user who cleared the topic.
topicCleared=%1$S has cleared the topic. topicCleared=%1$S has cleared the topic.
# LOCALIZATION NOTE (nickSet):
# This is displayed as a system message when a participant changes his/her
# nickname in a conversation.
# %1$S is the old nick.
# %2$S is the new nick.
nickSet=%1$S is now known as %2$S.
# LOCALIZATION NOTE (nickSet.you):
# This is displayed as a system message when your nickname is changed.
# %S is your new nick.
nickSet.you=You are now known as %S.
# LOCALIZATION NOTE (messenger.conversations.selections.ellipsis): # LOCALIZATION NOTE (messenger.conversations.selections.ellipsis):
# ellipsis is used when copying a part of a message to show that the message was cut # ellipsis is used when copying a part of a message to show that the message was cut
messenger.conversations.selections.ellipsis=[…] messenger.conversations.selections.ellipsis=[…]

Просмотреть файл

@ -96,10 +96,6 @@ message.usermode=Mode %1$S for %2$S set by %3$S.
message.channelmode=Channel mode %1$S set by %2$S. message.channelmode=Channel mode %1$S set by %2$S.
# %S is the user's mode. # %S is the user's mode.
message.yourmode=Your mode is %S. message.yourmode=Your mode is %S.
# %1$S is the old nick and %2$S is the new nick.
message.nick=%1$S is now known as %2$S.
# %S is your new nick.
message.nick.you=You are now known as %S.
# Could not change the nickname. %S is the user's nick. # Could not change the nickname. %S is the user's nick.
message.nick.fail=Could not use the desired nickname. Your nick remains %S. message.nick.fail=Could not use the desired nickname. Your nick remains %S.
# The parameter is the message.parted.reason, if a part message is given. # The parameter is the message.parted.reason, if a part message is given.

Просмотреть файл

@ -626,6 +626,66 @@ const GenericConvChatPrototype = {
}, },
getNormalizedChatBuddyName: aChatBuddyName => aChatBuddyName, getNormalizedChatBuddyName: aChatBuddyName => aChatBuddyName,
// Updates the nick of a participant in conversation to a new one.
updateNick: function(aOldNick, aNewNick, isOwnNick) {
let message;
let isParticipant = this._participants.has(aOldNick);
if (isOwnNick) {
// If this is the user's nick, change it.
this.nick = aNewNick;
message = _("nickSet.you", aNewNick);
// If the account was disconnected, it's OK the user is not a participant.
if (!isParticipant)
return;
}
else if (!isParticipant) {
this.ERROR("Trying to rename nick that doesn't exist! " + aOldNick +
" to " + aNewNick);
return;
}
else
message = _("nickSet", aOldNick, aNewNick);
// Get the original participant and then remove it.
let participant = this._participants.get(aOldNick);
this._participants.delete(aOldNick);
// Update the nickname and add it under the new nick.
participant.name = aNewNick;
this._participants.set(aNewNick, participant);
this.notifyObservers(participant, "chat-buddy-update", aOldNick);
this.writeMessage(aOldNick, message, {system: true});
},
// Removes a participant from conversation.
removeParticipant: function(aNick) {
if (!this._participants.has(aNick))
return;
let stringNickname = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
stringNickname.data = aNick;
this.notifyObservers(new nsSimpleEnumerator([stringNickname]),
"chat-buddy-remove");
this._participants.delete(aNick);
},
// Removes all participant in conversation.
removeAllParticipants: function() {
let stringNicknames = [];
this._participants.forEach(function(aParticipant) {
let stringNickname = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
stringNickname.data = aParticipant.name;
stringNicknames.push(stringNickname);
});
this.notifyObservers(new nsSimpleEnumerator(stringNicknames),
"chat-buddy-remove");
this._participants.clear();
},
writeMessage: function (aWho, aText, aProperties) { writeMessage: function (aWho, aText, aProperties) {
aProperties.containsNick = aProperties.containsNick =
"incoming" in aProperties && this._pingRegexp.test(aText); "incoming" in aProperties && this._pingRegexp.test(aText);
@ -637,7 +697,8 @@ const GenericConvChatBuddyPrototype = {
__proto__: ClassInfo("prplIConvChatBuddy", "generic ConvChatBuddy object"), __proto__: ClassInfo("prplIConvChatBuddy", "generic ConvChatBuddy object"),
_name: "", _name: "",
get name() { return this._name; }, get name() this._name,
set name(aName) this._name = aName,
alias: "", alias: "",
buddy: false, buddy: false,

Просмотреть файл

@ -375,56 +375,6 @@ ircChannel.prototype = {
} }
return participant; return participant;
}, },
updateNick: function(aOldNick, aNewNick) {
let isParticipant = this._participants.has(aOldNick);
if (this.normalizeNick(aOldNick) == this.normalizeNick(this.nick)) {
// If this is the user's nick, change it.
this.nick = aNewNick;
// If the account was disconnected, it's OK the user is not a participant.
if (!isParticipant)
return;
}
else if (!isParticipant) {
this.ERROR("Trying to rename nick that doesn't exist! " + aOldNick +
" to " + aNewNick);
return;
}
// Get the original ircParticipant and then remove it.
let participant = this.getParticipant(aOldNick);
this._participants.delete(aOldNick);
// Update the nickname and add it under the new nick.
participant._name = aNewNick;
this._participants.set(aNewNick, participant);
this.notifyObservers(participant, "chat-buddy-update", aOldNick);
},
removeParticipant: function(aNick) {
if (!this._participants.has(aNick))
return;
let stringNickname = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
stringNickname.data = aNick;
this.notifyObservers(new nsSimpleEnumerator([stringNickname]),
"chat-buddy-remove");
this._participants.delete(aNick);
},
// Use this before joining to avoid errors of trying to re-add an existing
// participant
removeAllParticipants: function() {
let stringNicknames = [];
this._participants.forEach(function(aParticipant) {
let stringNickname = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
stringNickname.data = aParticipant.name;
stringNicknames.push(stringNickname);
});
this.notifyObservers(new nsSimpleEnumerator(stringNicknames),
"chat-buddy-remove");
this._participants.clear();
},
/* /*
* Add/remove modes from this channel. * Add/remove modes from this channel.
@ -1285,25 +1235,24 @@ ircAccount.prototype = {
return buddy; return buddy;
}, },
changeBuddyNick: function(aOldNick, aNewNick) { changeBuddyNick: function(aOldNick, aNewNick) {
let msg;
if (this.normalizeNick(aOldNick) == this.normalizeNick(this._nickname)) { if (this.normalizeNick(aOldNick) == this.normalizeNick(this._nickname)) {
// Your nickname changed! // Your nickname changed!
this._nickname = aNewNick; this._nickname = aNewNick;
msg = _("message.nick.you", aNewNick);
this.conversations.forEach(conversation => { this.conversations.forEach(conversation => {
// Update the nick for chats, and inform the user in every conversation. // Update the nick for chats, and inform the user in every conversation.
if (conversation.isChat) if (conversation.isChat)
conversation.updateNick(aOldNick, aNewNick); conversation.updateNick(aOldNick, aNewNick, true);
conversation.writeMessage(aOldNick, msg, {system: true}); else {
conversation.writeMessage(aOldNick, _conv("nickSet.you", aNewNick),
{system: true});
}
}); });
} }
else { else {
msg = _("message.nick", aOldNick, aNewNick);
this.conversations.forEach(conversation => { this.conversations.forEach(conversation => {
if (conversation.isChat && conversation._participants.has(aOldNick)) { if (conversation.isChat && conversation._participants.has(aOldNick)) {
// Update the nick in every chat conversation it is in. // Update the nick in every chat conversation it is in.
conversation.updateNick(aOldNick, aNewNick); conversation.updateNick(aOldNick, aNewNick, false);
conversation.writeMessage(aOldNick, msg, {system: true});
} }
}); });
} }

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const EXPORTED_SYMBOLS = ["_", "ctcpFormatToText", "ctcpFormatToHTML", const EXPORTED_SYMBOLS = ["_", "_conv", "ctcpFormatToText", "ctcpFormatToHTML",
"conversationErrorMessage", "kListRefreshInterval"]; "conversationErrorMessage", "kListRefreshInterval"];
const {classes: Cc, interfaces: Ci} = Components; const {classes: Cc, interfaces: Ci} = Components;
@ -13,6 +13,10 @@ XPCOMUtils.defineLazyGetter(this, "_", () =>
l10nHelper("chrome://chat/locale/irc.properties") l10nHelper("chrome://chat/locale/irc.properties")
); );
XPCOMUtils.defineLazyGetter(this, "_conv", () =>
l10nHelper("chrome://chat/locale/conversations.properties")
);
XPCOMUtils.defineLazyGetter(this, "TXTToHTML", function() { XPCOMUtils.defineLazyGetter(this, "TXTToHTML", function() {
let cs = Cc["@mozilla.org/txttohtmlconv;1"].getService(Ci.mozITXTToHTMLConv); let cs = Cc["@mozilla.org/txttohtmlconv;1"].getService(Ci.mozITXTToHTMLConv);
return aTXT => cs.scanTXT(aTXT, cs.kEntities); return aTXT => cs.scanTXT(aTXT, cs.kEntities);

Просмотреть файл

@ -249,6 +249,17 @@ const XMPPMUCConversationPrototype = {
let codes = x.getElements(["status"]).map(elt => elt.attributes["code"]); let codes = x.getElements(["status"]).map(elt => elt.attributes["code"]);
let item = x.getElement(["item"]); let item = x.getElement(["item"]);
// Changes the nickname of a participant for this muc.
let changeNick = () => {
if (!item || !item.attributes["nick"]) {
this.WARN("Received a MUC presence code 303 or 210 stanza without an " +
"item element or a nick attribute.");
return;
}
let newNick = item.attributes["nick"];
this.updateNick(nick, newNick, nick == this.nick);
};
if (aStanza.attributes["type"] == "unavailable") { if (aStanza.attributes["type"] == "unavailable") {
if (!this._participants.has(nick)) { if (!this._participants.has(nick)) {
this.WARN("received unavailable presence for an unknown MUC participant: " + this.WARN("received unavailable presence for an unknown MUC participant: " +
@ -258,13 +269,7 @@ const XMPPMUCConversationPrototype = {
if (codes.indexOf("303") != -1) { if (codes.indexOf("303") != -1) {
// XEP-0045 (7.6): Changing Nickname. // XEP-0045 (7.6): Changing Nickname.
// Service Updates Nick for user. // Service Updates Nick for user.
if (!item || !item.attributes["nick"]) { changeNick();
this.WARN("Received a MUC presence code 303 stanza without an item " +
"element or a nick attribute.");
return;
}
let participant = this._participants.get(nick);
participant.name = item.attributes["nick"];
return; return;
} }
if (item && item.attributes["role"] == "none") { if (item && item.attributes["role"] == "none") {
@ -350,6 +355,13 @@ const XMPPMUCConversationPrototype = {
return true; return true;
}); });
} }
else if (codes.indexOf("210") != -1) {
// XEP-0045 (7.6): Changing Nickname.
// Service modifies this user's nickname in accordance with local service
// policies.
changeNick();
return;
}
else if (codes.indexOf("110") != -1) { else if (codes.indexOf("110") != -1) {
// XEP-0045: Room exists and joined successfully. // XEP-0045: Room exists and joined successfully.
this.left = false; this.left = false;
@ -414,33 +426,6 @@ const XMPPMUCConversationPrototype = {
return this._account.normalizeFullJid(this.name + "/" + aNick); return this._account.normalizeFullJid(this.name + "/" + aNick);
}, },
// Removes a participant from MUC conversation.
removeParticipant: function(aNick) {
if (!this._participants.has(aNick))
return;
this._participants.delete(aNick);
let nickString = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
nickString.data = aNick;
this.notifyObservers(new nsSimpleEnumerator([nickString]),
"chat-buddy-remove");
},
// Removes all participant in MUC conversation.
removeAllParticipants: function() {
let stringNicknames = [];
this._participants.forEach(function(aParticipant) {
let stringNickname = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
stringNickname.data = aParticipant.name;
stringNicknames.push(stringNickname);
});
this.notifyObservers(new nsSimpleEnumerator(stringNicknames),
"chat-buddy-remove");
this._participants.clear();
},
// Leaves MUC conversation. // Leaves MUC conversation.
part: function(aMsg = null) { part: function(aMsg = null) {
let s = Stanza.presence({to: this.name + "/" + this._nick, type: "unavailable"}, let s = Stanza.presence({to: this.name + "/" + this._nick, type: "unavailable"},

Просмотреть файл

@ -121,23 +121,6 @@ YahooConference.prototype = {
{system: true}); {system: true});
}, },
removeParticipant: function(aName) {
// In case we receive two logoff packets, make sure that the user is
// actually here before continuing.
if (!this._participants.has(aName))
return;
let stringNickname = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString);
stringNickname.data = aName;
this.notifyObservers(new nsSimpleEnumerator([stringNickname]),
"chat-buddy-remove");
this._participants.delete(aName);
this.writeMessage(this._roomName,
_("system.message.conferenceLogoff", aName),
{system: true});
},
getParticipantNames: function() { return [for (p of this._participants.values()) p.name]; } getParticipantNames: function() { return [for (p of this._participants.values()) p.name]; }
}; };
@ -304,6 +287,9 @@ YahooAccount.prototype = {
return; return;
let conf = this._conferences.get(aRoom); let conf = this._conferences.get(aRoom);
conf.removeParticipant(aUsername); conf.removeParticipant(aUsername);
conf.writeMessage(this._roomName,
_("system.message.conferenceLogoff", aName),
{system: true});
}, },
deleteConference: function(aName) { deleteConference: function(aName) {