Make icon generation more robust (#632)

* Make icon generation more robust

* Update packages/ui-shared/src/icons/polkadot.ts
This commit is contained in:
Jaco
2022-04-06 15:00:26 +02:00
committed by GitHub
parent fb360420e5
commit e598c7bb42
4 changed files with 39 additions and 12 deletions
@@ -4,15 +4,18 @@
import type { Props } from '../types';
import * as jdenticon from 'jdenticon';
import React from 'react';
import React, { useMemo } from 'react';
function Identicon ({ className = '', publicKey, size, style }: Props): React.ReactElement<Props> {
const html = useMemo(
() => ({ __html: jdenticon.toSvg(publicKey.substr(2), size) }),
[publicKey, size]
);
return (
<div
className={className}
dangerouslySetInnerHTML={{
__html: jdenticon.toSvg(publicKey.substr(2), size)
}}
dangerouslySetInnerHTML={html}
style={style}
/>
);
@@ -19,7 +19,7 @@
import type { Circle } from '@polkadot/ui-shared/icons/types';
import type { Props } from '../types';
import React from 'react';
import React, { useMemo } from 'react';
import { polkadotIcon } from '@polkadot/ui-shared';
@@ -36,6 +36,11 @@ function renderCircle ({ cx, cy, fill, r }: Circle, key: number): React.ReactNod
}
function Identicon ({ address, className = '', isAlternative = false, size, style }: Props): React.ReactElement<Props> {
const circles = useMemo(
() => polkadotIcon(address, { isAlternative }),
[address, isAlternative]
);
return (
<svg
className={className}
@@ -46,7 +51,7 @@ function Identicon ({ address, className = '', isAlternative = false, size, styl
viewBox='0 0 64 64'
width={size}
>
{polkadotIcon(address, { isAlternative }).map(renderCircle)}
{circles.map(renderCircle)}
</svg>
);
}
@@ -4,7 +4,7 @@
import type { Circle as CircleType } from '@polkadot/ui-shared/icons/types';
import type { Props } from '../types';
import React from 'react';
import React, { useMemo } from 'react';
import { View } from 'react-native';
import Svg, { Circle as SvgCircle } from 'react-native-svg';
@@ -23,6 +23,11 @@ function renderCircle ({ cx, cy, fill, r }: CircleType, key: number): React.Reac
}
export default function Identicon ({ address, isAlternative = false, size }: Props): React.ReactElement<Props> {
const circles = useMemo(
() => polkadotIcon(address, { isAlternative }),
[address, isAlternative]
);
return (
<View>
<Svg
@@ -31,7 +36,7 @@ export default function Identicon ({ address, isAlternative = false, size }: Pro
viewBox='0 0 64 64'
width={size}
>
{polkadotIcon(address, { isAlternative }).map(renderCircle)}
{circles.map(renderCircle)}
</Svg>
</View>
);
+18 -4
View File
@@ -22,7 +22,6 @@ const blake2 = (value: Uint8Array): Uint8Array =>
const S = 64;
const C = S / 2;
const Z = S / 64 * 5;
const ZERO = blake2(new Uint8Array(32));
/* eslint-disable sort-keys */
const SCHEMA: { [index: string]: Scheme } = {
@@ -43,6 +42,8 @@ const OUTER_CIRCLE: Circle = {
r: C
};
let zeroHash: Uint8Array = new Uint8Array();
function getRotation (isSixPoint: boolean): { r: number; ro2: number; r3o4: number; ro4: number; rroot3o2: number; rroot3o4: number } {
const r = isSixPoint
? (C / 8 * 5)
@@ -98,7 +99,11 @@ function findScheme (d: number): Scheme {
}
function addressToId (address: string): Uint8Array {
return blake2(decodeAddress(address)).map((x, i): number => (x + 256 - ZERO[i]) % 256);
if (!zeroHash.length) {
zeroHash = blake2(new Uint8Array(32));
}
return blake2(decodeAddress(address)).map((x, i) => (x + 256 - zeroHash[i]) % 256);
}
function getColors (address: string): string[] {
@@ -132,10 +137,19 @@ function getColors (address: string): string[] {
* @description Generate a array of the circles that make up an identicon
*/
export function polkadotIcon (address: string, { isAlternative }: Options): Circle[] {
const colors = getColors(address);
const xy = getCircleXY(isAlternative);
let colors: string[];
try {
// in some cases, e.g. RN where crypto may not be initialized, chaos can
// happen when hashing, in these cases we just fill with a placeholder
colors = getColors(address);
} catch {
colors = new Array<string>(xy.length).fill('#ddd');
}
return [OUTER_CIRCLE].concat(
getCircleXY(isAlternative).map(([cx, cy], index): Circle => ({
xy.map(([cx, cy], index): Circle => ({
cx, cy, fill: colors[index], r: Z
}))
);