Switch avatar rendering from canvas to SVG.
This delegates the calculation of the aspect ratio to the browser, and generally simplifies the code. Fixes #1156.
This commit is contained in:
parent
352c0797ad
commit
ab5dd4a146
@ -9631,7 +9631,7 @@ body.reset {
|
||||
#conversejs div, #conversejs span, #conversejs h1, #conversejs h2, #conversejs h3, #conversejs h4, #conversejs h5, #conversejs h6, #conversejs p, #conversejs blockquote,
|
||||
#conversejs pre, #conversejs a, #conversejs em, #conversejs img, #conversejs strong, #conversejs dl, #conversejs dt, #conversejs dd, #conversejs ol, #conversejs ul, #conversejs li,
|
||||
#conversejs fieldset, #conversejs form, #conversejs legend, #conversejs table, #conversejs caption, #conversejs tbody,
|
||||
#conversejs tfoot, #conversejs thead, #conversejs tr, #conversejs th, #conversejs td, #conversejs article, #conversejs aside, #conversejs canvas, #conversejs details,
|
||||
#conversejs tfoot, #conversejs thead, #conversejs tr, #conversejs th, #conversejs td, #conversejs article, #conversejs aside, #conversejs details,
|
||||
#conversejs embed, #conversejs figure, #conversejs figcaption, #conversejs footer, #conversejs header, #conversejs hgroup, #conversejs menu,
|
||||
#conversejs nav, #conversejs output, #conversejs ruby, #conversejs section, #conversejs summary, #conversejs time, #conversejs mark, #conversejs audio, #conversejs video {
|
||||
margin: 0;
|
||||
@ -9669,7 +9669,7 @@ body.reset {
|
||||
color: var(--subdued-color); }
|
||||
#conversejs a.fa:hover, #conversejs a.far:hover, #conversejs a.fas:hover, #conversejs a:visited.fa:hover, #conversejs a:visited.far:hover, #conversejs a:visited.fas:hover, #conversejs a:not([href]):not([tabindex]).fa:hover, #conversejs a:not([href]):not([tabindex]).far:hover, #conversejs a:not([href]):not([tabindex]).fas:hover {
|
||||
color: var(--gray-color); }
|
||||
#conversejs canvas {
|
||||
#conversejs svg {
|
||||
border-radius: var(--chatbox-border-radius); }
|
||||
#conversejs .fa, #conversejs .far, #conversejs .fas {
|
||||
color: var(--subdued-color); }
|
||||
|
77
dist/converse.js
vendored
77
dist/converse.js
vendored
@ -58492,8 +58492,10 @@ __webpack_require__.r(__webpack_exports__);
|
||||
/* harmony import */ var backbone_overview__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! backbone.overview */ "./node_modules/backbone.overview/backbone.overview.js");
|
||||
/* harmony import */ var backbone_overview__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(backbone_overview__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @converse/headless/converse-core */ "./src/headless/converse-core.js");
|
||||
/* harmony import */ var templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! templates/chatboxes.html */ "./src/templates/chatboxes.html");
|
||||
/* harmony import */ var templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var templates_avatar_svg__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! templates/avatar.svg */ "./src/templates/avatar.svg");
|
||||
/* harmony import */ var templates_avatar_svg__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(templates_avatar_svg__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! templates/chatboxes.html */ "./src/templates/chatboxes.html");
|
||||
/* harmony import */ var templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_5__);
|
||||
// Converse.js
|
||||
// http://conversejs.org
|
||||
//
|
||||
@ -58504,6 +58506,7 @@ __webpack_require__.r(__webpack_exports__);
|
||||
|
||||
|
||||
|
||||
|
||||
const _converse$env = _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].env,
|
||||
Backbone = _converse$env.Backbone,
|
||||
_ = _converse$env._,
|
||||
@ -58519,27 +58522,12 @@ const AvatarMixin = {
|
||||
}
|
||||
|
||||
const image_type = this.model.vcard.get('image_type'),
|
||||
image = this.model.vcard.get('image'),
|
||||
img_src = "data:" + image_type + ";base64," + image,
|
||||
img = new Image();
|
||||
return new Promise((resolve, reject) => {
|
||||
img.onload = () => {
|
||||
const ctx = canvas_el.getContext('2d'),
|
||||
ratio = img.width / img.height;
|
||||
ctx.clearRect(0, 0, canvas_el.width, canvas_el.height);
|
||||
|
||||
if (ratio < 1) {
|
||||
const scaled_img_with = canvas_el.width * ratio,
|
||||
x = Math.floor((canvas_el.width - scaled_img_with) / 2);
|
||||
ctx.drawImage(img, x, 0, scaled_img_with, canvas_el.height);
|
||||
} else {
|
||||
ctx.drawImage(img, 0, 0, canvas_el.width, canvas_el.height * ratio);
|
||||
}
|
||||
|
||||
resolve();
|
||||
};
|
||||
|
||||
img.src = img_src;
|
||||
image = this.model.vcard.get('image');
|
||||
canvas_el.outerHTML = templates_avatar_svg__WEBPACK_IMPORTED_MODULE_4___default()({
|
||||
'classes': canvas_el.getAttribute('class'),
|
||||
'width': canvas_el.width,
|
||||
'height': canvas_el.height,
|
||||
'image': "data:" + image_type + ";base64," + image
|
||||
});
|
||||
}
|
||||
|
||||
@ -58618,11 +58606,11 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
|
||||
|
||||
render() {
|
||||
try {
|
||||
this.el.innerHTML = templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_4___default()();
|
||||
this.el.innerHTML = templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_5___default()();
|
||||
} catch (e) {
|
||||
this._ensureElement();
|
||||
|
||||
this.el.innerHTML = templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_4___default()();
|
||||
this.el.innerHTML = templates_chatboxes_html__WEBPACK_IMPORTED_MODULE_5___default()();
|
||||
}
|
||||
|
||||
this.row_el = this.el.querySelector('.row');
|
||||
@ -61766,14 +61754,13 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||
msg_content.innerHTML = _.flow(_.partial(utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].geoUriToHttp, _, _converse.geouri_replacement), _.partial(utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].addMentionsMarkup, _, this.model.get('references'), this.model.collection.chatbox), utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].addHyperlinks, utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].renderNewLines, _.partial(utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].addEmoji, _converse, _))(text);
|
||||
}
|
||||
|
||||
const promises = [];
|
||||
promises.push(utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].renderImageURLs(_converse, msg_content));
|
||||
const promise = utils_emoji__WEBPACK_IMPORTED_MODULE_8__["default"].renderImageURLs(_converse, msg_content);
|
||||
|
||||
if (this.model.get('type') !== 'headline') {
|
||||
promises.push(this.renderAvatar(msg));
|
||||
this.renderAvatar(msg);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
await promise;
|
||||
this.replaceElement(msg);
|
||||
this.model.collection.trigger('rendered', this);
|
||||
},
|
||||
@ -100974,6 +100961,34 @@ return __p
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/templates/avatar.svg":
|
||||
/*!**********************************!*\
|
||||
!*** ./src/templates/avatar.svg ***!
|
||||
\**********************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
|
||||
module.exports = function(o) {
|
||||
var __t, __p = '', __e = _.escape;
|
||||
__p += '<!-- src/templates/avatar.svg -->\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="' +
|
||||
__e(o.classes) +
|
||||
'" width="' +
|
||||
__e(o.width) +
|
||||
'" height="' +
|
||||
__e(o.height) +
|
||||
'">\n <image width="' +
|
||||
__e(o.width) +
|
||||
'" height="' +
|
||||
__e(o.height) +
|
||||
'" preserveAspectRatio="xMidYMid meet" xlink:href="' +
|
||||
__e(o.image) +
|
||||
'"/>\n</svg>\n';
|
||||
return __p
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/templates/bookmark.html":
|
||||
/*!*************************************!*\
|
||||
!*** ./src/templates/bookmark.html ***!
|
||||
@ -102892,7 +102907,7 @@ __e(o.image) +
|
||||
} ;
|
||||
__p += '\n ';
|
||||
if (!o.image) { ;
|
||||
__p += '\n <canvas class="avatar" height="100px" width="100px"/>\n ';
|
||||
__p += '\n <canvas class="avatar" height="100px" width="100px"></canvas>\n ';
|
||||
} ;
|
||||
__p += '\n </a>\n <input class="hidden" name="image" type="file">\n </div>\n <div class="col">\n <div class="form-group">\n <label class="col-form-label">' +
|
||||
__e(o.label_jid) +
|
||||
@ -102989,7 +103004,7 @@ var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./no
|
||||
module.exports = function(o) {
|
||||
var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
|
||||
function print() { __p += __j.call(arguments, '') }
|
||||
__p += '<!-- src/templates/profile_view.html -->\n<div class="userinfo controlbox-padded">\n<div class="controlbox-section profile d-flex">\n <a class="show-profile" href="#">\n <canvas alt="o.__(\'Your avatar\')" class="avatar align-self-center" height="40" width="40"></canvas>\n </a>\n <span class="username w-100 align-self-center">' +
|
||||
__p += '<!-- src/templates/profile_view.html -->\n<div class="userinfo controlbox-padded">\n<div class="controlbox-section profile d-flex">\n <a class="show-profile" href="#">\n <canvas class="avatar align-self-center" height="40" width="40"></canvas>\n </a>\n <span class="username w-100 align-self-center">' +
|
||||
__e(o.fullname) +
|
||||
'</span>\n <a class="controlbox-heading__btn show-client-info fa fa-info-circle align-self-center" title="' +
|
||||
__e(o.info_details) +
|
||||
|
@ -196,7 +196,7 @@ body.reset {
|
||||
div, span, h1, h2, h3, h4, h5, h6, p, blockquote,
|
||||
pre, a, em, img, strong, dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, legend, table, caption, tbody,
|
||||
tfoot, thead, tr, th, td, article, aside, canvas, details,
|
||||
tfoot, thead, tr, th, td, article, aside, details,
|
||||
embed, figure, figcaption, footer, header, hgroup, menu,
|
||||
nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
margin: 0;
|
||||
@ -254,7 +254,7 @@ body.reset {
|
||||
}
|
||||
}
|
||||
|
||||
canvas {
|
||||
svg {
|
||||
border-radius: var(--chatbox-border-radius);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import "@converse/headless/converse-chatboxes";
|
||||
import "backbone.nativeview";
|
||||
import "backbone.overview";
|
||||
import converse from "@converse/headless/converse-core";
|
||||
import tpl_avatar from "templates/avatar.svg";
|
||||
import tpl_chatboxes from "templates/chatboxes.html";
|
||||
|
||||
const { Backbone, _, utils } = converse.env;
|
||||
@ -22,25 +23,13 @@ const AvatarMixin = {
|
||||
return;
|
||||
}
|
||||
const image_type = this.model.vcard.get('image_type'),
|
||||
image = this.model.vcard.get('image'),
|
||||
img_src = "data:" + image_type + ";base64," + image,
|
||||
img = new Image();
|
||||
image = this.model.vcard.get('image');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
img.onload = () => {
|
||||
const ctx = canvas_el.getContext('2d'),
|
||||
ratio = img.width / img.height;
|
||||
ctx.clearRect(0, 0, canvas_el.width, canvas_el.height);
|
||||
if (ratio < 1) {
|
||||
const scaled_img_with = canvas_el.width*ratio,
|
||||
x = Math.floor((canvas_el.width-scaled_img_with)/2);
|
||||
ctx.drawImage(img, x, 0, scaled_img_with, canvas_el.height);
|
||||
} else {
|
||||
ctx.drawImage(img, 0, 0, canvas_el.width, canvas_el.height*ratio);
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
img.src = img_src;
|
||||
canvas_el.outerHTML = tpl_avatar({
|
||||
'classes': canvas_el.getAttribute('class'),
|
||||
'width': canvas_el.width,
|
||||
'height': canvas_el.height,
|
||||
'image': "data:" + image_type + ";base64," + image,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -155,12 +155,11 @@ converse.plugins.add('converse-message-view', {
|
||||
_.partial(u.addEmoji, _converse, _)
|
||||
)(text);
|
||||
}
|
||||
const promises = [];
|
||||
promises.push(u.renderImageURLs(_converse, msg_content));
|
||||
const promise = u.renderImageURLs(_converse, msg_content);
|
||||
if (this.model.get('type') !== 'headline') {
|
||||
promises.push(this.renderAvatar(msg));
|
||||
this.renderAvatar(msg);
|
||||
}
|
||||
await Promise.all(promises);
|
||||
await promise;
|
||||
this.replaceElement(msg);
|
||||
this.model.collection.trigger('rendered', this);
|
||||
},
|
||||
|
3
src/templates/avatar.svg
Normal file
3
src/templates/avatar.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="{{{o.classes}}}" width="{{{o.width}}}" height="{{{o.height}}}">
|
||||
<image width="{{{o.width}}}" height="{{{o.height}}}" preserveAspectRatio="xMidYMid meet" xlink:href="{{{o.image}}}"/>
|
||||
</svg>
|
After Width: | Height: | Size: 283 B |
@ -26,7 +26,7 @@
|
||||
<img alt="{{{o.alt_avatar}}}" class="img-thumbnail avatar align-self-center" height="100px" width="100px" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
|
||||
{[ } ]}
|
||||
{[ if (!o.image) { ]}
|
||||
<canvas class="avatar" height="100px" width="100px"/>
|
||||
<canvas class="avatar" height="100px" width="100px"></canvas>
|
||||
{[ } ]}
|
||||
</a>
|
||||
<input class="hidden" name="image" type="file">
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="userinfo controlbox-padded">
|
||||
<div class="controlbox-section profile d-flex">
|
||||
<a class="show-profile" href="#">
|
||||
<canvas alt="o.__('Your avatar')" class="avatar align-self-center" height="40" width="40"></canvas>
|
||||
<canvas class="avatar align-self-center" height="40" width="40"></canvas>
|
||||
</a>
|
||||
<span class="username w-100 align-self-center">{{{o.fullname}}}</span>
|
||||
<a class="controlbox-heading__btn show-client-info fa fa-info-circle align-self-center" title="{{{o.info_details}}}"></a>
|
||||
|
@ -36,7 +36,7 @@ const config = {
|
||||
use: "exports-loader?filterXSS,filterCSS"
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
test: /\.(html|svg)$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'lodash-template-webpack-loader',
|
||||
|
Loading…
Reference in New Issue
Block a user