/* jshint sub: true */ var /** * @type {SlackWrapper} **/ DATA, /** * @type {Array.} **/ HIGHLIGHTED_CHANS = []; /** * @constructor * @implements {ChatSystem} * @extends {ChatContext} **/ function SimpleChatSystem() { ChatContext.call(this); } SimpleChatSystem.prototype = Object.create(ChatContext.prototype); SimpleChatSystem.prototype.constructor = SimpleChatSystem; SimpleChatSystem.prototype.getId = function() { return this.team ? this.team.id : null; }; SimpleChatSystem.prototype.getChatContext = function() { return this; }; SimpleChatSystem.prototype.onRequest = function() { console.error("unimplemented"); }; SimpleChatSystem.prototype.sendMeMsg = function(chan, text) { console.error("unimplemented"); }; SimpleChatSystem.prototype.sendMsg = function(chan, text, attachments) { console.error("unimplemented"); }; SimpleChatSystem.prototype.removeMsg = function(chan, ts) { console.error("unimplemented"); }; SimpleChatSystem.prototype.starMsg = function(chan, msgId) { console.error("unimplemented"); }; SimpleChatSystem.prototype.unstarMsg = function(chan, msgId) { console.error("unimplemented"); }; SimpleChatSystem.prototype.pinMsg = function(chan, msgId) { console.error("unimplemented"); }; SimpleChatSystem.prototype.unpinMsg = function(chan, msgId) { console.error("unimplemented"); }; SimpleChatSystem.prototype.editMsg = function(chan, ts, newText) { console.error("unimplemented"); }; SimpleChatSystem.prototype.addReaction = function(chan, ts, reaction) { console.error("unimplemented"); }; SimpleChatSystem.prototype.removeReaction = function(chan, ts, reaction) { console.error("unimplemented"); }; SimpleChatSystem.prototype.openUploadFileStream = function(chan, contentType, callback) { console.error("unimplemented"); }; SimpleChatSystem.prototype.fetchHistory = function(chan) { console.error("unimplemented"); }; SimpleChatSystem.prototype.sendTyping = function(chan) { console.error("unimplemented"); }; SimpleChatSystem.prototype.markRead = function(chan, ts) { console.error("unimplemented"); }; SimpleChatSystem.prototype.sendCommand = function(chan, cmd, args) { console.error("unimplemented"); }; SimpleChatSystem.prototype.poll = function(knownVersion, now) { console.error("unimplemented"); return null; }; /** * @constructor **/ function SlackWrapper() { /** @type {number} */ this.lastServerVersion = 0; /** @type {MultiChatManager} */ this.context = new MultiChatManager(); /** @type {!Object.} **/ this.history = {}; } SlackWrapper.prototype.update = function(data) { var now = Date.now(), i; if (data["v"]) this.lastServerVersion = data["v"]; if (data["static"]) { for (i in data["static"]) { var ctx = this.context.getById(i); if (!ctx) { ctx = new SimpleChatSystem(); this.context.push(ctx); } var pins = {}; if (data["static"][i]["channels"]) data["static"][i]["channels"].forEach(function(chanInfo) { if (chanInfo["pins"]) { pins[chanInfo["id"]] = chanInfo["pins"]; chanInfo["pins"] = undefined; } }); ctx.getChatContext().updateStatic(data["static"][i], now); for (var chanId in pins) { var msgs = [], histo = this.history[chanId]; if (!histo) histo = this.history[chanId] = new UiRoomHistory(chanId, 250, null, now); pins[chanId].forEach(function(msg) { msgs.push(histo.messageFactory(msg, now)); }); ctx.getChatContext().channels[chanId].pins = msgs; } } } this.context.foreachChannels(function(chan) { if (chan.lastMsg === chan.lastRead) { var pos = HIGHLIGHTED_CHANS.indexOf(chan); if (pos !== -1) HIGHLIGHTED_CHANS.splice(pos, 1); } }); if (data["live"]) { for (i in data["live"]) { var history = this.history[i]; if (!history) history = this.history[i] = new UiRoomHistory(i, 250, data["live"][i], now); else history.pushAll(data["live"][i], now); } for (var roomId in data["live"]) { var liveCtx = this.context.getChannelContext(roomId).getChatContext(), chan = liveCtx.channels[roomId]; if (chan) { if (this.history[roomId].messages.length) chan.setLastMsg(this.history[roomId].lastMessage().ts, now); if (!chan.archived) { onMsgReceived(liveCtx, chan, data["live"][roomId]); if (SELECTED_ROOM && data["live"][SELECTED_ROOM.id]) onRoomUpdated(); } } else { outOfSync(); } } } if (data["static"]) { onContextUpdated(); } var typingUpdated = false; if (data["typing"]) { this.context.contexts.forEach(function(ctx) { var chatCtx = ctx.getChatContext(); typingUpdated |= chatCtx.updateTyping(data["typing"], now); }, this); } if (data["static"] || typingUpdated) onTypingUpdated(); if (data["config"]) { CONFIG = new Config(data["config"]); onConfigUpdated(); } if (SELECTED_CONTEXT && SELECTED_ROOM && data["static"] && data["static"][SELECTED_CONTEXT.team.id] && data["static"][SELECTED_CONTEXT.team.id]["channels"] && data["static"][SELECTED_CONTEXT.team.id]["channels"]) { var arr = data["static"][SELECTED_CONTEXT.team.id]["channels"]; i =0; for (var nbChan = arr.length; i < nbChan; i++) { if (arr[i].id === SELECTED_ROOM.id) { onRoomUpdated(); break; } } } }; setInterval(function() { var updated = false, now = Date.now(); DATA.context.foreachContext(function(ctx) { if (ctx.getChatContext().cleanTyping(now)) updated = true; }); if (updated) onTypingUpdated(); }, 1000); /** * @param {ChatContext} ctx * @param {string} text * @return {boolean} **/ function isHighlighted(ctx, text) { var highlights = ctx.self.prefs.highlights; for (var i =0, nbHighlights = highlights.length; i < nbHighlights; i++) if (text.indexOf(highlights[i]) !== -1) { return true; } return false; } /** * @param {ChatContext} ctx * @param {Room} chan * @param {Array.<*>} msg **/ function onMsgReceived(ctx, chan, msg) { if (chan !== SELECTED_ROOM || !window.hasFocus) { var selfId = ctx.self ? ctx.self.id : null, selfReg = selfId ? new RegExp("<@" +selfId) : null, // FIXME remove context id highligted = false, areNew = false, newHighlited = false; msg.forEach(function(i) { if (parseFloat(i["ts"]) <= chan.lastRead) { return; } if (i["user"] !== ctx.self.id) { areNew = true; if (chan instanceof PrivateMessageRoom || (i["text"] && ((selfReg && i["text"].match(selfReg)) || isHighlighted(ctx, i["text"])))) { if (HIGHLIGHTED_CHANS.indexOf(chan) === -1) { newHighlited = true; HIGHLIGHTED_CHANS.push(chan); } highligted = true; } } }); if (areNew) { updateTitle(); var dom = document.getElementById("room_" +chan.id); if (dom) { dom.classList.add(R.klass.unread); if (highligted) dom.classList.add(R.klass.unreadHi); } if (newHighlited && !window.hasFocus) { // TODO setting spawnNotification(); } } } msg.forEach(function(m) { if (!selfId || selfId === m.userId) { for (var i =0, nbPending = PENDING_MESSAGES.length; i < nbPending; i++) { var current = PENDING_MESSAGES[i]; if (current.channel === chan.id && !!m["isMeMessage"] === current.isMe && ((m["pendingId"] === current.pendingId && current.pendingId) || (!current.pendingId && m["text"].trim() === current.text))) { PENDING_MESSAGES.splice(i, 1); return; } } } }); } /** * @param {Room} room **/ function markRoomAsRead(room) { var highlightIndex = HIGHLIGHTED_CHANS.indexOf(room); if (room.lastMsg > room.lastRead) { var history = DATA.history[room.id]; if (history) { var lastMsg = history.lastMessage(); if (lastMsg) { sendReadMarker(room, lastMsg.id, lastMsg.ts); room.lastRead = lastMsg.ts; } } } if (highlightIndex >= 0) { HIGHLIGHTED_CHANS.splice(highlightIndex, 1); updateTitle(); } var roomLi = document.getElementById("room_" +room.id); roomLi.classList.remove(R.klass.unread); roomLi.classList.remove(R.klass.unreadHi); } function invalidateAllMessages() { for (var i in DATA.history) DATA.history[i].invalidateAllMessages(); if (SELECTED_ROOM) onRoomUpdated(); } DATA = new SlackWrapper();