mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Avatars use text or colored silhouette as defaults
This commit is contained in:
parent
f2aba8b11d
commit
bff88e9f6a
4 changed files with 43 additions and 14 deletions
|
|
@ -1,5 +1,39 @@
|
||||||
(rl => {
|
(rl => {
|
||||||
|
|
||||||
|
const size = 50;
|
||||||
|
|
||||||
|
window.identiconSvg = (hash, txt) => {
|
||||||
|
// color defaults to last 7 chars as hue at 70% saturation, 50% brightness
|
||||||
|
// hsl2rgb adapted from: https://gist.github.com/aemkei/1325937
|
||||||
|
let h = (parseInt(hash.substr(-7), 16) / 0xfffffff) * 6, s = 0.7, l = 0.5,
|
||||||
|
v = [
|
||||||
|
l += s *= l < .5 ? l : 1 - l,
|
||||||
|
l - h % 1 * s * 2,
|
||||||
|
l -= s *= 2,
|
||||||
|
l,
|
||||||
|
l + h % 1 * s,
|
||||||
|
l + s
|
||||||
|
],
|
||||||
|
m = txt ? 128 : 200,
|
||||||
|
color = 'rgb(' + [
|
||||||
|
v[ ~~h % 6 ] * m, // red
|
||||||
|
v[ (h | 16) % 6 ] * m, // green
|
||||||
|
v[ (h | 8) % 6 ] * m // blue
|
||||||
|
].map(Math.round).join(',') + ')';
|
||||||
|
|
||||||
|
if (txt) {
|
||||||
|
return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}px" height="${size}px" viewBox="0 0 ${size} ${size}" version="1.1">
|
||||||
|
<circle fill="${color}" width="${size}" height="${size}" cx="${size/2}" cy="${size/2}" r="${size/2}"/>
|
||||||
|
<text x="${size}%" y="${size}%" style="color:#FFF" alignment-baseline="middle" text-anchor="middle"
|
||||||
|
font-weight="bold" font-size="${Math.round(size*0.5)}"
|
||||||
|
dy=".1em" dominant-baseline="middle" fill="#FFF">${txt}</text>
|
||||||
|
</svg>`;
|
||||||
|
}
|
||||||
|
return `<svg version="1.1" width="412" height="412" viewBox="0 0 412 412" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="${color}" d="m 404.4267,343.325 c -5.439,-16.32 -15.298,-32.782 -29.839,-42.362 -27.979,-18.572 -60.578,-28.479 -92.099,-39.085 -7.604,-2.664 -15.33,-5.568 -22.279,-9.7 -6.204,-3.686 -8.533,-11.246 -9.974,-17.886 -0.636,-3.512 -1.026,-7.116 -1.228,-10.661 22.857,-31.267 38.019,-82.295 38.019,-124.136 0,-65.298 -36.896,-83.495 -82.402,-83.495 -45.515,0 -82.403,18.17 -82.403,83.468 0,43.338 16.255,96.5 40.489,127.383 -0.221,2.438 -0.511,4.876 -0.95,7.303 -1.444,6.639 -3.77,14.058 -9.97,17.743 -6.957,4.133 -14.682,6.756 -22.287,9.42 -31.520996,10.605 -64.118996,19.957 -92.090996,38.529 -14.549,9.58 -24.403,27.159 -29.838,43.479 -5.597,16.938 -7.88600003,37.917 -7.54100003,54.917 H 205.9917 411.9657 c 0.348,-16.999 -1.946,-37.978 -7.539,-54.917 z"/>
|
||||||
|
</svg>`;
|
||||||
|
};
|
||||||
|
|
||||||
const
|
const
|
||||||
queue = [],
|
queue = [],
|
||||||
avatars = new Map,
|
avatars = new Map,
|
||||||
|
|
@ -26,7 +60,7 @@
|
||||||
(from.name?.split(/[^\p{L}]+/gu) || []).reduce((a, s) => a + (s[0] || ''), '')
|
(from.name?.split(/[^\p{L}]+/gu) || []).reduce((a, s) => a + (s[0] || ''), '')
|
||||||
.slice(0,2)
|
.slice(0,2)
|
||||||
.toUpperCase(),
|
.toUpperCase(),
|
||||||
setIdenticon = (from, fn) => window.identiconSvg && hash(from.email).then(hash =>
|
setIdenticon = (from, fn) => hash(from.email).then(hash =>
|
||||||
fn('data:image/svg+xml;base64,' + btoa(window.identiconSvg(hash, fromChars(from))))
|
fn('data:image/svg+xml;base64,' + btoa(window.identiconSvg(hash, fromChars(from))))
|
||||||
),
|
),
|
||||||
addQueue = (msg, fn) => {
|
addQueue = (msg, fn) => {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ window.identiconSvg = (hash, txt) => {
|
||||||
dy=".1em" dominant-baseline="middle" fill="#FFF">${txt}</text>
|
dy=".1em" dominant-baseline="middle" fill="#FFF">${txt}</text>
|
||||||
</svg>`;
|
</svg>`;
|
||||||
} else {
|
} else {
|
||||||
|
txt = `<path fill="${color}" d="m 404.4267,343.325 c -5.439,-16.32 -15.298,-32.782 -29.839,-42.362 -27.979,-18.572 -60.578,-28.479 -92.099,-39.085 -7.604,-2.664 -15.33,-5.568 -22.279,-9.7 -6.204,-3.686 -8.533,-11.246 -9.974,-17.886 -0.636,-3.512 -1.026,-7.116 -1.228,-10.661 22.857,-31.267 38.019,-82.295 38.019,-124.136 0,-65.298 -36.896,-83.495 -82.402,-83.495 -45.515,0 -82.403,18.17 -82.403,83.468 0,43.338 16.255,96.5 40.489,127.383 -0.221,2.438 -0.511,4.876 -0.95,7.303 -1.444,6.639 -3.77,14.058 -9.97,17.743 -6.957,4.133 -14.682,6.756 -22.287,9.42 -31.520996,10.605 -64.118996,19.957 -92.090996,38.529 -14.549,9.58 -24.403,27.159 -29.838,43.479 -5.597,16.938 -7.88600003,37.917 -7.54100003,54.917 H 205.9917 411.9657 c 0.348,-16.999 -1.946,-37.978 -7.539,-54.917 z"/>`;
|
||||||
|
|
||||||
const cell = Math.floor((size - ((Math.floor(size * margin)) * 2)) / 5),
|
const cell = Math.floor((size - ((Math.floor(size * margin)) * 2)) / 5),
|
||||||
imargin = Math.floor((size - cell * 5) / 2),
|
imargin = Math.floor((size - cell * 5) / 2),
|
||||||
rectangles = [],
|
rectangles = [],
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 665 B |
|
|
@ -19,13 +19,9 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
$this->addJs('avatars.js');
|
$this->addJs('avatars.js');
|
||||||
$this->addJsonHook('Avatar', 'DoAvatar');
|
$this->addJsonHook('Avatar', 'DoAvatar');
|
||||||
$this->addPartHook('Avatar', 'ServiceAvatar');
|
$this->addPartHook('Avatar', 'ServiceAvatar');
|
||||||
$identicon = $this->Config()->Get('plugin', 'identicon', 'identicon');
|
$identicon = $this->Config()->Get('plugin', 'identicon', '');
|
||||||
if ('none' != $identicon) {
|
if ($identicon && \is_file(__DIR__ . "/{$identicon}.js")) {
|
||||||
if ('jdenticon' === $this->Config()->Get('plugin', 'identicon', 'identicon')) {
|
$this->addJs("{$identicon}.js");
|
||||||
$this->addJs('jdenticon.js');
|
|
||||||
} else {
|
|
||||||
$this->addJs('identicon.js');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// https://github.com/the-djmaze/snappymail/issues/714
|
// https://github.com/the-djmaze/snappymail/issues/714
|
||||||
$this->Config()->Get('plugin', 'delay', true) || $this->addHook('filter.json-response', 'FilterJsonResponse');
|
$this->Config()->Get('plugin', 'delay', true) || $this->addHook('filter.json-response', 'FilterJsonResponse');
|
||||||
|
|
@ -93,9 +89,9 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECT)
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECT)
|
||||||
// ->SetAllowedInJs(true)
|
// ->SetAllowedInJs(true)
|
||||||
->SetDefaultValue([
|
->SetDefaultValue([
|
||||||
['id' => 'identicon', 'name' => 'Name characters or squares'],
|
['id' => '', 'name' => 'Name characters else silhouette'],
|
||||||
['id' => 'jdenticon', 'name' => 'Triangles shape'],
|
['id' => 'identicon', 'name' => 'Name characters else squares'],
|
||||||
['id' => 'none', 'name' => 'none']
|
['id' => 'jdenticon', 'name' => 'Triangles shape']
|
||||||
])
|
])
|
||||||
->SetDescription('https://wikipedia.org/wiki/Identicon'),
|
->SetDescription('https://wikipedia.org/wiki/Identicon'),
|
||||||
\RainLoop\Plugins\Property::NewInstance('bimi')->SetLabel('Lookup BIMI')
|
\RainLoop\Plugins\Property::NewInstance('bimi')->SetLabel('Lookup BIMI')
|
||||||
|
|
@ -212,9 +208,6 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
'services/' . \preg_replace('/^.+\\.([^.]+\\.[^.]+)$/D', '$1', $sDomain),
|
'services/' . \preg_replace('/^.+\\.([^.]+\\.[^.]+)$/D', '$1', $sDomain),
|
||||||
'services/' . \preg_replace('/^(.+\\.)?(paypal\\.[a-z][a-z])$/D', 'paypal.com', $sDomain)
|
'services/' . \preg_replace('/^(.+\\.)?(paypal\\.[a-z][a-z])$/D', 'paypal.com', $sDomain)
|
||||||
];
|
];
|
||||||
if (!$this->Config()->Get('plugin', 'identicon', false)) {
|
|
||||||
$aServices[] = 'empty-contact'; // DATA_IMAGE_USER_DOT_PIC
|
|
||||||
}
|
|
||||||
foreach ($aServices as $service) {
|
foreach ($aServices as $service) {
|
||||||
$file = __DIR__ . "/images/{$service}.png";
|
$file = __DIR__ . "/images/{$service}.png";
|
||||||
if (\file_exists($file)) {
|
if (\file_exists($file)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue