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 {