diff --git a/chat/locales/en-US/irc.properties b/chat/locales/en-US/irc.properties index f39f83aab7..c95f5e5c1f 100644 --- a/chat/locales/en-US/irc.properties +++ b/chat/locales/en-US/irc.properties @@ -109,7 +109,7 @@ message.parted=%1$S has left the room (Part%2$S). message.parted.reason=: %S # %1$S is the user's nick, %2$S is message.quit2 if a quit message is given. message.quit=%1$S has left the room (Quit%2$S). -# The paramter is the quit message given by the user. +# The parameter is the quit message given by the user. message.quit2=: %S # %1$S is the nickname of the user that invited us, %2$S is the conversation # name. @@ -161,8 +161,12 @@ error.mode.wrongUser=You cannot change modes for other users. error.noSuchNick=%S is not online. error.wasNoSuchNick=There was no nickname: %S error.noSuchChannel=There is no channel: %S. +error.unavailable=%S is temporarily unavailable. # %S is the channel name. +error.channelBanned=You have been banned from %S. error.cannotSendToChannel=You cannot send messages to %S. +error.channelFull=The channel %S is full. +error.inviteOnly=You must be invited to join %S. error.nonUniqueTarget=%S is not a unique user@host or shortname or you have tried to join too many channels at once. error.notChannelOp=You are not a channel operator on %S. error.notChannelOwner=You are not a channel owner of %S. diff --git a/chat/protocols/irc/irc.js b/chat/protocols/irc/irc.js index 2ed51c0f36..ffec2bed3a 100644 --- a/chat/protocols/irc/irc.js +++ b/chat/protocols/irc/irc.js @@ -795,7 +795,6 @@ function ircAccount(aProtocol, aImAccount) { this.trackQueue = []; this.pendingIsOnQueue = []; this.whoisInformation = new NormalizedMap(this.normalizeNick.bind(this)); - this._chatRoomFieldsList = {}; this._caps = []; this._roomInfoCallbacks = new Set(); @@ -1428,10 +1427,6 @@ ircAccount.prototype = { createConversation: function(aName) this.getConversation(aName), - // Temporarily stores the prplIChatRoomFieldValues passed to joinChat for - // each channel to enable later reconnections. - _chatRoomFieldsList: {}, - // aComponents implements prplIChatRoomFieldValues. joinChat: function(aComponents) { let channel = aComponents.getValue("channel"); @@ -1439,6 +1434,7 @@ ircAccount.prototype = { this.ERROR("joinChat called without a channel name."); return null; } + // A channel prefix is required. If the user didn't include one, // we prepend # automatically to match the behavior of other // clients. Not doing it used to cause user confusion. @@ -1457,13 +1453,13 @@ ircAccount.prototype = { if (key) params.push(key); let defaultName = key ? channel + " " + key : channel; - this._chatRoomFieldsList[this.normalize(channel)] = - this.getChatRoomDefaultFieldValues(defaultName); // Send the join command, but don't log the channel key. this.sendMessage("JOIN", params, "JOIN " + channel + (key ? " " : "")); // Open conversation early for better responsiveness. let conv = this.getConversation(channel); + // Store the prplIChatRoomFieldValues to enable later reconnections. + conv._chatRoomFields = this.getChatRoomDefaultFieldValues(defaultName); conv.joining = true; return conv; }, diff --git a/chat/protocols/irc/ircBase.jsm b/chat/protocols/irc/ircBase.jsm index d014cf3b7d..8b331dc3fc 100644 --- a/chat/protocols/irc/ircBase.jsm +++ b/chat/protocols/irc/ircBase.jsm @@ -186,12 +186,7 @@ var ircBase = { delete conversation._firstJoin; // Ensure chatRoomFields information is available for reconnection. - let nName = this.normalize(channelName); - if (hasOwnProperty(this._chatRoomFieldsList, nName)) { - conversation._chatRoomFields = this._chatRoomFieldsList[nName]; - delete this._chatRoomFieldsList[nName]; - } - else { + if (!conversation._chatRoomFields) { this.WARN("Opening a MUC without storing its " + "prplIChatRoomFieldValues first."); conversation._chatRoomFields = @@ -199,7 +194,7 @@ var ircBase = { } } else { - // Don't worry about adding ourself, RPL_NAMES takes care of that + // Don't worry about adding ourself, RPL_NAMREPLY takes care of that // case. conversation.getParticipant(aMessage.nickname, true); let msg = _("message.join", aMessage.nickname, aMessage.source || ""); @@ -1086,8 +1081,8 @@ var ircBase = { }, "403": function(aMessage) { // ERR_NOSUCHCHANNEL // :No such channel - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return conversationErrorMessage(this, aMessage, "error.noChannel"); + return conversationErrorMessage(this, aMessage, "error.noChannel", true, + false); }, "404": function(aMessage) { // ERR_CANNOTSENDTOCHAN // :Cannot send to channel @@ -1097,9 +1092,8 @@ var ircBase = { }, "405": function(aMessage) { // ERR_TOOMANYCHANNELS // :You have joined too many channels - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return serverErrorMessage(this, aMessage, - _("error.tooManyChannels", aMessage.params[1])); + return conversationErrorMessage(this, aMessage, "error.tooManyChannels", + true); }, "406": function(aMessage) { // ERR_WASNOSUCHNICK // :There was no such nickname @@ -1109,8 +1103,8 @@ var ircBase = { }, "407": function(aMessage) { // ERR_TOOMANYTARGETS // : recipients. - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return conversationErrorMessage(this, aMessage, "error.nonUniqueTarget"); + return conversationErrorMessage(this, aMessage, "error.nonUniqueTarget", + false, false); }, "408": function(aMessage) { // ERR_NOSUCHSERVICE // :No such service @@ -1205,9 +1199,8 @@ var ircBase = { }, "437": function(aMessage) { // ERR_UNAVAILRESOURCE // :Nick/channel is temporarily unavailable - // TODO - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return false; + return conversationErrorMessage(this, aMessage, "error.unavailable", + true); }, "441": function(aMessage) { // ERR_USERNOTINCHANNEL // :They aren't on that channel @@ -1291,9 +1284,8 @@ var ircBase = { }, "471": function(aMessage) { // ERR_CHANNELISFULL // :Cannot join channel (+l) - // TODO - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return false; + return conversationErrorMessage(this, aMessage, "error.channelFull", + true); }, "472": function(aMessage) { // ERR_UNKNOWNMODE // :is unknown mode char to me for @@ -1302,35 +1294,22 @@ var ircBase = { }, "473": function(aMessage) { // ERR_INVITEONLYCHAN // :Cannot join channel (+i) - // TODO - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return false; + return conversationErrorMessage(this, aMessage, "error.inviteOnly", + true, false); }, "474": function(aMessage) { // ERR_BANNEDFROMCHAN // :Cannot join channel (+b) - // TODO - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; - return false; + return conversationErrorMessage(this, aMessage, "error.channelBanned", + true, false); }, "475": function(aMessage) { // ERR_BADCHANNELKEY // :Cannot join channel (+k) - let channelName = aMessage.params[1]; - - // Display an error message to the user. - let msg = _("error.wrongKey", channelName); - let conversation = this.getConversation(channelName); - conversation.writeMessage(aMessage.servername, msg, {system: true}); - - // The stored information is out of date, remove it. - delete conversation._chatRoomFields; - delete this._chatRoomFieldsList[this.normalize(channelName)]; - - return true; + return conversationErrorMessage(this, aMessage, "error.wrongKey", + true, false); }, "476": function(aMessage) { // ERR_BADCHANMASK // :Bad Channel Mask // TODO - delete this._chatRoomFieldsList[this.normalize(aMessage.params[1])]; return false; }, "477": function(aMessage) { // ERR_NOCHANMODES diff --git a/chat/protocols/irc/ircUtils.jsm b/chat/protocols/irc/ircUtils.jsm index 59febffeca..af9c3c4448 100644 --- a/chat/protocols/irc/ircUtils.jsm +++ b/chat/protocols/irc/ircUtils.jsm @@ -216,10 +216,25 @@ function mIRCColoring(aStack, aInput) { return [stack, output, length]; } -function conversationErrorMessage(aAccount, aMessage, aError) { +// Print an error message into a conversation, optionally mark the conversation +// as not joined and/or not rejoinable. +function conversationErrorMessage(aAccount, aMessage, aError, + aJoinFailed = false, aRejoinable = true) { let conv = aAccount.getConversation(aMessage.params[1]); conv.writeMessage(aMessage.servername, _(aError, aMessage.params[1]), {error: true, system: true}); delete conv._pendingMessage; + + // Channels have a couple extra things that can be done to them. + if (aAccount.isMUCName(aMessage.params[1])) { + // If a value for joining is explictly given, mark it. + if (aJoinFailed) + conv.joining = false; + // If the conversation cannot be rejoined automatically, delete + // _chatRoomFields. + if (!aRejoinable) + delete conv._chatRoomFields; + } + return true; }