on df0c310 help sign in
bridge/src/lib/useSigilDownloader.js
58 lines 1.8 kB history raw
1import { useCallback } from 'react';
2import { saveAs } from 'file-saver';
3import { sigil, stringRenderer } from 'urbit-sigil-js';
4import * as ob from 'urbit-ob';
6import {
7 dataURItoBlob,
8 loadImg,
9 initCanvas,
10 cleanupCanvas,
11} from 'lib/SigilDownloader';
13export default function useSigilDownloader(canvasRef) {
14 const downloadSigil = useCallback(
15 (point, colors, size) => {
16 const patp = ob.patp(point);
18 const _size = size / window.devicePixelRatio;
20 const DATA_URI_PREFIX = 'data:image/svg+xml;base64,';
22 // initialize canvas element
23 const canvas = initCanvas(canvasRef.current, { x: _size, y: _size });
24 const ctx = canvas.getContext('2d');
26 // make sigil svg and encoded into base64
27 const svg = sigil({
28 patp,
29 renderer: stringRenderer,
30 size: _size,
31 colors,
32 margin: (54 / 256) * _size,
33 });
35 // FF rendering hack
36 const svgDocument = new DOMParser().parseFromString(svg, 'image/svg+xml');
37 svgDocument.documentElement.width.baseVal.valueAsString = `${size}px`;
38 svgDocument.documentElement.height.baseVal.valueAsString = `${size}px`;
39 const svgText = new XMLSerializer().serializeToString(svgDocument);
40 const svg64 = btoa(svgText);
42 return loadImg(DATA_URI_PREFIX + svg64, _size, _size)
43 .then(img => {
44 ctx.drawImage(img, 0, 0, _size, _size);
45 const png = dataURItoBlob(canvas.toDataURL('image/png'));
46 saveAs(png, `${patp.slice(1)}-sigil.png`);
47 ctx.clearRect(0, 0, _size, _size);
48 })
49 .catch(() => 'Error generating sigil')
50 .then(r => {
51 cleanupCanvas(canvasRef.current);
52 return r;
53 });
54 },
55 [canvasRef]
56 );
57 return { downloadSigil };