JSDoc: Source: jsxc.lib.xmpp.mam.js

# Source: jsxc.lib.xmpp.mam.js

    /**
     * Implements XEP-0313: Message Archive Management.
     *
     * @namespace jsxc.xmpp.mam
     * @see {@link https://xmpp.org/extensions/xep-0313.html}
     */
    jsxc.xmpp.mam = {
       conn: null
    };

    jsxc.xmpp.mam.init = function() {
       var self = jsxc.xmpp.mam;

       self.conn = jsxc.xmpp.conn;
    };

    jsxc.xmpp.mam.isEnabled = function() {
       var mamOptions = jsxc.options.get('mam') || {};

       var features = jsxc.storage.getUserItem('features') || [];
       var hasFeatureMam1 = features.indexOf('urn:xmpp:mam:1') >= 0;
       var hasFeatureMam2 = features.indexOf('urn:xmpp:mam:2') >= 0;

       if (hasFeatureMam1 && !hasFeatureMam2) {
          Strophe.addNamespace('MAM', 'urn:xmpp:mam:1');
       }

       return (hasFeatureMam1 || hasFeatureMam2) && mamOptions.enable;
    };

    jsxc.xmpp.mam.nextMessages = function(bid) {
       var self = jsxc.xmpp.mam;
       var buddyData = jsxc.storage.getUserItem('buddy', bid) || {};
       var lastArchiveUid = buddyData.lastArchiveUid;
       var queryId = self.conn.getUniqueId();
       var mamOptions = jsxc.options.get('mam') || {};
       var history = jsxc.storage.getUserItem('history', bid) || [];

       if (buddyData.archiveExhausted) {
          jsxc.debug('No more archived messages.');
          return;
       }

       var queryOptions = {
          queryid: queryId,
          before: lastArchiveUid || '',
          with: bid,
          onMessage: function() {
             var args = Array.from(arguments);
             args.unshift(bid);
             self.onMessage.apply(this, args);
             return true;
          },
          onComplete: function() {
             var args = Array.from(arguments);
             args.unshift(bid);
             self.onComplete.apply(this, args);
             return true;
          }
       };

       var oldestMessageId = history[history.length - 1];

       if (oldestMessageId && !lastArchiveUid) {
          var oldestMessage = new jsxc.Message(oldestMessageId);
          queryOptions.end = (new Date(oldestMessage.stamp)).toISOString();
       }

       if (mamOptions.max) {
          queryOptions.max = mamOptions.max;
       }

       self.conn.mam.query(undefined, queryOptions);
    };

    jsxc.xmpp.mam.onMessage = function(bid, stanza) {
       stanza = $(stanza);
       var result = stanza.find('result[xmlns="' + Strophe.NS.MAM + '"]');
       var queryId = result.attr('queryid');

       if (result.length !== 1) {
          return;
       }

       var forwarded = result.find('forwarded[xmlns="' + jsxc.CONST.NS.FORWARD + '"]');
       var message = forwarded.find('message');
       var messageId = $(message).attr('id');

       if (message.length !== 1) {
          return;
       }

       var from = message.attr('from');
       var to = message.attr('to');

       if (jsxc.jidToBid(from) !== bid && jsxc.jidToBid(to) !== bid) {
          return;
       }

       var delay = forwarded.find('delay[xmlns="urn:xmpp:delay"]');
       var stamp = (delay.length > 0) ? new Date(delay.attr('stamp')) : new Date();
       stamp = stamp.getTime();

       var body = $(message).find('body:first').text();

       if (!body || body.match(/\?OTR/i)) {
          return true;
       }

       var direction = (jsxc.jidToBid(to) === bid) ? jsxc.Message.OUT : jsxc.Message.IN;

       var win = jsxc.gui.window.get(bid);
       var textarea = win.find('.jsxc_textarea');
       if (textarea.find('[id="' + messageId + '"]').length === 0) {
          var pseudoChatElement = $('<div>');
          pseudoChatElement.attr('id', messageId.replace(/:/g, '-'));
          pseudoChatElement.attr('data-queryId', queryId);

          var lastMessage = textarea.find('[data-queryId="' + queryId + '"]').last();
          var history = jsxc.storage.getUserItem('history', bid) || [];

          if (history.indexOf(messageId) < 0) {
             if (lastMessage.length === 0) {
                textarea.prepend(pseudoChatElement);
                history.push(messageId);
             } else {
                lastMessage.after(pseudoChatElement);
                history.splice(history.indexOf(lastMessage.attr('id').replace(/-/g, ':')), 0, messageId);
             }
          }

          jsxc.storage.setUserItem('history', bid, history);
       }

       jsxc.gui.window.postMessage({
          _uid: messageId,
          bid: bid,
          direction: direction,
          msg: body,
          encrypted: false,
          forwarded: true,
          stamp: stamp
       });
    };

    jsxc.xmpp.mam.onComplete = function(bid, stanza) {
       stanza = $(stanza);
       var fin = stanza.find('fin[xmlns="' + Strophe.NS.MAM + '"]');
       var buddyData = jsxc.storage.getUserItem('buddy', bid) || {};
       var win = jsxc.gui.window.get(bid);

       buddyData.archiveExhausted = fin.attr('complete') === 'true';
       buddyData.lastArchiveUid = fin.find('first').text();

       if (buddyData.archiveExhausted) {
          win.find('.jsxc_fade').removeClass('jsxc_mam-enable');
       }

       jsxc.storage.setUserItem('buddy', bid, buddyData);
    };

    jsxc.xmpp.mam.initWindow = function(ev, win) {
       var self = jsxc.xmpp.mam;

       if (!jsxc.xmpp.conn && jsxc.master) {
          $(document).one('attached.jsxc', function() {
             self.initWindow(null, win);
          });
          return;
       }

       if (!jsxc.master) {
          return;
       }

       $(document).on('features.jsxc', function() {
          jsxc.xmpp.mam.addLoadButton(win);
       });

       var features = jsxc.storage.getUserItem('features');
       if (features !== null) {
          // features.jsxc was already fired
          jsxc.xmpp.mam.addLoadButton(win);
       }
    };

    jsxc.xmpp.mam.addLoadButton = function(win) {
       if (!jsxc.xmpp.mam.isEnabled()) {
          return;
       }

       var classNameShow = 'jsxc_show';
       var classNameMamEnable = 'jsxc_mam-enable';
       var bid = win.attr('data-bid');

       var element = $('<div>');
       element.addClass('jsxc_mam-load-more');
       element.appendTo(win.find('.slimScrollDiv'));
       element.click(function() {
          jsxc.xmpp.mam.nextMessages(bid);
       });
       element.text($.t('Load_older_messages'));

       win.find('.jsxc_textarea').scroll(function() {
          var buddyData = jsxc.storage.getUserItem('buddy', bid) || {};

          if (this.scrollTop < 42 && !buddyData.archiveExhausted) {
             element.addClass(classNameShow);
          } else {
             element.removeClass(classNameShow);
          }

          if (!buddyData.archiveExhausted) {
             win.find('.jsxc_fade').addClass(classNameMamEnable);
          }
       });

       win.find('.jsxc_textarea').scroll();
    };

    $(document).on('attached.jsxc', jsxc.xmpp.mam.init);
    $(document).on('init.window.jsxc', jsxc.xmpp.mam.initWindow);