Moving link generation into FormActions

This commit is contained in:
Jeff Avallone 2019-01-13 10:53:07 -05:00
parent f41518bd92
commit 42a1788c52
4 changed files with 111 additions and 72 deletions

View File

@ -10,54 +10,6 @@ import Message from 'components/Message';
const toUrl = params => new URLSearchParams(params).toString();
const createSvgLink = async ({ svg }) => {
try {
const type = 'image/svg+xml';
const blob = new Blob([svg], { type });
return {
url: URL.createObjectURL(blob),
label: 'Download SVG',
filename: 'image.svg',
type
};
}
catch (e) {
console.error(e); // eslint-disable-line no-console
}
};
const createPngLink = async ({ svg, width, height }) => {
try {
const type = 'image/png';
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const loader = new Image();
loader.width = canvas.width = Number(width) * 2;
loader.height = canvas.height = Number(height) * 2;
await new Promise(resolve => {
loader.onload = resolve;
loader.src = 'data:image/svg+xml,' + encodeURIComponent(svg);
});
context.drawImage(loader, 0, 0, loader.width, loader.height);
const blob = await new Promise(resolve => canvas.toBlob(resolve, type));
return {
url: URL.createObjectURL(blob),
label: 'Download PNG',
filename: 'image.png',
type
};
}
catch (e) {
console.error(e); // eslint-disable-line no-console
}
};
class App extends React.PureComponent {
state = {
loading: false,
@ -134,15 +86,7 @@ class App extends React.PureComponent {
this.handleRender();
}
handleSvgMarkup = async ({ svg, width, height }) => {
if (svg !== this.state.svg) {
this.setState({
svg,
svgLink: await createSvgLink({ svg }),
pngLink: await createPngLink({ svg, width, height })
});
}
}
handleSvg = imageDetails => this.setState({ imageDetails });
render() {
const {
@ -154,8 +98,7 @@ class App extends React.PureComponent {
loading,
loadingError,
Render,
svgLink,
pngLink
imageDetails
} = this.state;
const formProps = {
@ -163,20 +106,19 @@ class App extends React.PureComponent {
syntax,
expr
};
const actions = {
permalinkUrl,
svgLink,
pngLink
const actionProps = {
imageDetails,
permalinkUrl
};
const renderProps = {
onRender: this.handleSvgMarkup,
onRender: this.handleSvg,
syntax,
expr
};
return <>
<Form { ...formProps }>
<FormActions { ...actions } />
{ Render && <FormActions { ...actionProps } /> }
</Form>
{ loading && <Loader /> }

View File

@ -74,7 +74,7 @@ Form.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]).isRequired
])
};
export default Form;

View File

@ -6,7 +6,99 @@ import LinkIcon from 'react-feather/dist/icons/link';
import style from './style.module.css';
const createSvgLink = async ({ svg }) => {
try {
const type = 'image/svg+xml';
const blob = new Blob([svg], { type });
return {
url: URL.createObjectURL(blob),
label: 'Download SVG',
filename: 'image.svg',
type
};
}
catch (e) {
console.error(e); // eslint-disable-line no-console
}
};
const createPngLink = async ({ svg, width, height }) => {
try {
const type = 'image/png';
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const loader = new Image();
loader.width = canvas.width = width * 2;
loader.height = canvas.height = height * 2;
await new Promise(resolve => {
loader.onload = resolve;
loader.src = 'data:image/svg+xml,' + encodeURIComponent(svg);
});
context.drawImage(loader, 0, 0, loader.width, loader.height);
const blob = await new Promise(resolve => canvas.toBlob(resolve, type));
return {
url: URL.createObjectURL(blob),
label: 'Download PNG',
filename: 'image.png',
type
};
}
catch (e) {
console.error(e); // eslint-disable-line no-console
}
};
class FormActions extends React.PureComponent {
state = {}
componentDidMount() {
const { imageDetails } = this.props;
if (!imageDetails) {
return;
}
if (imageDetails.svg) {
this.generateDownloadLinks();
}
}
componentDidUpdate(prevProps) {
const { imageDetails } = this.props;
const { imageDetails: prevImageDetails } = prevProps;
if (!imageDetails) {
return;
}
if (!prevImageDetails) {
this.generateDownloadLinks();
return;
}
if (imageDetails.svg !== prevImageDetails.svg
|| imageDetails.width !== prevImageDetails.width
|| imageDetails.height !== prevImageDetails.height) {
this.generateDownloadLinks();
return;
}
}
async generateDownloadLinks() {
const { imageDetails: { svg, width, height } } = this.props;
this.setState({
svgLink: await createSvgLink({ svg }),
pngLink: await createPngLink({ svg, width, height })
});
}
downloadLink({ url, filename, type, label }) {
return <li>
<a href={ url } download={ filename } type={ type }>
@ -17,10 +109,12 @@ class FormActions extends React.PureComponent {
render() {
const {
permalinkUrl,
permalinkUrl
} = this.props;
const {
svgLink,
pngLink
} = this.props;
} = this.state;
return <ul className={ style.actions }>
{ pngLink && this.downloadLink(pngLink) }
@ -34,8 +128,11 @@ class FormActions extends React.PureComponent {
FormActions.propTypes = {
permalinkUrl: PropTypes.string,
svgLink: PropTypes.object,
pngLink: PropTypes.object
imageDetails: PropTypes.shape({
svg: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number
})
};
export default FormActions;

View File

@ -16,8 +16,8 @@ class Render extends React.PureComponent {
const svg = this.svgContainer.current.querySelector('svg');
this.props.onRender({
svg: svg.outerHTML,
width: svg.getAttribute('width'),
height: svg.getAttribute('height')
width: Number(svg.getAttribute('width')),
height: Number(svg.getAttribute('height'))
});
}