Moves identicon svg to TS
This commit is contained in:
parent
347f542ac0
commit
e76f603233
9 changed files with 111 additions and 129 deletions
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
})();
|
|
@ -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>
|
||||
|
|
21
ts/components/IdenticonSVG.stories.tsx
Normal file
21
ts/components/IdenticonSVG.stories.tsx
Normal 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}
|
||||
/>
|
||||
))
|
||||
);
|
33
ts/components/IdenticonSVG.tsx
Normal file
33
ts/components/IdenticonSVG.tsx
Normal 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>
|
||||
);
|
||||
}
|
|
@ -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: {
|
||||
|
|
53
ts/util/createIdenticon.tsx
Normal file
53
ts/util/createIdenticon.tsx
Normal 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;
|
||||
});
|
||||
}
|
|
@ -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
2
ts/window.d.ts
vendored
|
@ -633,8 +633,6 @@ export type WhisperType = {
|
|||
) => void;
|
||||
};
|
||||
|
||||
IdenticonSVGView: WhatIsThis;
|
||||
|
||||
ExpiringMessagesListener: {
|
||||
init: (events: Backbone.Events) => void;
|
||||
update: () => void;
|
||||
|
|
Loading…
Reference in a new issue