Moves identicon svg to TS

This commit is contained in:
Josh Perez 2021-08-24 20:17:51 -04:00 committed by GitHub
parent 347f542ac0
commit e76f603233
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 111 additions and 129 deletions

View File

@ -132,15 +132,6 @@
<button class='finish' tabIndex='1'><span class='icon'></span></button>
</script>
<script type="text/x-tmpl-mustache" id="identicon-svg">
<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
<circle cx='50' cy='50' r='40' fill='{{ color }}' />
<text text-anchor='middle' fill='white' font-family='sans-serif' font-size='24px' x='50' y='50' baseline-shift='-8px'>
{{ content }}
</text>
</svg>
</script>
<script type="text/x-tmpl-mustache" id="phone-number">
<div class='phone-input-form'>
<div class='number-container'>
@ -336,17 +327,12 @@
type="text/javascript"
src="ts/shims/showConfirmationDialog.js"
></script>
<script
type="text/javascript"
src="js/views/identicon_svg_view.js"
></script>
<script type="text/javascript" src="js/views/install_view.js"></script>
<script type="text/javascript" src="js/views/phone-input-view.js"></script>
<script
type="text/javascript"
src="js/views/standalone_registration_view.js"
></script>
<script type="text/javascript" src="js/views/clear_data_view.js"></script>
<script type="text/javascript" src="js/wall_clock_listener.js"></script>
<script

View File

@ -1,65 +0,0 @@
// Copyright 2015-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global Whisper, loadImage, $ */
// eslint-disable-next-line func-names
(function () {
window.Whisper = window.Whisper || {};
/*
* Render an avatar identicon to an svg for use in a notification.
*/
Whisper.IdenticonSVGView = Whisper.View.extend({
template: () => $('#identicon-svg').html(),
initialize(options) {
this.render_attributes = options;
this.render_attributes.color = COLORS[this.render_attributes.color];
},
getSVGUrl() {
const html = this.render().$el.html();
const svg = new Blob([html], { type: 'image/svg+xml;charset=utf-8' });
return URL.createObjectURL(svg);
},
getDataUrl() /* : Promise<string> */ {
const svgurl = this.getSVGUrl();
return new Promise(resolve => {
const img = document.createElement('img');
img.onload = () => {
const canvas = loadImage.scale(img, {
canvas: true,
maxWidth: 100,
maxHeight: 100,
});
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(svgurl);
resolve(canvas.toDataURL('image/png'));
};
img.onerror = () => {
URL.revokeObjectURL(svgurl);
// If this fails for some reason, we'd rather continue on than reject.
resolve(undefined);
};
img.src = svgurl;
});
},
});
const COLORS = {
blue: '#0a69c7',
burlap: '#866118',
crimson: '#d00b2c',
forest: '#067919',
indigo: '#5151f6',
plum: '#c70a88',
steel: '#077288',
taupe: '#cb0b6b',
teal: '#077288',
ultramarine: '#0d59f2',
vermilion: '#c72a0a',
violet: '#a20ced',
wintergreen: '#067953',
};
})();

View File

@ -114,15 +114,6 @@
<button class='close'><span class='icon'></span></button>
</script>
<script type="text/x-tmpl-mustache" id="identicon-svg">
<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
<circle cx='50' cy='50' r='40' fill='{{ color }}' />
<text text-anchor='middle' fill='white' font-family='sans-serif' font-size='24px' x='50' y='50' baseline-shift='-8px'>
{{ content }}
</text>
</svg>
</script>
<script type="text/x-tmpl-mustache" id="phone-number">
<div class='phone-input-form'>
<div class='number-container'>
@ -355,20 +346,11 @@
src="../js/views/inbox_view.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/identicon_svg_view.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/banner_view.js"
data-cover
></script>
<script
type="text/javascript"
src="../js/views/clear_data_view.js"
></script>
<script type="text/javascript" src="views/whisper_view_test.js"></script>
<script type="text/javascript" src="views/list_view_test.js"></script>

View File

@ -0,0 +1,21 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { storiesOf } from '@storybook/react';
import { IdenticonSVG } from './IdenticonSVG';
import { AvatarColorMap } from '../types/Colors';
const story = storiesOf('Components/IdenticonSVG', module);
AvatarColorMap.forEach((value, key) =>
story.add(key, () => (
<IdenticonSVG
backgroundColor={value.bg}
content="HI"
foregroundColor={value.fg}
/>
))
);

View File

@ -0,0 +1,33 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
export type PropsType = {
backgroundColor: string;
content: string;
foregroundColor: string;
};
export function IdenticonSVG({
backgroundColor,
content,
foregroundColor,
}: PropsType): JSX.Element {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<circle cx="50" cy="50" r="40" fill={backgroundColor} />
<text
baselineShift="-8px"
fill={foregroundColor}
fontFamily="sans-serif"
fontSize="24px"
textAnchor="middle"
x="50"
y="50"
>
{content}
</text>
</svg>
);
}

View File

@ -85,6 +85,7 @@ import { isAnnouncementGroupReady } from '../util/isAnnouncementGroupReady';
import { getProfile } from '../util/getProfile';
import { SEALED_SENDER } from '../types/SealedSender';
import { getAvatarData } from '../util/getAvatarData';
import { createIdenticon } from '../util/createIdenticon';
// TODO: remove once we move away from ArrayBuffers
const FIXMEU8 = Uint8Array;
@ -4963,14 +4964,11 @@ export class ConversationModel extends window.Backbone
return cached.url;
}
const fresh = await new window.Whisper.IdenticonSVGView({
color,
content,
}).getDataUrl();
const url = await createIdenticon(color, content);
this.cachedIdenticon = { content, color, url: fresh };
this.cachedIdenticon = { content, color, url };
return fresh;
return url;
}
notifyTyping(options: {

View File

@ -0,0 +1,53 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import loadImage from 'blueimp-load-image';
import { renderToString } from 'react-dom/server';
import { AvatarColorMap, AvatarColorType } from '../types/Colors';
import { IdenticonSVG } from '../components/IdenticonSVG';
export function createIdenticon(
color: AvatarColorType,
content: string
): Promise<string> {
const [defaultColorValue] = Array.from(AvatarColorMap.values());
const avatarColor = AvatarColorMap.get(color);
const html = renderToString(
<IdenticonSVG
backgroundColor={avatarColor?.bg || defaultColorValue.bg}
content={content}
foregroundColor={avatarColor?.fg || defaultColorValue.fg}
/>
);
const svg = new Blob([html], { type: 'image/svg+xml;charset=utf-8' });
const svgUrl = URL.createObjectURL(svg);
return new Promise(resolve => {
const img = document.createElement('img');
img.onload = () => {
const canvas = loadImage.scale(img, {
canvas: true,
maxWidth: 100,
maxHeight: 100,
});
if (!(canvas instanceof HTMLCanvasElement)) {
resolve('');
return;
}
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.drawImage(img, 0, 0);
}
URL.revokeObjectURL(svgUrl);
resolve(canvas.toDataURL('image/png'));
};
img.onerror = () => {
URL.revokeObjectURL(svgUrl);
resolve('');
};
img.src = svgUrl;
});
}

View File

@ -312,30 +312,6 @@
"updated": "2021-02-26T18:44:56.450Z",
"reasonDetail": "Static selector, read-only access"
},
{
"rule": "jQuery-$(",
"path": "js/views/identicon_svg_view.js",
"line": " template: () => $('#identicon-svg').html(),",
"reasonCategory": "usageTrusted",
"updated": "2021-02-26T18:44:56.450Z",
"reasonDetail": "Static selector, read-only access"
},
{
"rule": "jQuery-html(",
"path": "js/views/identicon_svg_view.js",
"line": " const html = this.render().$el.html();",
"reasonCategory": "usageTrusted",
"updated": "2018-09-15T00:38:04.183Z",
"reasonDetail": "Getting the value, not setting it"
},
{
"rule": "jQuery-html(",
"path": "js/views/identicon_svg_view.js",
"line": " template: () => $('#identicon-svg').html(),",
"reasonCategory": "usageTrusted",
"updated": "2021-02-26T18:44:56.450Z",
"reasonDetail": "Static selector, read-only access"
},
{
"rule": "jQuery-$(",
"path": "js/views/inbox_view.js",

2
ts/window.d.ts vendored
View File

@ -633,8 +633,6 @@ export type WhisperType = {
) => void;
};
IdenticonSVGView: WhatIsThis;
ExpiringMessagesListener: {
init: (events: Backbone.Events) => void;
update: () => void;