Some UI improvements
- Render images as thumbnails - Use the image.html template when rendering images from pasted URLs - Update message and spoiler markup to render avatars - Use the default avatar as fallback when user doesn't have one - Instead of 'me' render own name or JID
This commit is contained in:
parent
f913ee86f0
commit
3d42425083
|
@ -101,7 +101,6 @@ Brief description of converse.js's dependencies
|
|||
|
||||
Converse.js relies on the following dependencies:
|
||||
|
||||
* `JQuery <http://jquery.com/>`_ for DOM manipulation and `promises <http://api.jquery.com/promise/>`_.
|
||||
* `moment.js <http://momentjs.com/>`_ provides a better API for handling dates and times.
|
||||
* `Strophe.js <http://strophe.im/>`_ maintains the XMPP session, is used to
|
||||
build XMPP stanzas, to send them, and to register handlers for received stanzas.
|
||||
|
|
|
@ -25,12 +25,6 @@
|
|||
<div class="chat-head chat-head-chatbox row no-gutters">
|
||||
<div class="col">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-auto">
|
||||
<img alt="User Avatar"
|
||||
class="avatar"
|
||||
height="50px" width="50px"
|
||||
src="data:image/png;base64,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"/>
|
||||
</div>
|
||||
<div class="col chat-title" title="j@chat.example.org">Juliet Capulet
|
||||
<p class="user-custom-message" title="On the balcony">On the balcony</p>
|
||||
</div>
|
||||
|
|
|
@ -97,7 +97,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="message chat-msg">
|
||||
<canvas height="36" width="36" class="avatar"></canvas>
|
||||
<div class="chat-msg-content">
|
||||
|
@ -111,6 +110,24 @@
|
|||
Or, if thou wilt not, be but sworn my love,
|
||||
And I'll no longer be a Capulet.
|
||||
</p>
|
||||
<div class="chat-msg-media"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message chat-msg">
|
||||
<canvas height="36" width="36" class="avatar"></canvas>
|
||||
<div class="chat-msg-content">
|
||||
<span class="chat-msg-heading">
|
||||
<span class="chat-msg-author">Juliet Capulet</span>
|
||||
<span class="chat-msg-time text-muted">19:45</span>
|
||||
</span>
|
||||
<p class="chat-msg-text"></p>
|
||||
<div class="chat-msg-media">
|
||||
<a href="https://images.unsplash.com/photo-1496660067708-010ebdd7ce72?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ea3514e6e00d8ce25c24d992b97929d9&dpr=1&auto=format&fit=crop&w=1000&q=80&cs=tinysrgb"
|
||||
target="_blank" rel="noopener">
|
||||
<img class="chat-image img-thumbnail" src="https://images.unsplash.com/photo-1496660067708-010ebdd7ce72?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ea3514e6e00d8ce25c24d992b97929d9&dpr=1&auto=format&fit=crop&w=1000&q=80&cs=tinysrgb">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -121,13 +138,15 @@
|
|||
<span class="chat-msg-author">Romeo Montague</span>
|
||||
<span class="chat-msg-time text-muted">19:36</span>
|
||||
</span>
|
||||
<div class="spoiler-hint">By a name
|
||||
<a class="badge badge-info toggle-spoiler" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>Show more</a>
|
||||
<div>
|
||||
<span class="spoiler-hint">By a name</span>
|
||||
<a class="badge badge-info spoiler-toggle" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>Show more</a>
|
||||
</div>
|
||||
<div class="chat-msg-text spoiler collapsed">
|
||||
I know not how to tell thee who I am: My name, dear saint, is hateful to
|
||||
myself, Because it is an enemy to thee. Had I it written, I would tear the word.
|
||||
</div>
|
||||
<div class="chat-msg-media"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ function toggleSpoilerMessage (ev) {
|
|||
}
|
||||
|
||||
window.initSpoilers = function () {
|
||||
const spoilers = document.querySelectorAll('.toggle-spoiler');
|
||||
const spoilers = document.querySelectorAll('.spoiler-toggle');
|
||||
_.each(spoilers, (spoiler_el) => {
|
||||
spoiler_el.addEventListener('click', toggleSpoilerMessage);
|
||||
});
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
_converse.chatboxes.onMessage(msg);
|
||||
|
||||
var view = _converse.chatboxviews.get(sender_jid);
|
||||
expect(_.includes(view.el.querySelector('.chat-msg-author').textContent, 'Max Frankfurter')).toBeTruthy();
|
||||
expect(view.el.querySelector('.chat-msg-author').textContent).toBe('Max Frankfurter');
|
||||
|
||||
var message_content = view.el.querySelector('.chat-msg-content');
|
||||
var message_content = view.el.querySelector('.chat-msg-text');
|
||||
expect(message_content.textContent).toBe(spoiler);
|
||||
|
||||
var spoiler_hint_el = view.el.querySelector('.spoiler-hint');
|
||||
|
@ -82,7 +82,7 @@
|
|||
var view = _converse.chatboxviews.get(sender_jid);
|
||||
expect(_.includes(view.el.querySelector('.chat-msg-author').textContent, 'Max Frankfurter')).toBeTruthy();
|
||||
|
||||
var message_content = view.el.querySelector('.chat-msg-content');
|
||||
var message_content = view.el.querySelector('.chat-msg-text');
|
||||
expect(message_content.textContent).toBe(spoiler);
|
||||
|
||||
var spoiler_hint_el = view.el.querySelector('.spoiler-hint');
|
||||
|
@ -148,17 +148,17 @@
|
|||
expect(body_el.textContent).toBe('This is the spoiler');
|
||||
|
||||
/* Test the HTML spoiler message */
|
||||
expect(view.el.querySelector('.chat-msg-author').textContent.split(':')[1].trim().split(' ')[1]).toBe('me');
|
||||
expect(view.el.querySelector('.chat-msg-author').textContent).toBe('dummy@localhost');
|
||||
|
||||
var spoiler_msg_el = view.el.querySelector('.chat-msg-content.spoiler');
|
||||
var spoiler_msg_el = view.el.querySelector('.chat-msg-text.spoiler');
|
||||
expect(spoiler_msg_el.textContent).toBe('This is the spoiler');
|
||||
expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
|
||||
|
||||
spoiler_toggle = view.el.querySelector('.toggle-spoiler');
|
||||
expect(spoiler_toggle.textContent).toBe('Show hidden message');
|
||||
spoiler_toggle = view.el.querySelector('.spoiler-toggle');
|
||||
expect(spoiler_toggle.textContent).toBe('Show more');
|
||||
spoiler_toggle.click();
|
||||
expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeFalsy();
|
||||
expect(spoiler_toggle.textContent).toBe('Hide hidden message');
|
||||
expect(spoiler_toggle.textContent).toBe('Show less');
|
||||
spoiler_toggle.click();
|
||||
expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
|
||||
done();
|
||||
|
@ -227,17 +227,17 @@
|
|||
expect(body_el.textContent).toBe('This is the spoiler');
|
||||
|
||||
/* Test the HTML spoiler message */
|
||||
expect(view.el.querySelector('.chat-msg-author').textContent.split(':')[1].trim().split(' ')[1]).toBe('me');
|
||||
expect(view.el.querySelector('.chat-msg-author').textContent).toBe('dummy@localhost');
|
||||
|
||||
var spoiler_msg_el = view.el.querySelector('.chat-msg-content.spoiler');
|
||||
var spoiler_msg_el = view.el.querySelector('.chat-msg-text.spoiler');
|
||||
expect(spoiler_msg_el.textContent).toBe('This is the spoiler');
|
||||
expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
|
||||
|
||||
spoiler_toggle = view.el.querySelector('.toggle-spoiler');
|
||||
expect(spoiler_toggle.textContent).toBe('Show hidden message');
|
||||
spoiler_toggle = view.el.querySelector('.spoiler-toggle');
|
||||
expect(spoiler_toggle.textContent).toBe('Show more');
|
||||
spoiler_toggle.click();
|
||||
expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeFalsy();
|
||||
expect(spoiler_toggle.textContent).toBe('Hide hidden message');
|
||||
expect(spoiler_toggle.textContent).toBe('Show less');
|
||||
spoiler_toggle.click();
|
||||
expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy();
|
||||
done();
|
||||
|
|
|
@ -193,7 +193,6 @@
|
|||
'image': _converse.DEFAULT_IMAGE,
|
||||
'image_type': _converse.DEFAULT_IMAGE_TYPE,
|
||||
'num_unread': 0,
|
||||
'show_avatar': true,
|
||||
'type': 'chatbox',
|
||||
'message_type': 'chat',
|
||||
'url': ''
|
||||
|
|
|
@ -249,7 +249,7 @@
|
|||
'click .toggle-compose-spoiler': 'toggleComposeSpoilerMessage',
|
||||
'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
|
||||
'click .toggle-smiley': 'toggleEmojiMenu',
|
||||
'click .toggle-spoiler': 'toggleSpoilerMessage',
|
||||
'click .spoiler-toggle': 'toggleSpoilerMessage',
|
||||
'click .upload-file': 'toggleFileUpload',
|
||||
'keypress .chat-textarea': 'keyPressed',
|
||||
'input .chat-textarea': 'inputChanged'
|
||||
|
@ -373,7 +373,7 @@
|
|||
this.el.querySelector('.chat-toolbar').insertAdjacentHTML('afterBegin', html);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||
},
|
||||
|
||||
insertHeading () {
|
||||
|
@ -907,14 +907,16 @@
|
|||
toggle_el.parentElement.parentElement.querySelector('.spoiler')
|
||||
);
|
||||
if (toggle_el.getAttribute("data-toggle-state") == "closed") {
|
||||
toggle_el.textContent = __('Show less');
|
||||
toggle_el.textContent = 'Show less';
|
||||
icon_el.classList.remove("fa-eye");
|
||||
icon_el.classList.add("fa-eye-slash");
|
||||
toggle_el.insertAdjacentElement('afterBegin', icon_el);
|
||||
toggle_el.setAttribute("data-toggle-state", "open");
|
||||
} else {
|
||||
toggle_el.textContent = __('Show more');
|
||||
toggle_el.textContent = 'Show more';
|
||||
icon_el.classList.remove("fa-eye-slash");
|
||||
icon_el.classList.add("fa-eye");
|
||||
toggle_el.insertAdjacentElement('afterBegin', icon_el);
|
||||
toggle_el.setAttribute("data-toggle-state", "closed");
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1509,10 +1509,12 @@
|
|||
|
||||
defaults () {
|
||||
return {
|
||||
"status": _converse.default_state,
|
||||
"jid": _converse.bare_jid,
|
||||
"nickname": _converse.nickname,
|
||||
"vcard_updated": null
|
||||
"status": _converse.default_state,
|
||||
"vcard_updated": null,
|
||||
'image': _converse.DEFAULT_IMAGE,
|
||||
'image_type': _converse.DEFAULT_IMAGE_TYPE
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
_converse.HeadlinesBox = _converse.ChatBox.extend({
|
||||
defaults: {
|
||||
'type': 'headline',
|
||||
'show_avatar': false,
|
||||
'bookmarked': false,
|
||||
'chat_state': undefined,
|
||||
'num_unread': 0,
|
||||
|
|
|
@ -44,8 +44,8 @@
|
|||
_converse.MessageView = Backbone.NativeView.extend({
|
||||
|
||||
initialize () {
|
||||
const chatbox = this.model.collection.chatbox;
|
||||
chatbox.on('change:fullname', (chatbox) => this.model.save('fullname', chatbox.get('fullname')));
|
||||
this.chatbox = this.model.collection.chatbox;
|
||||
this.chatbox.on('change:fullname', (chatbox) => this.model.save('fullname', chatbox.get('fullname')));
|
||||
|
||||
this.model.on('change:fullname', this.render, this);
|
||||
this.model.on('change:progress', this.renderFileUploadProgresBar, this);
|
||||
|
@ -61,7 +61,7 @@
|
|||
return this.renderErrorMessage();
|
||||
}
|
||||
|
||||
let template, username,
|
||||
let template, username, image, image_type,
|
||||
text = this.model.get('message');
|
||||
|
||||
// TODO: store proper username on the message itself
|
||||
|
@ -71,9 +71,16 @@
|
|||
username = arr[1];
|
||||
text = arr[2];
|
||||
} else {
|
||||
const fullname = _converse.xmppstatus.get('fullname') || this.model.get('fullname');
|
||||
username = this.model.get('sender') === 'me' && __('me') || fullname || this.model.get('from');
|
||||
username = this.model.get('fullname') || this.model.get('from');
|
||||
template = this.model.get('is_spoiler') ? tpl_spoiler_message : tpl_message;
|
||||
|
||||
if (this.model.get('sender') === 'me') {
|
||||
image_type = _converse.xmppstatus.get('image_type');
|
||||
image = _converse.xmppstatus.get('image');
|
||||
} else {
|
||||
image_type = this.chatbox.get('image_type');
|
||||
image = this.chatbox.get('image');
|
||||
}
|
||||
}
|
||||
const moment_time = moment(this.model.get('time'));
|
||||
const msg = u.stringToElement(template(
|
||||
|
@ -82,7 +89,9 @@
|
|||
'time': moment_time.format(),
|
||||
'username': username,
|
||||
'extra_classes': this.getExtraMessageClasses(),
|
||||
'label_show': __('Show more')
|
||||
'label_show': __('Show more'),
|
||||
'image_type': image_type,
|
||||
'image': image
|
||||
})
|
||||
));
|
||||
|
||||
|
@ -97,7 +106,7 @@
|
|||
)(url);
|
||||
}
|
||||
|
||||
const msg_content = msg.querySelector('.chat-msg-content');
|
||||
const msg_content = msg.querySelector('.chat-msg-text');
|
||||
if (text !== url) {
|
||||
text = xss.filterXSS(text, {'whiteList': {}});
|
||||
msg_content.innerHTML = _.flow(
|
||||
|
@ -106,7 +115,7 @@
|
|||
_.partial(u.addEmoji, _converse, emojione, _)
|
||||
)(text);
|
||||
}
|
||||
u.renderImageURLs(msg_content).then(() => {
|
||||
u.renderImageURLs(_converse, msg_content).then(() => {
|
||||
this.model.collection.trigger('rendered');
|
||||
});
|
||||
return this.replaceElement(msg);
|
||||
|
|
|
@ -1485,7 +1485,7 @@
|
|||
* Chat rooms can be listed, joined and new rooms can be created.
|
||||
*/
|
||||
tagName: 'div',
|
||||
className: 'controlbox-pane',
|
||||
className: 'controlbox-section',
|
||||
id: 'chatrooms',
|
||||
events: {
|
||||
'click a.chatbox-btn.fa-users': 'showAddRoomModal',
|
||||
|
|
|
@ -304,15 +304,11 @@
|
|||
getOutgoingMessageAttributes (text, spoiler_hint) {
|
||||
const is_spoiler = this.get('composing_spoiler');
|
||||
return {
|
||||
'from': _converse.connection.jid,
|
||||
'fullname': this.get('nick'),
|
||||
'is_spoiler': is_spoiler,
|
||||
'message': text ? u.httpToGeoUri(emojione.shortnameToUnicode(text), _converse) : undefined,
|
||||
'msgid': _converse.connection.getUniqueId(),
|
||||
'sender': 'me',
|
||||
'spoiler_hint': is_spoiler ? spoiler_hint : undefined,
|
||||
'time': moment().format(),
|
||||
'to': this.get('jid'),
|
||||
'type': 'groupchat',
|
||||
};
|
||||
},
|
||||
|
|
|
@ -719,6 +719,7 @@
|
|||
_converse.RosterView = Backbone.OrderedListView.extend({
|
||||
tagName: 'div',
|
||||
id: 'converse-roster',
|
||||
className: 'controlbox-section',
|
||||
|
||||
ItemView: _converse.RosterGroupView,
|
||||
listItems: 'model',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="room-item">
|
||||
<div class="list-item room-item">
|
||||
<div class="available-chatroom d-flex flex-row {[ if (o.hidden) { ]} hidden {[ } ]}" data-room-jid="{{{o.jid}}}">
|
||||
<a class="open-room w-100" data-room-jid="{{{o.jid}}}" title="{{{o.open_title}}}" href="#">{{{o.name}}}</a>
|
||||
<a class="remove-bookmark fa fa-bookmark align-self-center {[ if (o.bookmarked) { ]} button-on {[ } ]}"
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
<div class="chat-head chat-head-chatbox row no-gutters">
|
||||
<div class="col">
|
||||
<div class="row no-gutters">
|
||||
{[ if (o.show_avatar) { ]}
|
||||
<div class="col-auto">
|
||||
<img alt="User Avatar"
|
||||
class="avatar"
|
||||
height="{{{o.avatar_height}}}px" width="{{{o.avatar_width}}}px"
|
||||
src="data:{{{o.image_type || o._converse.DEFAULT_IMAGE_TYPE}}};base64,{{{o.image || o._converse.DEFAULT_IMAGE}}}"/>
|
||||
</div>
|
||||
{[ } ]}
|
||||
<div class="col chat-title" title="{{{o.jid}}}">
|
||||
{[ if (o.url) { ]}
|
||||
<a href="{{{o.url}}}" target="_blank" rel="noopener" class="user">
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
<img class="chat-image" src="{{{o.url}}}"/>
|
||||
<a href="{{{o.url}}}"
|
||||
target="_blank" rel="noopener">
|
||||
<img class="chat-image img-thumbnail" src="{{{o.url}}}">
|
||||
</a>
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<div class="message chat-msg {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}">
|
||||
<span class="chat-msg-author chat-msg-{{{o.sender}}}">{{{o.pretty_time}}} {{{o.username}}}: </span>
|
||||
<span class="chat-msg-content"></span>
|
||||
<div class="chat-msg-media"></div>
|
||||
<img alt="User Avatar" class="avatar" height="36px" width="36px" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
|
||||
<div class="chat-msg-content">
|
||||
<span class="chat-msg-heading">
|
||||
<span class="chat-msg-author">{{{o.username}}}</span>
|
||||
<span class="chat-msg-time tex{{{o.username}}}t-muted">{{{o.pretty_time}}}</span>
|
||||
</span>
|
||||
<p class="chat-msg-text">
|
||||
<div class="chat-msg-media"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- <div id="chatrooms"> -->
|
||||
<div class="d-flex">
|
||||
<span class="w-100">{{{o.heading_chatrooms}}}</span>
|
||||
<span class="w-100 controlbox-heading">{{{o.heading_chatrooms}}}</span>
|
||||
<a class="chatbox-btn trigger-list-chatrooms-modal fa fa-list-ul" title="{{{o.title_list_rooms}}}" data-toggle="modal" data-target="#list-chatrooms-modal"></a>
|
||||
<a class="chatbox-btn trigger-add-chatrooms-modal fa fa-users" title="{{{o.title_new_room}}}" data-toggle="modal" data-target="#add-chatrooms-modal"></a>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="room-item">
|
||||
<div class="list-item room-item">
|
||||
<div class="available-chatroom d-flex flex-row {[ if (o.num_unread_general) { ]} unread-msgs {[ } ]}" data-room-jid="{{{o.jid}}}">
|
||||
{[ if (o.num_unread) { ]}
|
||||
<span class="msgs-indicator badge badge-info">{{{ o.num_unread }}}</span>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="d-flex">
|
||||
<span class="w-100">{{{o.heading_contacts}}}</span>
|
||||
<span class="w-100 controlbox-heading">{{{o.heading_contacts}}}</span>
|
||||
<a class="chatbox-btn add-contact fa fa-user-plus" title="{{{o.title_add_contact}}}"
|
||||
data-toggle="modal" data-target="#add-contact-modal"></a>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
<div class="message chat-msg {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}">
|
||||
<span class="chat-msg-author chat-msg-{{{o.sender}}}">{{{o.pretty_time}}} {{{o.username}}}: </span>
|
||||
<div class="spoiler-hint">{{{o.spoiler_hint}}}</div>
|
||||
<a class="toggle-spoiler" data-toggle-state="closed" href="#"><i class="fa fa-eye"></li>{{{o.label_show}}}</a>
|
||||
<div class="chat-msg-content spoiler collapsed"><!-- message gets added here via renderMessage --></div>
|
||||
<img alt="User Avatar" class="avatar" height="36px" width="36px" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
|
||||
<div class="chat-msg-content">
|
||||
<span class="chat-msg-heading">
|
||||
<span class="chat-msg-author">{{{o.username}}}</span>
|
||||
<span class="chat-msg-time text-muted">{{{o.pretty_time}}}</span>
|
||||
</span>
|
||||
<div>
|
||||
<span class="spoiler-hint">{{{o.spoiler_hint}}}</span>
|
||||
<a class="badge badge-info spoiler-toggle" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>{{{o.label_show}}}</a>
|
||||
</div>
|
||||
<div class="chat-msg-text spoiler collapsed"><!-- message gets added here via renderMessage --></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -218,30 +218,32 @@
|
|||
return text;
|
||||
};
|
||||
|
||||
u.renderImageURLs = function (obj) {
|
||||
u.renderImageURLs = function (_converse, obj) {
|
||||
/* Returns a Promise which resolves once all images have been loaded.
|
||||
*/
|
||||
const { __ } = _converse;
|
||||
const list = obj.textContent.match(URL_REGEX) || [];
|
||||
return Promise.all(
|
||||
_.map(list, (url) =>
|
||||
new Promise((resolve, reject) =>
|
||||
isImage(url).then(function (img) {
|
||||
// XXX: need to create a new image, otherwise the event
|
||||
// listener doesn't fire
|
||||
const i = new Image();
|
||||
i.className = 'chat-image';
|
||||
i.src = img.src;
|
||||
i.addEventListener('load', resolve);
|
||||
// We also resolve for non-images, otherwise the
|
||||
// Promise.all resolves prematurely.
|
||||
i.addEventListener('error', resolve);
|
||||
var anchors = sizzle(`a[href="${url}"]`, obj);
|
||||
_.each(anchors, (a) => {
|
||||
a.replaceChild(i, a.firstChild);
|
||||
|
||||
_.each(sizzle(`a[href="${url}"]`, obj), (a) => {
|
||||
a.innerHTML = tpl_image({
|
||||
'url': url,
|
||||
'label_download': __('Download image file')
|
||||
})
|
||||
});
|
||||
}).catch(resolve)
|
||||
)
|
||||
))
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
u.renderFileURL = function (_converse, url) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user