Render identicons in notifications
Render an svg, then canvas, then data url. Fixes #325 // FREEBIE
This commit is contained in:
parent
3bd9108f6e
commit
0ebdf08ceb
4 changed files with 90 additions and 11 deletions
|
@ -87,9 +87,17 @@
|
|||
<div class='scrollable'></div>
|
||||
</div>
|
||||
</script>
|
||||
<script type='text/x-tmpl-mustache' id='identicon-svg'>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44">
|
||||
<circle cx="22" cy="22" r="22" fill="{{ color }}" />
|
||||
<text text-anchor="middle" fill="white" font-size="14px" x="22" y="22" baseline-shift="-4px">
|
||||
{{ content }}
|
||||
</text>
|
||||
</svg>
|
||||
</script>
|
||||
<script type='text/x-tmpl-mustache' id='avatar'>
|
||||
<span class='avatar {{#avatar.color }} color{{avatar.color}} {{/avatar.color}}'
|
||||
style='background-image: url("{{ avatar.url }}");'>
|
||||
<span class='avatar'
|
||||
style='background-image: url("{{ avatar.url }}"); background-color: {{ avatar.color }}'>
|
||||
{{ avatar.content }}
|
||||
</span>
|
||||
</script>
|
||||
|
@ -286,6 +294,7 @@
|
|||
<script type="text/javascript" src="js/views/window_controls_view.js"></script>
|
||||
<script type="text/javascript" src="js/views/inbox_view.js"></script>
|
||||
<script type="text/javascript" src="js/views/confirmation_dialog_view.js"></script>
|
||||
<script type="text/javascript" src="js/views/identicon_svg_view.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/background.js"></script>
|
||||
</head>
|
||||
|
|
|
@ -7,6 +7,24 @@
|
|||
|
||||
// TODO: Factor out private and group subclasses of Conversation
|
||||
|
||||
var COLORS = [
|
||||
"#EF5350", // red
|
||||
"#EC407A", // pink
|
||||
"#AB47BC", // purple
|
||||
"#7E57C2", // deep purple
|
||||
"#5C6BC0", // indigo
|
||||
"#2196F3", // blue
|
||||
"#03A9F4", // light blue
|
||||
"#00BCD4", // cyan
|
||||
"#009688", // teal
|
||||
"#4CAF50", // green
|
||||
"#7CB342", // light green
|
||||
"#FF9800", // orange
|
||||
"#FF5722", // deep orange
|
||||
"#FFB300", // amber
|
||||
"#607D8B", // blue grey
|
||||
];
|
||||
|
||||
Whisper.Conversation = Backbone.Model.extend({
|
||||
database: Whisper.Database,
|
||||
storeName: 'conversations',
|
||||
|
@ -219,6 +237,17 @@
|
|||
}
|
||||
},
|
||||
|
||||
getNotificationIcon: function() {
|
||||
return new Promise(function(resolve) {
|
||||
var avatar = this.getAvatar();
|
||||
if (avatar.url) {
|
||||
resolve(avatar.url);
|
||||
} else {
|
||||
resolve(new Whisper.IdenticonSVGView(avatar).getDataUrl());
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
updateAvatarUrl: function(silent) {
|
||||
this.revokeAvatarUrl();
|
||||
var avatar = this.get('avatar');
|
||||
|
@ -243,11 +272,11 @@
|
|||
} else if (this.isPrivate()) {
|
||||
var title = this.get('name');
|
||||
if (!title) {
|
||||
return { content: '#', color: 'gray' };
|
||||
return { content: '#', color: '#999999' };
|
||||
}
|
||||
var initials = title.trim()[0];
|
||||
return {
|
||||
color: 1 + (Math.abs(this.hashCode()) % 15),
|
||||
color: COLORS[Math.abs(this.hashCode()) % 15],
|
||||
content: initials
|
||||
};
|
||||
} else {
|
||||
|
|
|
@ -93,14 +93,16 @@
|
|||
var sender = ConversationController.create({id: message.get('source')});
|
||||
conversation.fetch().then(function() {
|
||||
sender.fetch().then(function() {
|
||||
var notification = new Notification(sender.getTitle(), {
|
||||
body: message.getDescription(),
|
||||
icon: sender.getAvatar().url,
|
||||
tag: conversation.id
|
||||
sender.getNotificationIcon().then(function(icon) {
|
||||
var notification = new Notification(sender.getTitle(), {
|
||||
body: message.getDescription(),
|
||||
icon: icon,
|
||||
tag: conversation.id
|
||||
});
|
||||
notification.onclick = function() {
|
||||
openConversation(conversation);
|
||||
};
|
||||
});
|
||||
notification.onclick = function() {
|
||||
openConversation(conversation);
|
||||
};
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
|
39
js/views/identicon_svg_view.js
Normal file
39
js/views/identicon_svg_view.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* vim: ts=4:sw=4:expandtab
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
window.Whisper = window.Whisper || {};
|
||||
|
||||
/*
|
||||
* Render an avatar identicon to an svg for use in a notification.
|
||||
*/
|
||||
Whisper.IdenticonSVGView = Whisper.View.extend({
|
||||
templateName: 'identicon-svg',
|
||||
initialize: function(options) {
|
||||
this.render_attributes = options;
|
||||
},
|
||||
getSVGUrl: function() {
|
||||
var html = this.render().$el.html();
|
||||
var svg = new Blob([html], {type: 'image/svg+xml;charset=utf-8'});
|
||||
return URL.createObjectURL(svg);
|
||||
},
|
||||
getDataUrl: function() {
|
||||
var svgurl = this.getSVGUrl();
|
||||
return new Promise(function(resolve) {
|
||||
var img = document.createElement('img');
|
||||
img.onload = function () {
|
||||
var canvas = loadImage.scale(img, {
|
||||
canvas: true, maxWidth: 44, maxHeight: 44
|
||||
});
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
URL.revokeObjectURL(svgurl);
|
||||
resolve(canvas.toDataURL("image/png"));
|
||||
};
|
||||
|
||||
img.src = svgurl;
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
Loading…
Reference in a new issue