From 095d9b60cd3456f0d7159a475bd4e834aaebec24 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Thu, 17 Jun 2021 14:37:43 +0200 Subject: [PATCH] Render audio from URLs in messages --- docs/source/configuration.rst | 11 ++ karma.conf.js | 2 + src/plugins/chatview/index.js | 1 + src/plugins/chatview/tests/message-audio.js | 25 +++ src/plugins/chatview/tests/messages.js | 163 ------------------- src/plugins/chatview/tests/oob.js | 167 ++++++++++++++++++++ src/shared/chat/message-body.js | 6 +- src/shared/chat/message.js | 1 + src/shared/chat/styles/message-body.scss | 5 + src/shared/components/rich-text.js | 11 +- src/shared/directives/styling.js | 2 +- src/shared/rich-text.js | 13 +- src/templates/audio.js | 10 +- src/utils/html.js | 26 ++- 14 files changed, 257 insertions(+), 186 deletions(-) create mode 100644 src/plugins/chatview/tests/message-audio.js create mode 100644 src/plugins/chatview/tests/oob.js create mode 100644 src/shared/chat/styles/message-body.scss diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 268e74485..734794c82 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -793,6 +793,17 @@ domain_placeholder The placeholder text shown in the domain input on the registration form. +embed_audio +----------- + +* Default: ``true`` + +If set to ``false``, audio files won't be embedded in chats, instead only their links will be shown. + +It also accepts an array strings of whitelisted domain names to only render videos that belong to those domains. +E.g. ``['conversejs.org']`` + + embed_videos ------------ diff --git a/karma.conf.js b/karma.conf.js index 59fe533a2..60b612908 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -47,9 +47,11 @@ module.exports = function(config) { { pattern: "src/plugins/chatview/tests/http-file-upload.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/markers.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/me-messages.js", type: 'module' }, + { pattern: "src/plugins/chatview/tests/message-audio.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/message-images.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/message-videos.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/messages.js", type: 'module' }, + { pattern: "src/plugins/chatview/tests/oob.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/receipts.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/spoilers.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/xss.js", type: 'module' }, diff --git a/src/plugins/chatview/index.js b/src/plugins/chatview/index.js index e9fa5e895..b0665c717 100644 --- a/src/plugins/chatview/index.js +++ b/src/plugins/chatview/index.js @@ -37,6 +37,7 @@ converse.plugins.add('converse-chatview', { 'auto_focus': true, 'debounced_content_rendering': true, 'embed_videos': true, + 'embed_audio': true, 'filter_url_query_params': null, 'image_urls_regex': null, 'message_limit': 0, diff --git a/src/plugins/chatview/tests/message-audio.js b/src/plugins/chatview/tests/message-audio.js new file mode 100644 index 000000000..545b4bbd2 --- /dev/null +++ b/src/plugins/chatview/tests/message-audio.js @@ -0,0 +1,25 @@ +/*global mock, converse */ + +const { sizzle, u } = converse.env; + +describe("A Chat Message", function () { + + it("will render audio files from their URLs", + mock.initConverse(['chatBoxesFetched'], {}, + async function (done, _converse) { + await mock.waitForRoster(_converse, 'current'); + const base_url = 'https://conversejs.org'; + const message = base_url+"/logo/audio.mp3"; + + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; + await mock.openChatBoxFor(_converse, contact_jid); + const view = _converse.chatboxviews.get(contact_jid); + await mock.sendMessage(view, message); + await u.waitUntil(() => view.querySelectorAll('.chat-content audio').length, 1000) + const msg = sizzle('.chat-content .chat-msg:last .chat-msg__text').pop(); + expect(msg.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual( + ``+ + `${message}`); + done(); + })); +}); diff --git a/src/plugins/chatview/tests/messages.js b/src/plugins/chatview/tests/messages.js index 667a50bea..5511e020e 100644 --- a/src/plugins/chatview/tests/messages.js +++ b/src/plugins/chatview/tests/messages.js @@ -1267,167 +1267,4 @@ describe("A Chat Message", function () { done(); })); }); - - - describe("which contains an OOB URL", function () { - - it("will render audio from oob mp3 URLs", - mock.initConverse( - ['chatBoxesFetched'], {}, - async function (done, _converse) { - - await mock.waitForRoster(_converse, 'current', 1); - const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; - await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.chatboxviews.get(contact_jid); - spyOn(view.model, 'sendMessage').and.callThrough(); - - let stanza = u.toStanza(` - - Have you heard this funny audio? - https://montague.lit/audio.mp3 - `) - _converse.connection._dataRecv(mock.createRequest(stanza)); - await new Promise(resolve => view.model.messages.once('rendered', resolve)); - await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg audio').length, 1000); - let msg = view.querySelector('.chat-msg .chat-msg__text'); - expect(msg.classList.length).toEqual(1); - expect(u.hasClass('chat-msg__text', msg)).toBe(true); - expect(msg.textContent).toEqual('Have you heard this funny audio?'); - let media = view.querySelector('.chat-msg .chat-msg__media'); - expect(media.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual( - ` `+ - `Download audio file "audio.mp3"`); - - // If the and contents is the same, don't duplicate. - stanza = u.toStanza(` - - https://montague.lit/audio.mp3 - https://montague.lit/audio.mp3 - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await new Promise(resolve => view.model.messages.once('rendered', resolve)); - msg = view.querySelector('.chat-msg:last-child .chat-msg__text'); - expect(msg.innerHTML.replace(//g, '')).toEqual('Have you heard this funny audio?'); // Emtpy - media = view.querySelector('.chat-msg:last-child .chat-msg__media'); - expect(media.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual( - ` `+ - ``+ - `Download audio file "audio.mp3"`); - done(); - })); - - it("will render video from oob mp4 URLs", - mock.initConverse( - ['chatBoxesFetched'], {}, - async function (done, _converse) { - - await mock.waitForRoster(_converse, 'current', 1); - const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; - await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.chatboxviews.get(contact_jid); - spyOn(view.model, 'sendMessage').and.callThrough(); - - let stanza = u.toStanza(` - - Have you seen this funny video? - https://montague.lit/video.mp4 - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg video').length, 2000) - let msg = view.querySelector('.chat-msg .chat-msg__text'); - expect(msg.classList.length).toBe(1); - expect(msg.textContent).toEqual('Have you seen this funny video?'); - let media = view.querySelector('.chat-msg .chat-msg__media'); - expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(//g, '')).toEqual( - ``); - - - // If the and contents is the same, don't duplicate. - stanza = u.toStanza(` - - https://montague.lit/video.mp4 - https://montague.lit/video.mp4 - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await new Promise(resolve => view.model.messages.once('rendered', resolve)); - msg = view.querySelector('.chat-msg:last-child .chat-msg__text'); - expect(msg.innerHTML.replace(//g, '')).toEqual('Have you seen this funny video?'); - media = view.querySelector('.chat-msg:last-child .chat-msg__media'); - expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(//g, '')).toEqual( - ``); - done(); - })); - - it("will render download links for files from oob URLs", - mock.initConverse( - ['chatBoxesFetched'], {}, - async function (done, _converse) { - - await mock.waitForRoster(_converse, 'current', 1); - const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; - await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.chatboxviews.get(contact_jid); - spyOn(view.model, 'sendMessage').and.callThrough(); - const stanza = u.toStanza(` - - Have you downloaded this funny file? - https://montague.lit/funny.pdf - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await new Promise(resolve => view.model.messages.once('rendered', resolve)); - await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg a').length, 1000); - const msg = view.querySelector('.chat-msg .chat-msg__text'); - expect(u.hasClass('chat-msg__text', msg)).toBe(true); - expect(msg.textContent).toEqual('Have you downloaded this funny file?'); - const media = view.querySelector('.chat-msg .chat-msg__media'); - expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(//g, '')).toEqual( - `Download file "funny.pdf"`); - done(); - })); - - it("will render images from oob URLs", - mock.initConverse( - ['chatBoxesFetched'], {}, - async function (done, _converse) { - - const base_url = 'https://conversejs.org'; - await mock.waitForRoster(_converse, 'current', 1); - const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; - await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.chatboxviews.get(contact_jid); - spyOn(view.model, 'sendMessage').and.callThrough(); - const url = base_url+"/logo/conversejs-filled.svg"; - - const stanza = u.toStanza(` - - Have you seen this funny image? - ${url} - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await new Promise(resolve => view.model.messages.once('rendered', resolve)); - await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg a').length, 1000); - const msg = view.querySelector('.chat-msg .chat-msg__text'); - expect(u.hasClass('chat-msg__text', msg)).toBe(true); - expect(msg.textContent).toEqual('Have you seen this funny image?'); - const media = view.querySelector('.chat-msg .chat-msg__media'); - expect(media.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "")).toEqual( - ``+ - `Download image file "conversejs-filled.svg"`); - done(); - })); - }); }); diff --git a/src/plugins/chatview/tests/oob.js b/src/plugins/chatview/tests/oob.js new file mode 100644 index 000000000..d8751a4fa --- /dev/null +++ b/src/plugins/chatview/tests/oob.js @@ -0,0 +1,167 @@ +/*global mock, converse */ + +const { Promise, u } = converse.env; + +describe("A Chat Message", function () { + describe("which contains an OOB URL", function () { + + it("will render audio from oob mp3 URLs", + mock.initConverse( + ['chatBoxesFetched'], {}, + async function (done, _converse) { + + await mock.waitForRoster(_converse, 'current', 1); + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; + await mock.openChatBoxFor(_converse, contact_jid); + const view = _converse.chatboxviews.get(contact_jid); + spyOn(view.model, 'sendMessage').and.callThrough(); + + const url = 'https://montague.lit/audio.mp3'; + let stanza = u.toStanza(` + + Have you heard this funny audio? + ${url} + `) + _converse.connection._dataRecv(mock.createRequest(stanza)); + await new Promise(resolve => view.model.messages.once('rendered', resolve)); + await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg audio').length, 1000); + let msg = view.querySelector('.chat-msg .chat-msg__text'); + expect(msg.classList.length).toEqual(1); + expect(u.hasClass('chat-msg__text', msg)).toBe(true); + expect(msg.textContent).toEqual('Have you heard this funny audio?'); + let media = view.querySelector('.chat-msg .chat-msg__media'); + expect(media.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual( + ``+ + `${url}`); + + // If the and contents is the same, don't duplicate. + stanza = u.toStanza(` + + https://montague.lit/audio.mp3 + https://montague.lit/audio.mp3 + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await new Promise(resolve => view.model.messages.once('rendered', resolve)); + msg = view.querySelector('.chat-msg:last-child .chat-msg__text'); + expect(msg.innerHTML.replace(//g, '')).toEqual('Have you heard this funny audio?'); // Emtpy + media = view.querySelector('.chat-msg:last-child .chat-msg__media'); + expect(media.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "").trim()).toEqual( + ``+ + `${url}`); + done(); + })); + + it("will render video from oob mp4 URLs", + mock.initConverse( + ['chatBoxesFetched'], {}, + async function (done, _converse) { + + await mock.waitForRoster(_converse, 'current', 1); + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; + await mock.openChatBoxFor(_converse, contact_jid) + const view = _converse.chatboxviews.get(contact_jid); + spyOn(view.model, 'sendMessage').and.callThrough(); + + let stanza = u.toStanza(` + + Have you seen this funny video? + https://montague.lit/video.mp4 + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg video').length, 2000) + let msg = view.querySelector('.chat-msg .chat-msg__text'); + expect(msg.classList.length).toBe(1); + expect(msg.textContent).toEqual('Have you seen this funny video?'); + let media = view.querySelector('.chat-msg .chat-msg__media'); + expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(//g, '')).toEqual( + ``); + + + // If the and contents is the same, don't duplicate. + stanza = u.toStanza(` + + https://montague.lit/video.mp4 + https://montague.lit/video.mp4 + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await new Promise(resolve => view.model.messages.once('rendered', resolve)); + msg = view.querySelector('.chat-msg:last-child .chat-msg__text'); + expect(msg.innerHTML.replace(//g, '')).toEqual('Have you seen this funny video?'); + media = view.querySelector('.chat-msg:last-child .chat-msg__media'); + expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(//g, '')).toEqual( + ``); + done(); + })); + + it("will render download links for files from oob URLs", + mock.initConverse( + ['chatBoxesFetched'], {}, + async function (done, _converse) { + + await mock.waitForRoster(_converse, 'current', 1); + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; + await mock.openChatBoxFor(_converse, contact_jid); + const view = _converse.chatboxviews.get(contact_jid); + spyOn(view.model, 'sendMessage').and.callThrough(); + const stanza = u.toStanza(` + + Have you downloaded this funny file? + https://montague.lit/funny.pdf + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await new Promise(resolve => view.model.messages.once('rendered', resolve)); + await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg a').length, 1000); + const msg = view.querySelector('.chat-msg .chat-msg__text'); + expect(u.hasClass('chat-msg__text', msg)).toBe(true); + expect(msg.textContent).toEqual('Have you downloaded this funny file?'); + const media = view.querySelector('.chat-msg .chat-msg__media'); + expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(//g, '')).toEqual( + `Download file "funny.pdf"`); + done(); + })); + + it("will render images from oob URLs", + mock.initConverse( + ['chatBoxesFetched'], {}, + async function (done, _converse) { + + const base_url = 'https://conversejs.org'; + await mock.waitForRoster(_converse, 'current', 1); + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; + await mock.openChatBoxFor(_converse, contact_jid) + const view = _converse.chatboxviews.get(contact_jid); + spyOn(view.model, 'sendMessage').and.callThrough(); + const url = base_url+"/logo/conversejs-filled.svg"; + + const stanza = u.toStanza(` + + Have you seen this funny image? + ${url} + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await new Promise(resolve => view.model.messages.once('rendered', resolve)); + await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg a').length, 1000); + const msg = view.querySelector('.chat-msg .chat-msg__text'); + expect(u.hasClass('chat-msg__text', msg)).toBe(true); + expect(msg.textContent).toEqual('Have you seen this funny image?'); + const media = view.querySelector('.chat-msg .chat-msg__media'); + expect(media.innerHTML.replace(//g, '').replace(/(\r\n|\n|\r)/gm, "")).toEqual( + ``+ + `Download image file "conversejs-filled.svg"`); + done(); + })); + }); +}); diff --git a/src/shared/chat/message-body.js b/src/shared/chat/message-body.js index f2f32d7db..54db3a36f 100644 --- a/src/shared/chat/message-body.js +++ b/src/shared/chat/message-body.js @@ -4,6 +4,8 @@ import renderRichText from 'shared/directives/rich-text.js'; import { CustomElement } from 'shared/components/element.js'; import { api } from "@converse/headless/core"; +import './styles/message-body.scss'; + export default class MessageBody extends CustomElement { @@ -13,6 +15,7 @@ export default class MessageBody extends CustomElement { is_me_message: { type: Boolean }, show_images: { type: Boolean }, embed_videos: { type: Boolean }, + embed_audio: { type: Boolean }, text: { type: String }, } } @@ -31,12 +34,13 @@ export default class MessageBody extends CustomElement { const offset = 0; const mentions = this.model.get('references'); const options = { + 'embed_audio': this.embed_audio, + 'embed_videos': this.embed_videos, 'nick': this.model.collection.chatbox.get('nick'), 'onImgClick': this.onImgClick, 'onImgLoad': () => this.onImgLoad(), 'render_styling': !this.model.get('is_unstyled') && api.settings.get('allow_message_styling'), 'show_images': this.show_images, - 'embed_videos': this.embed_videos, 'show_me_message': true } return renderRichText(this.text, offset, mentions, options, callback); diff --git a/src/shared/chat/message.js b/src/shared/chat/message.js index 9eff46199..3cd129e8c 100644 --- a/src/shared/chat/message.js +++ b/src/shared/chat/message.js @@ -240,6 +240,7 @@ export default class Message extends CustomElement { ?is_me_message="${this.model.isMeCommand()}" ?show_images="${api.settings.get('show_images_inline')}" ?embed_videos="${api.settings.get('embed_videos')}" + ?embed_audio="${api.settings.get('embed_audio')}" text="${text}"> ${ (this.model.get('received') && !this.model.isMeCommand() && !is_groupchat_message) ? html`` : '' } ${ (this.model.get('edited')) ? html`` : '' } diff --git a/src/shared/chat/styles/message-body.scss b/src/shared/chat/styles/message-body.scss new file mode 100644 index 000000000..2d86a9846 --- /dev/null +++ b/src/shared/chat/styles/message-body.scss @@ -0,0 +1,5 @@ +converse-chat-message-body { + audio { + width: 100%; + } +} diff --git a/src/shared/components/rich-text.js b/src/shared/components/rich-text.js index 511865200..ffdd40439 100644 --- a/src/shared/components/rich-text.js +++ b/src/shared/components/rich-text.js @@ -6,6 +6,8 @@ export default class RichText extends CustomElement { static get properties () { return { + embed_audio: { type: Boolean }, + embed_videos: { type: Boolean }, mentions: { type: Array }, nick: { type: String }, offset: { type: Number }, @@ -13,7 +15,6 @@ export default class RichText extends CustomElement { onImgLoad: { type: Function }, render_styling: { type: Boolean }, show_images: { type: Boolean }, - embed_videos: { type: Boolean }, show_me_message: { type: Boolean }, text: { type: String }, } @@ -21,22 +22,24 @@ export default class RichText extends CustomElement { constructor () { super(); - this.offset = 0; + this.embed_audio = false; + this.embed_videos = false; this.mentions = []; + this.offset = 0; this.render_styling = false; this.show_images = false; - this.embed_videos = false; this.show_me_message = false; } render () { const options = { + embed_audio: this.embed_audio, + embed_videos: this.embed_videos, nick: this.nick, onImgClick: this.onImgClick, onImgLoad: this.onImgLoad, render_styling: this.render_styling, show_images: this.show_images, - embed_videos: this.embed_videos, show_me_message: this.show_me_message, } return renderRichText(this.text, this.offset, this.mentions, options); diff --git a/src/shared/directives/styling.js b/src/shared/directives/styling.js index e37ddc3d4..5f9ab7532 100644 --- a/src/shared/directives/styling.js +++ b/src/shared/directives/styling.js @@ -14,7 +14,7 @@ class StylingDirective extends Directive { txt, offset, mentions, - Object.assign(options, { 'show_images': false, 'embed_videos': false }) + Object.assign(options, { 'show_images': false, 'embed_videos': false, 'embed_audio': false }) ); return html`${until(transform(t), html`${t}`)}`; } diff --git a/src/shared/rich-text.js b/src/shared/rich-text.js index b91522f5c..6c31beb68 100644 --- a/src/shared/rich-text.js +++ b/src/shared/rich-text.js @@ -1,7 +1,8 @@ import URI from 'urijs'; import log from '@converse/headless/log'; +import tpl_audio from 'templates/audio.js'; import tpl_image from 'templates/image.js'; -import tpl_video from '../templates/video.js'; +import tpl_video from 'templates/video.js'; import { _converse, api } from '@converse/headless/core'; import { containsDirectives, getDirectiveAndLength, getDirectiveTemplate, isQuoteDirective } from './styling.js'; import { @@ -13,8 +14,11 @@ import { import { filterQueryParamsFromURL, getHyperlinkTemplate, - isImageURL, + getURI, + isAudioDomainAllowed, + isAudioURL, isImageDomainAllowed, + isImageURL, isVideoDomainAllowed, isVideoURL } from 'utils/html'; @@ -66,6 +70,8 @@ export class RichText extends String { */ constructor (text, offset = 0, mentions = [], options = {}) { super(text); + this.embed_audio = options?.embed_audio; + this.embed_videos = options?.embed_videos; this.mentions = mentions; this.nick = options?.nick; this.offset = offset; @@ -76,7 +82,6 @@ export class RichText extends String { this.references = []; this.render_styling = options?.render_styling; this.show_images = options?.show_images; - this.embed_videos = options?.embed_videos; } /** @@ -114,6 +119,8 @@ export class RichText extends String { }); } else if (this.embed_videos && isVideoURL(url_text) && isVideoDomainAllowed(url_text)) { template = tpl_video({ 'url': filtered_url }); + } else if (this.embed_audio && isAudioURL(url_text) && isAudioDomainAllowed(url_text)) { + template = tpl_audio(filtered_url); } else { template = getHyperlinkTemplate(filtered_url); } diff --git a/src/templates/audio.js b/src/templates/audio.js index 4daa7c35e..a3d941623 100644 --- a/src/templates/audio.js +++ b/src/templates/audio.js @@ -1,7 +1,5 @@ -import { html } from "lit"; +import { html } from 'lit'; - -export default (o) => html` - - ${o.label_download} -`; +export default (url) => { + return html`${url}`; +} diff --git a/src/utils/html.js b/src/utils/html.js index 29c5a3797..dcf189970 100644 --- a/src/utils/html.js +++ b/src/utils/html.js @@ -94,6 +94,20 @@ export function isImageURL (url) { return regex?.test(url) || isURLWithImageExtension(url); } +export function isAudioDomainAllowed (url) { + const embed_audio = api.settings.get('embed_audio'); + if (!Array.isArray(embed_audio)) { + return embed_audio; + } + try { + const audio_domain = getURI(url).domain(); + return embed_audio.includes(audio_domain); + } catch (error) { + log.debug(error); + return false; + } +} + export function isVideoDomainAllowed (url) { const embed_videos = api.settings.get('embed_videos'); if (!Array.isArray(embed_videos)) { @@ -122,7 +136,7 @@ export function isImageDomainAllowed (url) { } } -function getFileName (uri) { +export function getFileName (uri) { try { return decodeURI(uri.filename()); } catch (error) { @@ -131,12 +145,8 @@ function getFileName (uri) { } } -function renderAudioURL (_converse, uri) { - const { __ } = _converse; - return tpl_audio({ - 'url': uri.toString(), - 'label_download': __('Download audio file "%1$s"', getFileName(uri)) - }); +function renderAudioURL (url) { + return tpl_audio(url); } function renderImageURL (_converse, uri) { @@ -170,7 +180,7 @@ u.getOOBURLMarkup = function (_converse, url) { if (u.isVideoURL(uri)) { return tpl_video({ url }); } else if (u.isAudioURL(uri)) { - return renderAudioURL(_converse, uri); + return renderAudioURL(url); } else if (u.isImageURL(uri)) { return renderImageURL(_converse, uri); } else {