uiMessage.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /**
  2. * @constructor
  3. * @extends {RoomHistory}
  4. * @param {Room|string} room or roomId
  5. * @param {number} keepMessages number of messages to keep in memory
  6. * @param {Array|undefined} evts
  7. * @param {number|undefined} now
  8. **/
  9. function UiRoomHistory(room, keepMessages, evts, now) {
  10. RoomHistory.call(this, room, keepMessages, evts, now);
  11. }
  12. UiRoomHistory.prototype = Object.create(RoomHistory.prototype);
  13. UiRoomHistory.prototype.constructor = UiRoomHistory;
  14. UiRoomHistory.prototype.messageFactory = function(ev, ts) {
  15. if (ev["isMeMessage"] === true)
  16. return new UiMeMessage(this.id, ev, ts);
  17. if (ev["isNotice"] === true)
  18. return new UiNoticeMessage(this.id, ev, ts);
  19. return new UiMessage(this.id, ev, ts);
  20. }
  21. /** @interface */
  22. function IUiMessage() {};
  23. /**
  24. * @return {Element}
  25. **/
  26. IUiMessage.prototype.getDom = function() {};
  27. /**
  28. * @return {IUiMessage}
  29. **/
  30. IUiMessage.prototype.removeDom = function() {};
  31. /**
  32. * @return {IUiMessage}
  33. **/
  34. IUiMessage.prototype.invalidate = function() {};
  35. /**
  36. * @return {IUiMessage}
  37. **/
  38. IUiMessage.prototype.createDom = function() {};
  39. /**
  40. * @return {IUiMessage}
  41. **/
  42. IUiMessage.prototype.updateDom = function() {};
  43. /**
  44. * @return {Element}
  45. **/
  46. IUiMessage.prototype.duplicateDom = function() {};
  47. /** @const */
  48. var AbstractUiMessage = (function() {
  49. var updateReactions = function(_this, channelId) {
  50. var reactionFrag = document.createDocumentFragment();
  51. if (_this.reactions) {
  52. for (var reaction in _this.reactions) {
  53. var reac = createReactionDom(channelId, _this.id, reaction, _this.reactions[reaction]);
  54. if (reac)
  55. reactionFrag.appendChild(reac);
  56. }
  57. }
  58. _this.dom.reactions.textContent = '';
  59. _this.dom.reactions.appendChild(reactionFrag);
  60. },
  61. updateAttachments = function(_this, channelId) {
  62. var attachmentFrag = document.createDocumentFragment();
  63. for (var i =0, nbAttachments = _this.attachments.length; i < nbAttachments; i++) {
  64. var attachment = _this.attachments[i];
  65. if (attachment) {
  66. var domAttachment = createAttachmentDom(channelId, _this, attachment, i);
  67. if (domAttachment)
  68. attachmentFrag.appendChild(domAttachment);
  69. }
  70. }
  71. _this.dom.attachments.textContent = '';
  72. _this.dom.attachments.appendChild(attachmentFrag);
  73. },
  74. updateCommon = function(_this, sender) {
  75. _this.dom.ts.innerHTML = locale.formatDate(_this.ts);
  76. _this.dom.textDom.innerHTML = formatText(_this.text);
  77. _this.dom.authorName.textContent = sender ? sender.name : (_this.username || "?");
  78. };
  79. return {
  80. /** @type {Element|null} *
  81. dom: null,
  82. /** @type {boolean} *
  83. uiNeedRefresh: true,
  84. */
  85. /** @param {IUiMessage} _this */
  86. invalidate: function(_this) {
  87. _this.uiNeedRefresh = true;
  88. return _this;
  89. },
  90. /** @param {UiMessage|UiMeMessage|UiNoticeMessage} _this */
  91. removeDom: function(_this) {
  92. if (_this.dom && _this.dom.parentElement) {
  93. _this.dom.remove();
  94. delete(_this.dom);
  95. }
  96. return _this;
  97. },
  98. /** @param {UiMessage|UiMeMessage|UiNoticeMessage} _this */
  99. getDom: function(_this) {
  100. if (!_this.dom) {
  101. _this.createDom().updateDom();
  102. } else if (_this.uiNeedRefresh) {
  103. _this.uiNeedRefresh = false;
  104. _this.updateDom();
  105. }
  106. return _this.dom;
  107. },
  108. /** @param {UiMessage|UiMeMessage|UiNoticeMessage} _this */
  109. updateDom: function(_this) {
  110. var sender = SLACK.context.users[_this.userId];
  111. updateCommon(_this, sender);
  112. updateAttachments(_this, _this.channelId);
  113. updateReactions(_this, _this.channelId);
  114. if (_this.edited)
  115. _this.dom.classList.add(R.klass.msg.editedStatus);
  116. return _this;
  117. },
  118. duplicateDom: function(_this) {
  119. return _this.dom.cloneNode(true);
  120. }
  121. };
  122. })();
  123. /**
  124. * @constructor
  125. * @implements {IUiMessage}
  126. * @extends {MeMessage}
  127. * @param {*} ev
  128. * @param {number} ts
  129. **/
  130. function UiMeMessage(channelId, ev, ts) {
  131. // Extends AbstractUiMessage and MeMessage
  132. MeMessage.call(this, ev, ts);
  133. /** @type {string} @const */
  134. this.channelId = channelId;
  135. this.dom = AbstractUiMessage.dom;
  136. this.uiNeedRefresh = AbstractUiMessage.uiNeedRefresh;
  137. }
  138. UiMeMessage.prototype = Object.create(MeMessage.prototype);
  139. UiMeMessage.prototype.constructor = UiMeMessage;
  140. UiMeMessage.prototype.invalidate = function() {
  141. return AbstractUiMessage.invalidate(this);
  142. };
  143. UiMeMessage.prototype.removeDom = function() {
  144. return AbstractUiMessage.removeDom(this);
  145. };
  146. UiMeMessage.prototype.getDom = function() {
  147. return AbstractUiMessage.getDom(this);
  148. };
  149. UiMeMessage.prototype.createDom = function() {
  150. this.dom = doCreateMessageDom(this, false);
  151. this.dom.classList.add(R.klass.msg.meMessage);
  152. return this;
  153. };
  154. UiMeMessage.prototype.duplicateDom = function() {
  155. return AbstractUiMessage.duplicateDom(this);
  156. };
  157. UiMeMessage.prototype.updateDom = function() {
  158. AbstractUiMessage.updateDom(this);
  159. return this;
  160. };
  161. UiMeMessage.prototype.update = function(ev, ts) {
  162. MeMessage.prototype.update.call(this, ev, ts);
  163. this.invalidate();
  164. };
  165. /**
  166. * @constructor
  167. * @implements {IUiMessage}
  168. * @extends {Message}
  169. * @param {*} ev
  170. * @param {number} ts
  171. **/
  172. function UiMessage(channelId, ev, ts) {
  173. // Extends AbstractUiMessage and Message
  174. Message.call(this, ev, ts);
  175. /** @type {string} @const */
  176. this.channelId = channelId;
  177. /** @type {Element} */
  178. this.dom = AbstractUiMessage.dom;
  179. /** @type {boolean} */
  180. this.uiNeedRefresh = AbstractUiMessage.uiNeedRefresh;
  181. }
  182. UiMessage.prototype = Object.create(Message.prototype);
  183. UiMessage.prototype.constructor = UiMessage;
  184. UiMessage.prototype.invalidate = function() {
  185. return AbstractUiMessage.invalidate(this);
  186. };
  187. UiMessage.prototype.removeDom = function() {
  188. return AbstractUiMessage.removeDom(this);
  189. };
  190. UiMessage.prototype.getDom = function() {
  191. return AbstractUiMessage.getDom(this);
  192. };
  193. UiMessage.prototype.createDom = function() {
  194. this.dom = doCreateMessageDom(this, false);
  195. return this;
  196. };
  197. UiMessage.prototype.duplicateDom = function() {
  198. return AbstractUiMessage.duplicateDom(this);
  199. };
  200. UiMessage.prototype.updateDom = function() {
  201. AbstractUiMessage.updateDom(this);
  202. return this;
  203. };
  204. UiMessage.prototype.update = function(ev, ts) {
  205. Message.prototype.update.call(this, ev, ts);
  206. this.invalidate();
  207. };
  208. /**
  209. * @constructor
  210. * @implements {IUiMessage}
  211. * @extends {NoticeMessage}
  212. * @param {*} ev
  213. * @param {number} ts
  214. **/
  215. function UiNoticeMessage(channelId, ev, ts) {
  216. // Extends AbstractUiMessage and NoticeMessage
  217. NoticeMessage.call(this, ev, ts);
  218. /** @type {string} @const */
  219. this.channelId = channelId;
  220. this.dom = AbstractUiMessage.dom;
  221. /** @type {Element} */
  222. this.domWrapper = null;
  223. this.uiNeedRefresh = AbstractUiMessage.uiNeedRefresh;
  224. }
  225. UiNoticeMessage.prototype = Object.create(NoticeMessage.prototype);
  226. UiNoticeMessage.prototype.constructor = UiNoticeMessage;
  227. UiNoticeMessage.prototype.invalidate = function() {
  228. return AbstractUiMessage.invalidate(this);
  229. };
  230. UiNoticeMessage.prototype.removeDom = function() {
  231. if (this.domWrapper && this.domWrapper.parentElement) {
  232. this.domWrapper.remove();
  233. delete(this.domWrapper);
  234. }
  235. if (this.dom)
  236. delete(this.dom);
  237. return this;
  238. };
  239. UiNoticeMessage.prototype.getDom = function() {
  240. AbstractUiMessage.getDom(this);
  241. return this.domWrapper;
  242. };
  243. UiNoticeMessage.prototype.duplicateDom = function() {
  244. return this.domWrapper.cloneNode(true);
  245. };
  246. UiNoticeMessage.prototype.createDom = function() {
  247. this.dom = doCreateMessageDom(this, false);
  248. this.domWrapper = document.createElement("span");
  249. this.dom.classList.add(R.klass.msg.notice);
  250. this.domWrapper.className = R.klass.msg.notice;
  251. this.domWrapper.textContent = locale.onlyVisible;
  252. return this;
  253. };
  254. UiNoticeMessage.prototype.updateDom = function() {
  255. AbstractUiMessage.updateDom(this);
  256. return this;
  257. };
  258. UiNoticeMessage.prototype.update = function(ev, ts) {
  259. NoticeMessage.prototype.update.call(this, ev, ts);
  260. this.invalidate();
  261. };