| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- /* jshint sub: true */
- /**
- * @constructor
- * @extends {RoomHistory}
- * @param {Room|string} room or roomId
- * @param {number} keepMessages number of messages to keep in memory
- * @param {Array|undefined} evts
- * @param {number|undefined} now
- **/
- function UiRoomHistory(room, keepMessages, evts, now) {
- RoomHistory.call(this, room, keepMessages, 0, evts, now);
- }
- UiRoomHistory.prototype = Object.create(RoomHistory.prototype);
- UiRoomHistory.prototype.constructor = UiRoomHistory;
- UiRoomHistory.prototype.messageFactory = function(ev, ts) {
- if (ev["isMeMessage"] === true)
- return new UiMeMessage(this.id, ev, ts);
- if (ev["isNotice"] === true)
- return new UiNoticeMessage(this.id, ev, ts);
- return new UiMessage(this.id, ev, ts);
- };
- UiRoomHistory.prototype.invalidateAllMessages = function() {
- this.messages.forEach(function(m) {
- m.invalidate();
- });
- };
- /** @interface */
- function IUiMessage() {}
- /**
- * @return {Element}
- **/
- IUiMessage.prototype.getDom = function() {};
- /**
- * @return {IUiMessage}
- **/
- IUiMessage.prototype.removeDom = function() {};
- /**
- * @return {IUiMessage}
- **/
- IUiMessage.prototype.invalidate = function() {};
- /**
- * @return {IUiMessage}
- **/
- IUiMessage.prototype.createDom = function() {};
- /**
- * @return {IUiMessage}
- **/
- IUiMessage.prototype.updateDom = function() {};
- /**
- * @return {Element}
- **/
- IUiMessage.prototype.duplicateDom = function() {};
- /** @const */
- var AbstractUiMessage = (function() {
- var updateReactions = function(_this, channelId) {
- var reactionFrag = document.createDocumentFragment();
- if (_this.reactions) {
- for (var reaction in _this.reactions) {
- var reac = createReactionDom(channelId, _this.id, reaction, _this.reactions[reaction]);
- if (reac)
- reactionFrag.appendChild(reac);
- }
- }
- _this.dom.reactions.textContent = '';
- _this.dom.reactions.appendChild(reactionFrag);
- },
- _linkFilter = function(msgContext, str) {
- var sep = str.indexOf('|'),
- link,
- text,
- isInternal = false;
- if (sep === -1) {
- link = str;
- } else {
- link = str.substr(0, sep);
- text = str.substr(sep +1);
- }
- var newLink;
- if (link[0] === '@') {
- newLink = msgContext.context.getId() +'|' +link.substr(1);
- var user = DATA.context.getUser(newLink);
- if (user) {
- isInternal = true;
- link = '#' +user.privateRoom.id;
- text = '@' +user.name;
- } else {
- return null;
- }
- } else if (link[0] === '#') {
- newLink = msgContext.context.getId() +'|' +link.substr(1);
- var chan = DATA.context.getChannel(newLink);
- if (chan) {
- isInternal = true;
- link = '#' +newLink;
- text = '#' +chan.name;
- } else {
- return null;
- }
- } else {
- if (!link.match(/^(https?|mailto):\/\//i))
- return null;
- isInternal = false;
- }
- return {
- link: link,
- text: text || link,
- isInternal: isInternal
- };
- },
- _formatText = function(_this, text) {
- return formatText(text, {
- highlights: _this.context.self.prefs.highlights,
- emojiFormatFunction: function(emoji) {
- if (emoji[0] === ':' && emoji[emoji.length -1] === ':')
- emoji = emoji.substr(1, emoji.length -2);
- var emojiDom = makeEmojiDom(emoji);
- if (emojiDom) {
- var domParent = document.createElement("span");
- domParent.className = R.klass.emoji.small;
- domParent.appendChild(emojiDom);
- return domParent.outerHTML;
- }
- return null;
- },
- linkFilter: function(link) {
- return _linkFilter(_this, link);
- }
- });
- },
- updateAttachments = function(_this, channelId) {
- var attachmentFrag = document.createDocumentFragment();
- for (var i =0, nbAttachments = _this.attachments.length; i < nbAttachments; i++) {
- var attachment = _this.attachments[i];
- if (attachment) {
- var domAttachment = createAttachmentDom(channelId, _this, attachment, i);
- if (domAttachment)
- attachmentFrag.appendChild(domAttachment);
- }
- }
- _this.dom.attachments.textContent = '';
- _this.dom.attachments.appendChild(attachmentFrag);
- },
- updateCommon = function(_this, sender) {
- _this.dom.ts.innerHTML = locale.formatDate(_this.ts);
- _this.dom.textDom.innerHTML = _formatText(_this, _this.text);
- _this.dom.authorName.textContent = sender ? sender.name : (_this.username || "?");
- };
- return {
- /** @type {Element|null} *
- dom: null,
- /** @type {boolean} *
- uiNeedRefresh: true,
- */
- /** @param {IUiMessage} _this */
- invalidate: function(_this) {
- _this.uiNeedRefresh = true;
- return _this;
- },
- /** @param {UiMessage|UiMeMessage|UiNoticeMessage} _this */
- removeDom: function(_this) {
- if (_this.dom && _this.dom.parentElement) {
- _this.dom.remove();
- delete(_this.dom);
- }
- return _this;
- },
- /** @param {UiMessage|UiMeMessage|UiNoticeMessage} _this */
- getDom: function(_this) {
- if (!_this.dom) {
- _this.createDom().updateDom();
- } else if (_this.uiNeedRefresh) {
- _this.uiNeedRefresh = false;
- _this.updateDom();
- }
- return _this.dom;
- },
- /** @param {UiMessage|UiMeMessage|UiNoticeMessage} _this */
- updateDom: function(_this) {
- var sender = DATA.context.getUser(_this.userId);
- updateCommon(_this, sender);
- updateAttachments(_this, _this.channelId);
- updateReactions(_this, _this.channelId);
- if (_this.edited) {
- _this.dom.edited.innerHTML = locale.edited(_this.edited);
- _this.dom.classList.add(R.klass.msg.editedStatus);
- }
- return _this;
- },
- duplicateDom: function(_this) {
- return _this.dom.cloneNode(true);
- },
- formatText: function(_this, text) {
- return _formatText(_this, text);
- }
- };
- })();
- /**
- * @constructor
- * @implements {IUiMessage}
- * @extends {MeMessage}
- * @param {*} ev
- * @param {number} ts
- **/
- function UiMeMessage(channelId, ev, ts) {
- // Extends AbstractUiMessage and MeMessage
- MeMessage.call(this, ev, ts);
- /** @const @type {ChatContext} */
- this.context = DATA.context.getChannelContext(channelId).getChatContext();
- /** @type {string} @const */
- this.channelId = channelId;
- this.dom = AbstractUiMessage.dom;
- this.uiNeedRefresh = AbstractUiMessage.uiNeedRefresh;
- }
- UiMeMessage.prototype = Object.create(MeMessage.prototype);
- UiMeMessage.prototype.constructor = UiMeMessage;
- UiMeMessage.prototype.invalidate = function() {
- return AbstractUiMessage.invalidate(this);
- };
- UiMeMessage.prototype.formatText = function(text) {
- return AbstractUiMessage.formatText(this, text);
- };
- UiMeMessage.prototype.removeDom = function() {
- return AbstractUiMessage.removeDom(this);
- };
- UiMeMessage.prototype.getDom = function() {
- return AbstractUiMessage.getDom(this);
- };
- UiMeMessage.prototype.createDom = function() {
- this.dom = doCreateMessageDom(this, false);
- this.dom.classList.add(R.klass.msg.meMessage);
- return this;
- };
- UiMeMessage.prototype.duplicateDom = function() {
- return AbstractUiMessage.duplicateDom(this);
- };
- UiMeMessage.prototype.updateDom = function() {
- AbstractUiMessage.updateDom(this);
- return this;
- };
- UiMeMessage.prototype.update = function(ev, ts) {
- MeMessage.prototype.update.call(this, ev, ts);
- this.invalidate();
- };
- /**
- * @constructor
- * @implements {IUiMessage}
- * @extends {Message}
- * @param {*} ev
- * @param {number} ts
- **/
- function UiMessage(channelId, ev, ts) {
- // Extends AbstractUiMessage and Message
- Message.call(this, ev, ts);
- /** @const @type {ChatContext} */
- this.context = DATA.context.getChannelContext(channelId).getChatContext();
- /** @type {string} @const */
- this.channelId = channelId;
- /** @type {Element} */
- this.dom = AbstractUiMessage.dom;
- /** @type {boolean} */
- this.uiNeedRefresh = AbstractUiMessage.uiNeedRefresh;
- }
- UiMessage.prototype = Object.create(Message.prototype);
- UiMessage.prototype.constructor = UiMessage;
- UiMessage.prototype.invalidate = function() {
- return AbstractUiMessage.invalidate(this);
- };
- UiMessage.prototype.formatText = function(text) {
- return AbstractUiMessage.formatText(this, text);
- };
- UiMessage.prototype.removeDom = function() {
- return AbstractUiMessage.removeDom(this);
- };
- UiMessage.prototype.getDom = function() {
- return AbstractUiMessage.getDom(this);
- };
- UiMessage.prototype.createDom = function() {
- this.dom = doCreateMessageDom(this, false);
- return this;
- };
- UiMessage.prototype.duplicateDom = function() {
- return AbstractUiMessage.duplicateDom(this);
- };
- UiMessage.prototype.updateDom = function() {
- AbstractUiMessage.updateDom(this);
- return this;
- };
- UiMessage.prototype.update = function(ev, ts) {
- Message.prototype.update.call(this, ev, ts);
- this.invalidate();
- var match = this.text.match(/^<?https:\/\/www\.openstreetmap\.org\/\?mlat=(-?[0-9\.]+)(&|&)mlon=(-?[0-9\.]+)(&|&)macc=([0-9\.]+)[^\s]*/);
- if (match) {
- var lat = match[1],
- lon = match[3],
- acc = match[5];
- this.text = this.text.substr(0, match.index) +this.text.substr(match.index +match[0].length).trim();
- this.attachments.unshift({
- "color": "#008000",
- "text": match[0],
- "footer": "Open Street Map",
- "footer_icon": "https://www.openstreetmap.org/assets/favicon-32x32-36d06d8a01933075bc7093c9631cffd02d49b03b659f767340f256bb6839d990.png",
- "geo": {
- "latitude": match[1],
- "longitude": match[3],
- "accuracy": match[5]
- }
- });
- }
- };
- /**
- * @constructor
- * @implements {IUiMessage}
- * @extends {NoticeMessage}
- * @param {*} ev
- * @param {number} ts
- **/
- function UiNoticeMessage(channelId, ev, ts) {
- // Extends AbstractUiMessage and NoticeMessage
- NoticeMessage.call(this, ev, ts);
- /** @const @type {ChatContext} */
- this.context = DATA.context.getChannelContext(channelId).getChatContext();
- /** @type {string} @const */
- this.channelId = channelId;
- /** @type {Element} */
- this.dom; // jshint ignore:line
- /** @type {Element} */
- this.domWrapper = null;
- /** @type {boolean} */
- this.uiNeedRefresh = true;
- }
- UiNoticeMessage.prototype = Object.create(NoticeMessage.prototype);
- UiNoticeMessage.prototype.constructor = UiNoticeMessage;
- UiNoticeMessage.prototype.invalidate = function() {
- return AbstractUiMessage.invalidate(this);
- };
- UiNoticeMessage.prototype.formatText = function(text) {
- return AbstractUiMessage.formatText(this, text);
- };
- UiNoticeMessage.prototype.removeDom = function() {
- if (this.domWrapper && this.domWrapper.parentElement) {
- this.domWrapper.remove();
- delete(this.domWrapper);
- }
- if (this.dom)
- delete(this.dom);
- return this;
- };
- UiNoticeMessage.prototype.getDom = function() {
- AbstractUiMessage.getDom(this);
- return this.domWrapper;
- };
- UiNoticeMessage.prototype.duplicateDom = function() {
- return this.domWrapper.cloneNode(true);
- };
- UiNoticeMessage.prototype.createDom = function() {
- this.dom = doCreateMessageDom(this, false);
- this.domWrapper = document.createElement("span");
- this.dom.classList.add(R.klass.msg.notice);
- this.domWrapper.className = R.klass.msg.notice;
- this.domWrapper.textContent = locale.onlyVisible;
- this.domWrapper.appendChild(this.dom);
- return this;
- };
- UiNoticeMessage.prototype.updateDom = function() {
- AbstractUiMessage.updateDom(this);
- return this;
- };
- UiNoticeMessage.prototype.update = function(ev, ts) {
- NoticeMessage.prototype.update.call(this, ev, ts);
- this.invalidate();
- };
|