diff --git a/plugins/avatars/avatars.js b/plugins/avatars/avatars.js index 501fdfae8..81a16b460 100644 --- a/plugins/avatars/avatars.js +++ b/plugins/avatars/avatars.js @@ -1,5 +1,39 @@ (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 ` + + ${txt} + `; + } + return ` + + `; + }; + const queue = [], avatars = new Map, @@ -26,7 +60,7 @@ (from.name?.split(/[^\p{L}]+/gu) || []).reduce((a, s) => a + (s[0] || ''), '') .slice(0,2) .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)))) ), addQueue = (msg, fn) => { diff --git a/plugins/avatars/identicon.js b/plugins/avatars/identicon.js index 59664ccbb..237c2e574 100644 --- a/plugins/avatars/identicon.js +++ b/plugins/avatars/identicon.js @@ -31,6 +31,8 @@ window.identiconSvg = (hash, txt) => { dy=".1em" dominant-baseline="middle" fill="#FFF">${txt} `; } else { + txt = ``; + const cell = Math.floor((size - ((Math.floor(size * margin)) * 2)) / 5), imargin = Math.floor((size - cell * 5) / 2), rectangles = [], diff --git a/plugins/avatars/images/empty-contact.png b/plugins/avatars/images/empty-contact.png deleted file mode 100644 index 4418810b8..000000000 Binary files a/plugins/avatars/images/empty-contact.png and /dev/null differ diff --git a/plugins/avatars/index.php b/plugins/avatars/index.php index 7e7eda1d6..f42c468f2 100644 --- a/plugins/avatars/index.php +++ b/plugins/avatars/index.php @@ -19,13 +19,9 @@ class AvatarsPlugin extends \RainLoop\Plugins\AbstractPlugin $this->addJs('avatars.js'); $this->addJsonHook('Avatar', 'DoAvatar'); $this->addPartHook('Avatar', 'ServiceAvatar'); - $identicon = $this->Config()->Get('plugin', 'identicon', 'identicon'); - if ('none' != $identicon) { - if ('jdenticon' === $this->Config()->Get('plugin', 'identicon', 'identicon')) { - $this->addJs('jdenticon.js'); - } else { - $this->addJs('identicon.js'); - } + $identicon = $this->Config()->Get('plugin', 'identicon', ''); + if ($identicon && \is_file(__DIR__ . "/{$identicon}.js")) { + $this->addJs("{$identicon}.js"); } // https://github.com/the-djmaze/snappymail/issues/714 $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) // ->SetAllowedInJs(true) ->SetDefaultValue([ - ['id' => 'identicon', 'name' => 'Name characters or squares'], - ['id' => 'jdenticon', 'name' => 'Triangles shape'], - ['id' => 'none', 'name' => 'none'] + ['id' => '', 'name' => 'Name characters else silhouette'], + ['id' => 'identicon', 'name' => 'Name characters else squares'], + ['id' => 'jdenticon', 'name' => 'Triangles shape'] ]) ->SetDescription('https://wikipedia.org/wiki/Identicon'), \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('/^(.+\\.)?(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) { $file = __DIR__ . "/images/{$service}.png"; if (\file_exists($file)) {