From 31080bf2f95735012323e4bdf1f7dccd05ea50e6 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Mon, 24 Sep 2018 16:03:53 +0200 Subject: [PATCH] Add a FormData polyfill for Edge comptaibility Fixes #1220 --- CHANGES.md | 3 +- dist/converse.js | 423 ++++++++++++++++++++++++++++++++++++- package-lock.json | 6 + package.json | 3 +- src/converse-controlbox.js | 2 + src/converse-muc-views.js | 2 + src/converse-profile.js | 2 + src/converse-rosterview.js | 2 + webpack.config.js | 1 + 9 files changed, 431 insertions(+), 13 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 79b0f20f1..c6e01745c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,9 @@ # Changelog -## 4.0.2 (2018-??-??) +## 4.0.2 (Unreleased) - M4A and WEBM files when sent as XEP-0066 Out of Band Data, are now playable directly in chat +- #1220 Converse not working in Edge ## 4.0.1 (2018-09-19) diff --git a/dist/converse.js b/dist/converse.js index 3d1c40f0e..ead9aa1a9 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -7685,6 +7685,407 @@ return Promise$2; /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js"))) +/***/ }), + +/***/ "./node_modules/formdata-polyfill/FormData.js": +/*!****************************************************!*\ + !*** ./node_modules/formdata-polyfill/FormData.js ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +if (typeof FormData === 'undefined' || !FormData.prototype.keys) { + const global = typeof window === 'object' + ? window : typeof self === 'object' + ? self : this + + // keep a reference to native implementation + const _FormData = global.FormData + + // To be monkey patched + const _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send + const _fetch = global.Request && global.fetch + + // Unable to patch Request constructor correctly + // const _Request = global.Request + // only way is to use ES6 class extend + // https://github.com/babel/babel/issues/1966 + + const stringTag = global.Symbol && Symbol.toStringTag + const map = new WeakMap + const wm = o => map.get(o) + const arrayFrom = Array.from || (obj => [].slice.call(obj)) + + // Add missing stringTags to blob and files + if (stringTag) { + if (!Blob.prototype[stringTag]) { + Blob.prototype[stringTag] = 'Blob' + } + + if ('File' in global && !File.prototype[stringTag]) { + File.prototype[stringTag] = 'File' + } + } + + // Fix so you can construct your own File + try { + new File([], '') + } catch (a) { + global.File = function(b, d, c) { + const blob = new Blob(b, c) + const t = c && void 0 !== c.lastModified ? new Date(c.lastModified) : new Date + + Object.defineProperties(blob, { + name: { + value: d + }, + lastModifiedDate: { + value: t + }, + lastModified: { + value: +t + }, + toString: { + value() { + return '[object File]' + } + } + }) + + if (stringTag) { + Object.defineProperty(blob, stringTag, { + value: 'File' + }) + } + + return blob + } + } + + function normalizeValue([value, filename]) { + if (value instanceof Blob) + // Should always returns a new File instance + // console.assert(fd.get(x) !== fd.get(x)) + value = new File([value], filename, { + type: value.type, + lastModified: value.lastModified + }) + + return value + } + + function stringify(name) { + if (!arguments.length) + throw new TypeError('1 argument required, but only 0 present.') + + return [name + ''] + } + + function normalizeArgs(name, value, filename) { + if (arguments.length < 2) + throw new TypeError( + `2 arguments required, but only ${arguments.length} present.` + ) + + return value instanceof Blob + // normalize name and filename if adding an attachment + ? [name + '', value, filename !== undefined + ? filename + '' // Cast filename to string if 3th arg isn't undefined + : typeof value.name === 'string' // if name prop exist + ? value.name // Use File.name + : 'blob'] // otherwise fallback to Blob + + // If no attachment, just cast the args to strings + : [name + '', value + ''] + } + + /** + * @implements {Iterable} + */ + class FormDataPolyfill { + + /** + * FormData class + * + * @param {HTMLElement=} form + */ + constructor(form) { + map.set(this, Object.create(null)) + + if (!form) + return this + + for (let elm of arrayFrom(form.elements)) { + if (!elm.name || elm.disabled) continue + + if (elm.type === 'file') + for (let file of arrayFrom(elm.files || [])) + this.append(elm.name, file) + else if (elm.type === 'select-multiple' || elm.type === 'select-one') + for (let opt of arrayFrom(elm.options)) + !opt.disabled && opt.selected && this.append(elm.name, opt.value) + else if (elm.type === 'checkbox' || elm.type === 'radio') { + if (elm.checked) this.append(elm.name, elm.value) + } else + this.append(elm.name, elm.value) + } + } + + + /** + * Append a field + * + * @param {String} name field name + * @param {String|Blob|File} value string / blob / file + * @param {String=} filename filename to use with blob + * @return {Undefined} + */ + append(name, value, filename) { + const map = wm(this) + + if (!map[name]) + map[name] = [] + + map[name].push([value, filename]) + } + + + /** + * Delete all fields values given name + * + * @param {String} name Field name + * @return {Undefined} + */ + delete(name) { + delete wm(this)[name] + } + + + /** + * Iterate over all fields as [name, value] + * + * @return {Iterator} + */ + *entries() { + const map = wm(this) + + for (let name in map) + for (let value of map[name]) + yield [name, normalizeValue(value)] + } + + /** + * Iterate over all fields + * + * @param {Function} callback Executed for each item with parameters (value, name, thisArg) + * @param {Object=} thisArg `this` context for callback function + * @return {Undefined} + */ + forEach(callback, thisArg) { + for (let [name, value] of this) + callback.call(thisArg, value, name, this) + } + + + /** + * Return first field value given name + * or null if non existen + * + * @param {String} name Field name + * @return {String|File|null} value Fields value + */ + get(name) { + const map = wm(this) + return map[name] ? normalizeValue(map[name][0]) : null + } + + + /** + * Return all fields values given name + * + * @param {String} name Fields name + * @return {Array} [{String|File}] + */ + getAll(name) { + return (wm(this)[name] || []).map(normalizeValue) + } + + + /** + * Check for field name existence + * + * @param {String} name Field name + * @return {boolean} + */ + has(name) { + return name in wm(this) + } + + + /** + * Iterate over all fields name + * + * @return {Iterator} + */ + *keys() { + for (let [name] of this) + yield name + } + + + /** + * Overwrite all values given name + * + * @param {String} name Filed name + * @param {String} value Field value + * @param {String=} filename Filename (optional) + * @return {Undefined} + */ + set(name, value, filename) { + wm(this)[name] = [[value, filename]] + } + + + /** + * Iterate over all fields + * + * @return {Iterator} + */ + *values() { + for (let [name, value] of this) + yield value + } + + + /** + * Return a native (perhaps degraded) FormData with only a `append` method + * Can throw if it's not supported + * + * @return {FormData} + */ + ['_asNative']() { + const fd = new _FormData + + for (let [name, value] of this) + fd.append(name, value) + + return fd + } + + + /** + * [_blob description] + * + * @return {Blob} [description] + */ + ['_blob']() { + const boundary = '----formdata-polyfill-' + Math.random() + const chunks = [] + + for (let [name, value] of this) { + chunks.push(`--${boundary}\r\n`) + + if (value instanceof Blob) { + chunks.push( + `Content-Disposition: form-data; name="${name}"; filename="${value.name}"\r\n`, + `Content-Type: ${value.type || 'application/octet-stream'}\r\n\r\n`, + value, + '\r\n' + ) + } else { + chunks.push( + `Content-Disposition: form-data; name="${name}"\r\n\r\n${value}\r\n` + ) + } + } + + chunks.push(`--${boundary}--`) + + return new Blob(chunks, {type: 'multipart/form-data; boundary=' + boundary}) + } + + + /** + * The class itself is iterable + * alias for formdata.entries() + * + * @return {Iterator} + */ + [Symbol.iterator]() { + return this.entries() + } + + + /** + * Create the default string description. + * + * @return {String} [object FormData] + */ + toString() { + return '[object FormData]' + } + } + + + if (stringTag) { + /** + * Create the default string description. + * It is accessed internally by the Object.prototype.toString(). + * + * @return {String} FormData + */ + FormDataPolyfill.prototype[stringTag] = 'FormData' + } + + const decorations = [ + ['append', normalizeArgs], + ['delete', stringify], + ['get', stringify], + ['getAll', stringify], + ['has', stringify], + ['set', normalizeArgs] + ] + + decorations.forEach(arr => { + const orig = FormDataPolyfill.prototype[arr[0]] + FormDataPolyfill.prototype[arr[0]] = function() { + return orig.apply(this, arr[1].apply(this, arrayFrom(arguments))) + } + }) + + // Patch xhr's send method to call _blob transparently + if (_send) { + XMLHttpRequest.prototype.send = function(data) { + // I would check if Content-Type isn't already set + // But xhr lacks getRequestHeaders functionallity + // https://github.com/jimmywarting/FormData/issues/44 + if (data instanceof FormDataPolyfill) { + const blob = data['_blob']() + this.setRequestHeader('Content-Type', blob.type) + _send.call(this, blob) + } else { + _send.call(this, data) + } + } + } + + // Patch fetch's function to call _blob transparently + if (_fetch) { + const _fetch = global.fetch + + global.fetch = function(input, init) { + if (init && init.body && init.body instanceof FormDataPolyfill) { + init.body = init.body['_blob']() + } + + return _fetch(input, init) + } + } + + global['FormData'] = FormDataPolyfill +} + + /***/ }), /***/ "./node_modules/jed/jed.js": @@ -62203,11 +62604,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /*global define */ (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! lodash.fp */ "./src/lodash.fp.js"), __webpack_require__(/*! templates/converse_brand_heading.html */ "./src/templates/converse_brand_heading.html"), __webpack_require__(/*! templates/controlbox.html */ "./src/templates/controlbox.html"), __webpack_require__(/*! templates/controlbox_toggle.html */ "./src/templates/controlbox_toggle.html"), __webpack_require__(/*! templates/login_panel.html */ "./src/templates/login_panel.html"), __webpack_require__(/*! converse-chatview */ "./src/converse-chatview.js"), __webpack_require__(/*! converse-rosterview */ "./src/converse-rosterview.js"), __webpack_require__(/*! converse-profile */ "./src/converse-profile.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! formdata-polyfill */ "./node_modules/formdata-polyfill/FormData.js"), __webpack_require__(/*! lodash.fp */ "./src/lodash.fp.js"), __webpack_require__(/*! templates/converse_brand_heading.html */ "./src/templates/converse_brand_heading.html"), __webpack_require__(/*! templates/controlbox.html */ "./src/templates/controlbox.html"), __webpack_require__(/*! templates/controlbox_toggle.html */ "./src/templates/controlbox_toggle.html"), __webpack_require__(/*! templates/login_panel.html */ "./src/templates/login_panel.html"), __webpack_require__(/*! converse-chatview */ "./src/converse-chatview.js"), __webpack_require__(/*! converse-rosterview */ "./src/converse-rosterview.js"), __webpack_require__(/*! converse-profile */ "./src/converse-profile.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, bootstrap, fp, tpl_brand_heading, tpl_controlbox, tpl_controlbox_toggle, tpl_login_panel) { +})(void 0, function (converse, bootstrap, _FormData, fp, tpl_brand_heading, tpl_controlbox, tpl_controlbox_toggle, tpl_login_panel) { "use strict"; const CHATBOX_TYPE = 'chatbox'; @@ -67879,11 +68280,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ // Copyright (c) 2013-2018, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! utils/muc */ "./src/utils/muc.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! templates/add_chatroom_modal.html */ "./src/templates/add_chatroom_modal.html"), __webpack_require__(/*! templates/chatarea.html */ "./src/templates/chatarea.html"), __webpack_require__(/*! templates/chatroom.html */ "./src/templates/chatroom.html"), __webpack_require__(/*! templates/chatroom_details_modal.html */ "./src/templates/chatroom_details_modal.html"), __webpack_require__(/*! templates/chatroom_disconnect.html */ "./src/templates/chatroom_disconnect.html"), __webpack_require__(/*! templates/chatroom_features.html */ "./src/templates/chatroom_features.html"), __webpack_require__(/*! templates/chatroom_form.html */ "./src/templates/chatroom_form.html"), __webpack_require__(/*! templates/chatroom_head.html */ "./src/templates/chatroom_head.html"), __webpack_require__(/*! templates/chatroom_invite.html */ "./src/templates/chatroom_invite.html"), __webpack_require__(/*! templates/chatroom_nickname_form.html */ "./src/templates/chatroom_nickname_form.html"), __webpack_require__(/*! templates/chatroom_password_form.html */ "./src/templates/chatroom_password_form.html"), __webpack_require__(/*! templates/chatroom_sidebar.html */ "./src/templates/chatroom_sidebar.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/list_chatrooms_modal.html */ "./src/templates/list_chatrooms_modal.html"), __webpack_require__(/*! templates/occupant.html */ "./src/templates/occupant.html"), __webpack_require__(/*! templates/room_description.html */ "./src/templates/room_description.html"), __webpack_require__(/*! templates/room_item.html */ "./src/templates/room_item.html"), __webpack_require__(/*! templates/room_panel.html */ "./src/templates/room_panel.html"), __webpack_require__(/*! templates/rooms_results.html */ "./src/templates/rooms_results.html"), __webpack_require__(/*! templates/spinner.html */ "./src/templates/spinner.html"), __webpack_require__(/*! awesomplete */ "./node_modules/awesomplete-avoid-xss/awesomplete.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! formdata-polyfill */ "./node_modules/formdata-polyfill/FormData.js"), __webpack_require__(/*! utils/muc */ "./src/utils/muc.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! templates/add_chatroom_modal.html */ "./src/templates/add_chatroom_modal.html"), __webpack_require__(/*! templates/chatarea.html */ "./src/templates/chatarea.html"), __webpack_require__(/*! templates/chatroom.html */ "./src/templates/chatroom.html"), __webpack_require__(/*! templates/chatroom_details_modal.html */ "./src/templates/chatroom_details_modal.html"), __webpack_require__(/*! templates/chatroom_disconnect.html */ "./src/templates/chatroom_disconnect.html"), __webpack_require__(/*! templates/chatroom_features.html */ "./src/templates/chatroom_features.html"), __webpack_require__(/*! templates/chatroom_form.html */ "./src/templates/chatroom_form.html"), __webpack_require__(/*! templates/chatroom_head.html */ "./src/templates/chatroom_head.html"), __webpack_require__(/*! templates/chatroom_invite.html */ "./src/templates/chatroom_invite.html"), __webpack_require__(/*! templates/chatroom_nickname_form.html */ "./src/templates/chatroom_nickname_form.html"), __webpack_require__(/*! templates/chatroom_password_form.html */ "./src/templates/chatroom_password_form.html"), __webpack_require__(/*! templates/chatroom_sidebar.html */ "./src/templates/chatroom_sidebar.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/list_chatrooms_modal.html */ "./src/templates/list_chatrooms_modal.html"), __webpack_require__(/*! templates/occupant.html */ "./src/templates/occupant.html"), __webpack_require__(/*! templates/room_description.html */ "./src/templates/room_description.html"), __webpack_require__(/*! templates/room_item.html */ "./src/templates/room_item.html"), __webpack_require__(/*! templates/room_panel.html */ "./src/templates/room_panel.html"), __webpack_require__(/*! templates/rooms_results.html */ "./src/templates/rooms_results.html"), __webpack_require__(/*! templates/spinner.html */ "./src/templates/spinner.html"), __webpack_require__(/*! awesomplete */ "./node_modules/awesomplete-avoid-xss/awesomplete.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, muc_utils, xss, tpl_add_chatroom_modal, tpl_chatarea, tpl_chatroom, tpl_chatroom_details_modal, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_info, tpl_list_chatrooms_modal, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) { +})(void 0, function (converse, _FormData, muc_utils, xss, tpl_add_chatroom_modal, tpl_chatarea, tpl_chatroom, tpl_chatroom_details_modal, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_info, tpl_list_chatrooms_modal, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) { "use strict"; const _converse$env = converse.env, @@ -73362,11 +73763,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /*global define */ (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! templates/alert.html */ "./src/templates/alert.html"), __webpack_require__(/*! templates/chat_status_modal.html */ "./src/templates/chat_status_modal.html"), __webpack_require__(/*! templates/profile_modal.html */ "./src/templates/profile_modal.html"), __webpack_require__(/*! templates/profile_view.html */ "./src/templates/profile_view.html"), __webpack_require__(/*! templates/status_option.html */ "./src/templates/status_option.html"), __webpack_require__(/*! converse-vcard */ "./src/converse-vcard.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! formdata-polyfill */ "./node_modules/formdata-polyfill/FormData.js"), __webpack_require__(/*! templates/alert.html */ "./src/templates/alert.html"), __webpack_require__(/*! templates/chat_status_modal.html */ "./src/templates/chat_status_modal.html"), __webpack_require__(/*! templates/profile_modal.html */ "./src/templates/profile_modal.html"), __webpack_require__(/*! templates/profile_view.html */ "./src/templates/profile_view.html"), __webpack_require__(/*! templates/status_option.html */ "./src/templates/status_option.html"), __webpack_require__(/*! converse-vcard */ "./src/converse-vcard.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, bootstrap, tpl_alert, tpl_chat_status_modal, tpl_profile_modal, tpl_profile_view, tpl_status_option) { +})(void 0, function (converse, bootstrap, _FormData, tpl_alert, tpl_chat_status_modal, tpl_profile_modal, tpl_profile_view, tpl_status_option) { "use strict"; const _converse$env = converse.env, @@ -75980,11 +76381,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ // Copyright (c) 2012-2018, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! templates/add_contact_modal.html */ "./src/templates/add_contact_modal.html"), __webpack_require__(/*! templates/group_header.html */ "./src/templates/group_header.html"), __webpack_require__(/*! templates/pending_contact.html */ "./src/templates/pending_contact.html"), __webpack_require__(/*! templates/requesting_contact.html */ "./src/templates/requesting_contact.html"), __webpack_require__(/*! templates/roster.html */ "./src/templates/roster.html"), __webpack_require__(/*! templates/roster_filter.html */ "./src/templates/roster_filter.html"), __webpack_require__(/*! templates/roster_item.html */ "./src/templates/roster_item.html"), __webpack_require__(/*! templates/search_contact.html */ "./src/templates/search_contact.html"), __webpack_require__(/*! awesomplete */ "./node_modules/awesomplete-avoid-xss/awesomplete.js"), __webpack_require__(/*! converse-chatboxes */ "./src/converse-chatboxes.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! formdata-polyfill */ "./node_modules/formdata-polyfill/FormData.js"), __webpack_require__(/*! templates/add_contact_modal.html */ "./src/templates/add_contact_modal.html"), __webpack_require__(/*! templates/group_header.html */ "./src/templates/group_header.html"), __webpack_require__(/*! templates/pending_contact.html */ "./src/templates/pending_contact.html"), __webpack_require__(/*! templates/requesting_contact.html */ "./src/templates/requesting_contact.html"), __webpack_require__(/*! templates/roster.html */ "./src/templates/roster.html"), __webpack_require__(/*! templates/roster_filter.html */ "./src/templates/roster_filter.html"), __webpack_require__(/*! templates/roster_item.html */ "./src/templates/roster_item.html"), __webpack_require__(/*! templates/search_contact.html */ "./src/templates/search_contact.html"), __webpack_require__(/*! awesomplete */ "./node_modules/awesomplete-avoid-xss/awesomplete.js"), __webpack_require__(/*! converse-chatboxes */ "./src/converse-chatboxes.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, tpl_add_contact_modal, tpl_group_header, tpl_pending_contact, tpl_requesting_contact, tpl_roster, tpl_roster_filter, tpl_roster_item, tpl_search_contact, Awesomplete) { +})(void 0, function (converse, _FormData, tpl_add_contact_modal, tpl_group_header, tpl_pending_contact, tpl_requesting_contact, tpl_roster, tpl_roster_filter, tpl_roster_item, tpl_search_contact, Awesomplete) { "use strict"; const _converse$env = converse.env, @@ -81311,7 +81712,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ filename = uri.filename(), lower_filename = filename.toLowerCase(); - if (!_.includes(["https", "http"], uri.protocol().toLowerCase()) || lower_filename.endsWith('mp3') || lower_filename.endsWith('mp4') || lower_filename.endsWith('jpg') || lower_filename.endsWith('jpeg') || lower_filename.endsWith('png') || lower_filename.endsWith('gif') || lower_filename.endsWith('svg')) { + if (!_.includes(["https", "http"], uri.protocol().toLowerCase()) || lower_filename.endsWith('mp3') || lower_filename.endsWith('mp4') || lower_filename.endsWith('jpg') || lower_filename.endsWith('jpeg') || lower_filename.endsWith('png') || lower_filename.endsWith('gif') || lower_filename.endsWith('m4a') || lower_filename.endsWith('webm') || lower_filename.endsWith('svg')) { return url; } @@ -81338,7 +81739,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ u.renderMovieURL = function (_converse, url) { const __ = _converse.__; - if (url.endsWith('mp4')) { + if (url.endsWith('mp4') || url.endsWith('webm')) { return tpl_video({ 'url': url, 'label_download': __('Download video file') @@ -81351,7 +81752,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ u.renderAudioURL = function (_converse, url) { const __ = _converse.__; - if (url.endsWith('mp3')) { + if (url.endsWith('mp3') || url.endsWith('m4a')) { return tpl_audio({ 'url': url, 'label_download': __('Download audio file') diff --git a/package-lock.json b/package-lock.json index 2f80438f3..9cdca2504 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4225,6 +4225,12 @@ "samsam": "1.3.0" } }, + "formdata-polyfill": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-3.0.12.tgz", + "integrity": "sha512-y5V1Y4e2VSJ29+CAHozJwN9BqvsigYicZp/MqeYP00X/UMah3cLb2ix7/58fLcaAjwr8HfztD7Ih/IQCW1BGfw==", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", diff --git a/package.json b/package.json index 17db13f29..701909f0a 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@babel/core": "^7.0.0-beta.48", "@babel/preset-env": "^7.0.0-beta.48", "@babel/preset-es2015": "^7.0.0-beta.49", + "@fortawesome/fontawesome-free": "5.3.1", "awesomplete-avoid-xss": "^1.1.2", "babel-loader": "^8.0.0-beta.3", "backbone": "1.3.3", @@ -53,7 +54,7 @@ "eslint-plugin-lodash": "^2.3.3", "exports-loader": "^0.7.0", "filesize": "^3.6.1", - "@fortawesome/fontawesome-free": "5.3.1", + "formdata-polyfill": "^3.0.12", "hellojs": "^1.16.1", "http-server": "^0.10.0", "imports-loader": "^0.8.0", diff --git a/src/converse-controlbox.js b/src/converse-controlbox.js index 46b84ccb8..e2d8ed406 100644 --- a/src/converse-controlbox.js +++ b/src/converse-controlbox.js @@ -9,6 +9,7 @@ (function (root, factory) { define(["converse-core", "bootstrap", + "formdata-polyfill", "lodash.fp", "templates/converse_brand_heading.html", "templates/controlbox.html", @@ -21,6 +22,7 @@ }(this, function ( converse, bootstrap, + _FormData, fp, tpl_brand_heading, tpl_controlbox, diff --git a/src/converse-muc-views.js b/src/converse-muc-views.js index 0bc50e87c..cc9006c83 100644 --- a/src/converse-muc-views.js +++ b/src/converse-muc-views.js @@ -7,6 +7,7 @@ (function (root, factory) { define([ "converse-core", + "formdata-polyfill", "utils/muc", "xss", "templates/add_chatroom_modal.html", @@ -34,6 +35,7 @@ ], factory); }(this, function ( converse, + _FormData, muc_utils, xss, tpl_add_chatroom_modal, diff --git a/src/converse-profile.js b/src/converse-profile.js index bac07b158..6ab3e9a22 100644 --- a/src/converse-profile.js +++ b/src/converse-profile.js @@ -9,6 +9,7 @@ (function (root, factory) { define(["converse-core", "bootstrap", + "formdata-polyfill", "templates/alert.html", "templates/chat_status_modal.html", "templates/profile_modal.html", @@ -20,6 +21,7 @@ }(this, function ( converse, bootstrap, + _FormData, tpl_alert, tpl_chat_status_modal, tpl_profile_modal, diff --git a/src/converse-rosterview.js b/src/converse-rosterview.js index e5660db0d..c530c5703 100644 --- a/src/converse-rosterview.js +++ b/src/converse-rosterview.js @@ -6,6 +6,7 @@ (function (root, factory) { define(["converse-core", + "formdata-polyfill", "templates/add_contact_modal.html", "templates/group_header.html", "templates/pending_contact.html", @@ -20,6 +21,7 @@ ], factory); }(this, function ( converse, + _FormData, tpl_add_contact_modal, tpl_group_header, tpl_pending_contact, diff --git a/webpack.config.js b/webpack.config.js index 9525f20d8..234d5f86a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -80,6 +80,7 @@ const config = { "IPv6": path.resolve(__dirname, "node_modules/urijs/src/IPv6"), "SecondLevelDomains": path.resolve(__dirname, "node_modules/urijs/src/SecondLevelDomains"), "awesomplete": path.resolve(__dirname, "node_modules/awesomplete-avoid-xss/awesomplete"), + "formdata-polyfill": path.resolve(__dirname, "node_modules/formdata-polyfill/FormData"), "backbone": path.resolve(__dirname, "node_modules/backbone/backbone"), "backbone.browserStorage": path.resolve(__dirname, "node_modules/backbone.browserStorage/backbone.browserStorage"), "backbone.nativeview": path.resolve(__dirname, "node_modules/backbone.nativeview/backbone.nativeview"),