JSDoc: Source: jsxc.lib.fileTransfer.js

# Source: jsxc.lib.fileTransfer.js

    /**
     * @namespace jsxc.fileTransfer
     * @type {Object}
     */
    jsxc.fileTransfer = {};

    /**
     * Make bytes more human readable.
     *
     * @memberOf jsxc.fileTransfer
     * @param  {Integer} byte
     * @return {String}
     */
    jsxc.fileTransfer.formatByte = function(byte) {
       var s = ['', 'KB', 'MB', 'GB', 'TB'];
       var i;

       for (i = 1; i < s.length; i++) {
          if (byte < 1024) {
             break;
          }
          byte /= 1024;
       }

       return (Math.round(byte * 10) / 10) + s[i - 1];
    };

    /**
     * Start file transfer dialog.
     *
     * @memberOf jsxc.fileTransfer
     * @param  {String} jid
     */
    jsxc.fileTransfer.startGuiAction = function(jid) {
       var bid = jsxc.jidToBid(jid);
       var res = Strophe.getResourceFromJid(jid);

       if (!res && !jsxc.xmpp.httpUpload.ready) {
          if (jsxc.fileTransfer.isWebrtcCapable(bid)) {
             jsxc.fileTransfer.selectResource(bid, jsxc.fileTransfer.startGuiAction);
          } else {
             jsxc.gui.window.postMessage({
                bid: bid,
                direction: jsxc.Message.SYS,
                msg: $.t('No_proper_file_transfer_method_available')
             });
          }

          return;
       }

       jsxc.fileTransfer.showFileSelection(jid);
    };

    /**
     * Show select dialog for file transfer capable resources.
     *
     * @memberOf jsxc.fileTransfer
     * @param  {String} bid
     * @param  {Function} success_cb Called if user selects resource
     * @param  {Function} error_cb Called if no resource was found or selected
     */
    jsxc.fileTransfer.selectResource = function(bid, success_cb, error_cb) {
       var win = jsxc.gui.window.get(bid);
       var jid = win.data('jid');
       var res = Strophe.getResourceFromJid(jid);

       var fileCapableRes = jsxc.webrtc.getCapableRes(jid, jsxc.webrtc.reqFileFeatures);
       var resources = Object.keys(jsxc.storage.getUserItem('res', bid)) || [];

       if (res === null && resources.length === 1 && fileCapableRes.length === 1) {
          // only one resource is available and this resource is also capable to receive files
          res = fileCapableRes[0];
          jid = bid + '/' + res;

          success_cb(jid);
       } else if (fileCapableRes.indexOf(res) >= 0) {
          // currently used resource is capable to receive files
          success_cb(bid + '/' + res);
       } else if (fileCapableRes.indexOf(res) < 0) {
          // show selection dialog
          jsxc.gui.window.selectResource(bid, $.t('Your_contact_uses_multiple_clients_'), function(data) {
             if (data.status === 'unavailable') {
                jsxc.gui.window.hideOverlay(bid);

                if (typeof error_cb === 'function') {
                   error_cb();
                }
             } else if (data.status === 'selected') {
                success_cb(bid + '/' + data.result);
             }
          }, fileCapableRes);
       }
    };

    /**
     * Show file selector.
     *
     * @memberOf jsxc.fileTransfer
     * @param  {String} jid
     */
    jsxc.fileTransfer.showFileSelection = function(jid) {
       var bid = jsxc.jidToBid(jid);
       var msg = $('<div><div><label><input type="file" name="files" /><label></div></div>');
       msg.addClass('jsxc_chatmessage');

       jsxc.gui.window.showOverlay(bid, msg, true);

       // open file selection for user
       msg.find('label').click();

       msg.find('[type="file"]').change(function(ev) {
          var file = ev.target.files[0]; // FileList object

          if (!file) {
             return;
          }

          jsxc.fileTransfer.fileSelected(jid, msg, file);
       });
    };

    jsxc.fileTransfer.showFileTooLarge = function(bid, file) {
       var maxSize = jsxc.fileTransfer.formatByte(jsxc.options.get('httpUpload').maxSize);
       var fileSize = jsxc.fileTransfer.formatByte(file.size);

       jsxc.gui.window.postMessage({
          bid: bid,
          direction: jsxc.Message.SYS,
          msg: $.t('File_too_large') + ' (' + fileSize + ' > ' + maxSize + ')'
       });

       jsxc.gui.window.hideOverlay(bid);
    };

    /**
     * Callback for file selector.
     *
     * @memberOf jsxc.fileTransfer
     * @param  {String} jid
     * @param  {jQuery} msg jQuery object of temporary file message
     * @param  {File} file selected file
     */
    jsxc.fileTransfer.fileSelected = function(jid, msg, file) {
       var bid = jsxc.jidToBid(jid);
       var httpUploadOptions = jsxc.options.get('httpUpload') || {};
       var maxSize = httpUploadOptions.maxSize || -1;

       if (file.transportMethod !== 'webrtc' && jsxc.xmpp.httpUpload.ready && maxSize >= 0 && file.size > maxSize) {
          jsxc.debug('File too large for http upload.');

          if (jsxc.fileTransfer.isWebrtcCapable(bid)) {
             // try data channels
             file.transportMethod = 'webrtc';

             jsxc.fileTransfer.selectResource(bid, function(jid) {
                jsxc.fileTransfer.fileSelected(jid, msg, file);
             }, function() {
                jsxc.fileTransfer.showFileTooLarge(bid, file);
             });
          } else {
             jsxc.fileTransfer.showFileTooLarge(bid, file);
          }

          return;
       } else if (!jsxc.xmpp.httpUpload.ready && Strophe.getResourceFromJid(jid)) {
          // http upload not available
          file.transportMethod = 'webrtc';
       }

       var attachment = $('<div>');
       attachment.addClass('jsxc_attachment');
       attachment.addClass('jsxc_' + file.type.replace(/\//, '-'));
       attachment.addClass('jsxc_' + file.type.replace(/^([^/]+)\/.*/, '$1'));

       msg.empty().append(attachment);

       if (FileReader && file.type.match(/^image\//)) {
          // show image preview
          var img = $('<img alt="preview">').attr('title', file.name);
          img.attr('src', jsxc.options.get('root') + '/img/loading.gif');
          img.appendTo(attachment);

          var reader = new FileReader();

          reader.onload = function() {
             img.attr('src', reader.result);
          };

          reader.readAsDataURL(file);
       } else {
          attachment.text(file.name + ' (' + file.size + ' byte)');
       }

       $('<button>').addClass('jsxc_btn jsxc_btn-primary').text($.t('Send')).click(function() {
          // user confirmed file transfer
          jsxc.gui.window.hideOverlay(bid);
          msg.remove();

          var message = jsxc.gui.window.postMessage({
             bid: bid,
             direction: jsxc.Message.OUT,
             attachment: {
                name: file.name,
                size: file.size,
                type: file.type,
                data: (file.type.match(/^image\//)) ? img.attr('src') : null
             }
          });

          if (file.transportMethod === 'webrtc') {
             var sess = jsxc.webrtc.sendFile(jid, file);

             sess.sender.on('progress', function(sent, size) {
                jsxc.gui.window.updateProgress(message, sent, size);

                if (sent === size) {
                   message.received();
                }
             });
          } else {
             // progress is updated in xmpp.httpUpload.uploadFile
             jsxc.xmpp.httpUpload.sendFile(file, message);
          }
       }).appendTo(msg);

       $('<button>').addClass('jsxc_btn jsxc_btn-default').text($.t('Abort')).click(function() {
          // user aborted file transfer
          jsxc.gui.window.hideOverlay(bid);
       }).appendTo(msg);
    };

    /**
     * Enable/disable icons for file transfer.
     *
     * @memberOf jsxc.fileTransfer
     * @param  {String} bid
     */
    jsxc.fileTransfer.updateIcons = function(bid) {
       var win = jsxc.gui.window.get(bid);

       if (!win || win.length === 0 || !jsxc.xmpp.conn) {
          return;
       }

       jsxc.debug('Update file transfer icons for ' + bid);

       if (jsxc.xmpp.httpUpload.ready) {
          win.find('.jsxc_sendFile').removeClass('jsxc_disabled');

          return;
       } else if (!jsxc.fileTransfer.isWebrtcCapable(bid)) {
          win.find('.jsxc_sendFile').addClass('jsxc_disabled');

          return;
       }

       var jid = win.data('jid');
       var res = Strophe.getResourceFromJid(jid);
       var fileCapableRes = jsxc.webrtc.getCapableRes(bid, jsxc.webrtc.reqFileFeatures);
       var resources = Object.keys(jsxc.storage.getUserItem('res', bid) || {}) || [];

       if (fileCapableRes.indexOf(res) > -1 || (res === null && fileCapableRes.length === 1 && resources.length === 1)) {
          win.find('.jsxc_sendFile').removeClass('jsxc_disabled');
       } else {
          win.find('.jsxc_sendFile').addClass('jsxc_disabled');
       }
    };

    jsxc.fileTransfer.isWebrtcCapable = function(bid) {
       return !jsxc.muc.isGroupchat(bid);
    };

    $(document).on('update.gui.jsxc', function(ev, bid) {
       jsxc.fileTransfer.updateIcons(bid);
    });