@@ -0,0 +1,61 @@
1+import React, { useRef } from 'react';
2+import * as ob from 'urbit-ob';
3+import { saveAs } from 'file-saver';
4+import { sigil, stringRenderer } from 'urbit-sigil-js';
5+
6+import { dataURItoBlob, loadImg, initCanvas } from 'lib/SigilDownloader';
7+
8+// const attachClickHandler = (children, handler) => Array.isArray(children) ? children.map((Child,key) => (<Child key={key} onClick={handler} />)) : (<children onClick={handler}>);
9+export default function SigilDownloader({ point, children }) {
10+ const downloadSigil = () => {
11+ const patp = ob.patp(point);
12+
13+ const _size = 1024 / window.devicePixelRatio;
14+ const pngSize = 1024;
15+
16+ const DATA_URI_PREFIX = 'data:image/svg+xml;base64,';
17+
18+ // initialize canvas element
19+ const canvas = initCanvas(canvasRef.current, { x: _size, y: _size });
20+ const ctx = canvas.getContext('2d');
21+
22+ // make sigil svg and encoded into base64
23+ const svg = sigil({
24+ patp,
25+ full: true,
26+ renderer: stringRenderer,
27+ size: _size,
28+ colors: ['#FFFFFF', '#000000'],
29+ margin: (54 / 256) * _size,
30+ });
31+
32+ // FF rendering hack
33+ const svgDocument = new DOMParser().parseFromString(svg, 'image/svg+xml');
34+ svgDocument.documentElement.width.baseVal.valueAsString = `${pngSize}px`;
35+ svgDocument.documentElement.height.baseVal.valueAsString = `${pngSize}px`;
36+ const svgText = new XMLSerializer().serializeToString(svgDocument);
37+ const svg64 = btoa(svgText);
38+
39+ const svgBlob = new Blob([svgText], { type: 'image/svg+xml' });
40+ saveAs(svgBlob, `${patp}.svg`);
41+
42+ const pngTask = loadImg(DATA_URI_PREFIX + svg64, _size, _size).then(img => {
43+ ctx.drawImage(img, 0, 0, _size, _size);
44+ const png = dataURItoBlob(canvas.toDataURL('image/png'));
45+ saveAs(png, `${patp}.png`);
46+ ctx.clearRect(0, 0, pngSize, pngSize);
47+ });
48+
49+ return pngTask;
50+ };
51+ const canvasRef = useRef(null);
52+
53+ return (
54+ <>
55+ {React.Children.map(children, child =>
56+ React.cloneElement(child, { onClick: downloadSigil })
57+ )}
58+ <canvas style={{ display: 'none' }} ref={canvasRef} />
59+ </>
60+ );
61+}