// Theirs import React from 'react' import HTML5Backend from 'react-dnd-html5-backend' import { DragDropContext } from 'react-dnd' import domtoimage from 'dom-to-image' import ReadFileDropContainer, { DATA_URL, TEXT } from 'dropperx' // Ours import Page from '../components/Page' import Button from '../components/Button' import Dropdown from '../components/Dropdown' import BackgroundSelect from '../components/BackgroundSelect' import Settings from '../components/Settings' import Toolbar from '../components/Toolbar' import Overlay from '../components/Overlay' import Carbon from '../components/Carbon' import ArrowDown from '../components/svg/Arrowdown' import api from '../lib/api' import { THEMES, THEMES_HASH, LANGUAGES, LANGUAGE_MIME_HASH, LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, DEFAULT_LANGUAGE, DEFAULT_THEME, DEFAULT_EXPORT_SIZE, COLORS, EXPORT_SIZES, EXPORT_SIZES_HASH, DEFAULT_CODE, DEFAULT_BG_COLOR, DEFAULT_SETTINGS } from '../lib/constants' import { getQueryStringState, updateQueryString, serializeState } from '../lib/routing' import { getState, saveState } from '../lib/util' const saveButtonOptions = { button: true, color: '#c198fb', selected: { id: 'SAVE_IMAGE', name: 'Save Image' }, list: ['png', 'svg'].map(id => ({ id, name: id.toUpperCase() })) } class Editor extends React.Component { static async getInitialProps({ asPath, query }) { const path = removeQueryString(asPath.split('/').pop()) const queryParams = getQueryStringState(query) const initialState = Object.keys(queryParams).length ? queryParams : null try { // TODO fix this hack if (path.length >= 19 && path.indexOf('.') === -1) { const content = await api.getGist(path) return { content, initialState } } } catch (e) { console.log(e) } return { initialState } } constructor(props) { super(props) this.state = Object.assign( { ...DEFAULT_SETTINGS, uploading: false, code: props.content, _initialState: this.props.initialState }, this.props.initialState ) this.save = this.save.bind(this) this.upload = this.upload.bind(this) this.updateSetting = this.updateSetting.bind(this) this.updateCode = this.updateSetting.bind(this, 'code') this.updateAspectRatio = this.updateSetting.bind(this, 'aspectRatio') this.updateTitleBar = this.updateSetting.bind(this, 'titleBar') this.updateTheme = this.updateTheme.bind(this) this.updateLanguage = this.updateLanguage.bind(this) this.updateBackground = this.updateBackground.bind(this) this.resetDefaultSettings = this.resetDefaultSettings.bind(this) this.getCarbonImage = this.getCarbonImage.bind(this) this.onDrop = this.onDrop.bind(this) } componentDidMount() { // Load from localStorage instead of query params if (!this.state._initialState) { const state = getState(localStorage) if (state) { this.setState(state) } } } componentDidUpdate() { updateQueryString(this.state) const s = { ...this.state } delete s.code delete s.backgroundImage delete s.backgroundImageSelection saveState(localStorage, s) } getCarbonImage({ format } = { format: 'png' }) { //if safari, get image from api if ( navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1 && format === 'png' ) { const encodedState = serializeState(this.state) return api.image(encodedState) } const node = document.getElementById('export-container') const exportSize = (EXPORT_SIZES_HASH[this.state.exportSize] || DEFAULT_EXPORT_SIZE).value const config = { style: { transform: `scale(${exportSize})`, 'transform-origin': 'center', background: this.state.squaredImage ? this.state.backgroundColor : 'none' }, filter: n => (n.className ? String(n.className).indexOf('eliminateOnRender') < 0 : true), width: node.offsetWidth * exportSize, height: this.state.squaredImage ? node.offsetWidth * exportSize : node.offsetHeight * exportSize } return format.toLowerCase() === 'svg' ? domtoimage.toSvg(node, config) : domtoimage.toPng(node, config) } updateSetting(key, value) { this.setState({ [key]: value }) } save({ id: format = 'png' }) { this.getCarbonImage({ format }).then(dataUrl => { if (format === 'svg') { dataUrl = dataUrl.split(' ').join(' ') } const link = document.createElement('a') link.download = `carbon.${format}` link.href = dataUrl document.body.appendChild(link) link.click() link.remove() }) } resetDefaultSettings() { this.setState(DEFAULT_SETTINGS) localStorage.clear() } upload() { this.setState({ uploading: true }) this.getCarbonImage({ format: 'png' }) .then(api.tweet) .then(() => this.setState({ uploading: false })) .catch(err => { console.error(err) this.setState({ uploading: false }) }) } onDrop([file]) { if (isImage(file)) { this.setState({ backgroundImage: file.content, backgroundImageSelection: null, backgroundMode: 'image' }) } else { this.setState({ code: file.content, language: 'auto' }) } } updateTheme(theme) { this.updateSetting('theme', theme.id) } updateLanguage(language) { this.updateSetting('language', language.mime || language.mode) } updateBackground(changes, cb) { this.setState(changes, cb) } render() { return (
{({ isOver, canDrop }) => ( {this.state.code != null ? this.state.code : DEFAULT_CODE} )}
) } } function removeQueryString(str) { const qI = str.indexOf('?') return (qI >= 0 ? str.substr(0, qI) : str) .replace(//g, '>') .replace(/\//g, '/') } function isImage(file) { return file.type.split('/')[0] === 'image' } function readAs(file) { if (isImage(file)) { return DATA_URL } return TEXT } export default DragDropContext(HTML5Backend)(Editor)