You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			125 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			125 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			TypeScript
		
	
import React from 'react';
 | 
						|
import { getInitials } from '../../util/getInitials';
 | 
						|
 | 
						|
interface Props {
 | 
						|
  diameter: number;
 | 
						|
  name: string;
 | 
						|
  pubkey?: string;
 | 
						|
  colors: Array<string>;
 | 
						|
  borderColor: string;
 | 
						|
}
 | 
						|
 | 
						|
interface State {
 | 
						|
  sha512Seed?: string;
 | 
						|
}
 | 
						|
 | 
						|
export class AvatarPlaceHolder extends React.PureComponent<Props, State> {
 | 
						|
  public constructor(props: Props) {
 | 
						|
    super(props);
 | 
						|
 | 
						|
    this.state = {
 | 
						|
      sha512Seed: undefined,
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  public componentDidMount() {
 | 
						|
    const { pubkey } = this.props;
 | 
						|
    if (pubkey) {
 | 
						|
      void this.sha512(pubkey).then((sha512Seed: string) => {
 | 
						|
        this.setState({ sha512Seed });
 | 
						|
      });
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  public componentDidUpdate(prevProps: Props, prevState: State) {
 | 
						|
    const { pubkey, name } = this.props;
 | 
						|
    if (pubkey === prevProps.pubkey && name === prevProps.name) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pubkey) {
 | 
						|
      void this.sha512(pubkey).then((sha512Seed: string) => {
 | 
						|
        this.setState({ sha512Seed });
 | 
						|
      });
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  public render() {
 | 
						|
    const { borderColor, colors, diameter, name } = this.props;
 | 
						|
    const diameterWithoutBorder = diameter - 2;
 | 
						|
    const viewBox = `0 0 ${diameter} ${diameter}`;
 | 
						|
    const r = diameter / 2;
 | 
						|
    const rWithoutBorder = diameterWithoutBorder / 2;
 | 
						|
 | 
						|
    if (!this.state.sha512Seed) {
 | 
						|
      // return grey circle
 | 
						|
      return (
 | 
						|
        <svg viewBox={viewBox}>
 | 
						|
          <g id="UrTavla">
 | 
						|
            <circle
 | 
						|
              cx={r}
 | 
						|
              cy={r}
 | 
						|
              r={rWithoutBorder}
 | 
						|
              fill="#d2d2d3"
 | 
						|
              shapeRendering="geometricPrecision"
 | 
						|
              stroke={borderColor}
 | 
						|
              strokeWidth="1"
 | 
						|
            />
 | 
						|
          </g>
 | 
						|
        </svg>
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    const initial = getInitials(name)?.toLocaleUpperCase() || '0';
 | 
						|
    const fontSize = diameter * 0.5;
 | 
						|
 | 
						|
    // Generate the seed simulate the .hashCode as Java
 | 
						|
    const hash = parseInt(this.state.sha512Seed.substring(0, 12), 16) || 0;
 | 
						|
 | 
						|
    const bgColorIndex = hash % colors.length;
 | 
						|
 | 
						|
    const bgColor = colors[bgColorIndex];
 | 
						|
 | 
						|
    return (
 | 
						|
      <svg viewBox={viewBox}>
 | 
						|
        <g id="UrTavla">
 | 
						|
          <circle
 | 
						|
            cx={r}
 | 
						|
            cy={r}
 | 
						|
            r={rWithoutBorder}
 | 
						|
            fill={bgColor}
 | 
						|
            shapeRendering="geometricPrecision"
 | 
						|
            stroke={borderColor}
 | 
						|
            strokeWidth="1"
 | 
						|
          />
 | 
						|
          <text
 | 
						|
            fontSize={fontSize}
 | 
						|
            x="50%"
 | 
						|
            y="50%"
 | 
						|
            fill="white"
 | 
						|
            textAnchor="middle"
 | 
						|
            stroke="white"
 | 
						|
            strokeWidth={1}
 | 
						|
            alignmentBaseline="central"
 | 
						|
          >
 | 
						|
            {initial}
 | 
						|
          </text>
 | 
						|
        </g>
 | 
						|
      </svg>
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  private async sha512(str: string) {
 | 
						|
    // tslint:disable-next-line: await-promise
 | 
						|
    const buf = await crypto.subtle.digest(
 | 
						|
      'SHA-512',
 | 
						|
      new TextEncoder().encode(str)
 | 
						|
    );
 | 
						|
 | 
						|
    // tslint:disable: prefer-template restrict-plus-operands
 | 
						|
    return Array.prototype.map
 | 
						|
      .call(new Uint8Array(buf), (x: any) => ('00' + x.toString(16)).slice(-2))
 | 
						|
      .join('');
 | 
						|
  }
 | 
						|
}
 |