From da12939253e9c19dfdebd4e58a4b4fa9adb06958 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Wed, 14 Feb 2018 14:52:16 +0100 Subject: [PATCH] update fileformat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - don’t include images guides - don’t store sketch data and app version in object --- index.js | 3 +- src/components/App.js | 4 +- src/components/DoodlePreview.js | 4 +- src/constants/general.js | 2 +- src/shape/JSONToSketchData.js | 100 ++++++++++++++++++++------------ src/shape/docToFile.js | 3 +- src/shape/sketchDataToJSON.js | 77 ++++++++++++------------ 7 files changed, 111 insertions(+), 82 deletions(-) diff --git a/index.js b/index.js index ad7c7de..1d24e02 100644 --- a/index.js +++ b/index.js @@ -58,7 +58,8 @@ window.addEventListener('keydown',(event) => { // add model to store import modelData from './models/circle_error.d3sketch'; import JSONToSketchData from './src/shape/JSONToSketchData.js'; -JSONToSketchData(JSON.parse(modelData)).then(data => { +const { data, appVersion } = JSON.parse(modelData); +JSONToSketchData(data, appVersion).then(data => { store.dispatch(actions.openSketch({ data })); }); diff --git a/src/components/App.js b/src/components/App.js index 29f2c9d..a1f8dde 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -99,8 +99,8 @@ class App extends React.Component { case 'D3SKETCH': case 'JSON': const url = URL.createObjectURL(file); - const data = await fetch(url).then(result => result.json()); - const sketchData = await JSONToSketchData(data); + const { data, appVersion } = await fetch(url).then(result => result.json()); + const sketchData = await JSONToSketchData(data, appVersion); openSketch({ data: sketchData }); break; case 'JPG': diff --git a/src/components/DoodlePreview.js b/src/components/DoodlePreview.js index 4d1af00..d03c2ca 100644 --- a/src/components/DoodlePreview.js +++ b/src/components/DoodlePreview.js @@ -37,7 +37,7 @@ class DoodlePreview extends React.Component { sketchData: PropTypes.object, // TODO docData: PropTypes.shape({ appVersion: PropTypes.string, - data: PropTypes.string + data: PropTypes.oneOf([PropTypes.string, PropTypes.object]) }) }; @@ -48,7 +48,7 @@ class DoodlePreview extends React.Component { async componentWillMount() { let { docData, sketchData } = this.props; - if (docData) sketchData = await JSONToSketchData(this.props.docData); + if (docData) sketchData = await JSONToSketchData(docData.data, docData.appVersion); const { canvas } = this.refs; diff --git a/src/constants/general.js b/src/constants/general.js index 4f84533..27f13ec 100644 --- a/src/constants/general.js +++ b/src/constants/general.js @@ -1,6 +1,6 @@ import * as contextTools from './contextTools.js'; -export const VERSION = '0.17.4'; +export const VERSION = '0.18.0'; export const SHAPE_CACHE_LIMIT = 50; export const PIXEL_RATIO = 1.0; diff --git a/src/shape/JSONToSketchData.js b/src/shape/JSONToSketchData.js index 6d6b59d..8337a8e 100644 --- a/src/shape/JSONToSketchData.js +++ b/src/shape/JSONToSketchData.js @@ -5,47 +5,71 @@ import { recursivePromiseApply } from '../utils/async.js'; import { base64ToImage, base64ToVectorArray } from '../utils/binaryUtils.js'; import { LEGACY_HEIGHT_STEP } from '../constants/d3Constants.js'; -export default async function JSONToSketchData({ data, appVersion }) { - let sketchData = JSON.parse(data, (key, value) => { - if (semver.lt(appVersion, '0.1.2')) { - if (key === 'imageData') { +export function recursiveMap(objects, reviver) { + const newObjects = {}; + + for (const i in objects) { + if (!objects.hasOwnProperty(i)) continue; + + let object = objects[i]; + if (typeof object === 'object') { + object = recursiveMap(object, reviver); + } + object = reviver(i, object) || object; + newObjects[i] = object; + } + + return newObjects; +} + +function revive(appVersion, key, value) { + if (semver.lt(appVersion, '0.1.2')) { + if (key === 'imageData') { + return base64ToImage(value); + } + } + + if (value.metadata && value.metadata.type) { + switch (value.metadata.type) { + case 'Vector': + return new Vector().fromJSON(value); + + case 'Matrix': + return new Matrix().fromJSON(value); + + case 'VectorArray': + return base64ToVectorArray(value); + + case 'Image': return base64ToImage(value); - } + + case 'Matrix4': + return new Matrix4().copy(value); + + case 'Color': + return new Color(value.data).getHex(); + + default: + break; } - - if (value.metadata && value.metadata.type) { - switch (value.metadata.type) { - case 'Vector': - return new Vector().fromJSON(value); - - case 'Matrix': - return new Matrix().fromJSON(value); - - case 'VectorArray': - return base64ToVectorArray(value); - - case 'Image': - return base64ToImage(value); - - case 'Matrix4': - return new Matrix4().copy(value); - - case 'Color': - return new Color(value.data).getHex(); - - default: - break; - } - return value; - } - - // legacy, convert { r: Float, g: Float, b: Float } to hex - if (typeof value.r === 'number' && typeof value.g === 'number' && typeof value.b === 'number') { - return new Color(value.r, value.g, value.b).getHex(); - } - return value; - }); + } + + // legacy, convert { r: Float, g: Float, b: Float } to hex + if (typeof value.r === 'number' && typeof value.g === 'number' && typeof value.b === 'number') { + return new Color(value.r, value.g, value.b).getHex(); + } + + return value; +} + +export default async function JSONToSketchData(data, appVersion) { + let sketchData; + if (semver.gt(appVersion, '0.17.4')) { + sketchData = recursiveMap(data, (key, value) => revive(appVersion, key, value)); + } else { + sketchData = JSON.parse(data.data, (key, value) => revive(appVersion, key, value)); + } sketchData = await recursivePromiseApply(sketchData); if (semver.lt(appVersion, '0.4.0')) { diff --git a/src/shape/docToFile.js b/src/shape/docToFile.js index 5a26188..d7bdb34 100644 --- a/src/shape/docToFile.js +++ b/src/shape/docToFile.js @@ -26,7 +26,8 @@ export default async function docToFile(db, doc, { image = false, sketch = false throw new Error(`'${doc.name}' doesn't include sketch attachment`); } const data = await blobToJSON(doc._attachments.sketch.data); - response.data = await JSONToSketchData(data); + + response.data = await JSONToSketchData(data, appVersion); } else { const data = { data: doc.data, appVersion }; response.data = await JSONToSketchData(data); diff --git a/src/shape/sketchDataToJSON.js b/src/shape/sketchDataToJSON.js index cc2e4f6..2599a80 100644 --- a/src/shape/sketchDataToJSON.js +++ b/src/shape/sketchDataToJSON.js @@ -1,49 +1,55 @@ import { vectorArrayToBase64, imageToBase64 } from '../utils/binaryUtils.js'; -import { VERSION } from '../constants/general.js'; + +function createShapeData(shape) { + shape = { ...shape }; + delete shape.UID; + delete shape.space; + + switch (shape.type) { + case 'POLYGON': + case 'BRUSH': + case 'FREE_HAND': { + shape.points = vectorArrayToBase64(shape.points); + break; + } + + case 'COMPOUND_PATH': { + shape.points = vectorArrayToBase64(shape.points); + shape.holes = shape.holes.map(vectorArrayToBase64); + break; + } + + case 'IMAGE_GUIDE': { + shape.imageData = imageToBase64(shape.imageData); + break; + } + + default: { + break; + } + } + return shape; +} + export default function sketchDataToJSON({ objectsById, spaces }) { + const mapToShapes = id => objectsById[id]; + const filter = (shape) => { + if (shape.type === 'IMAGE_GUIDE') return false; + return true; + }; + const data = { spaces: [] }; - function createShapeData(id) { - const shape = { ...objectsById[id] }; - delete shape.UID; - delete shape.space; - - switch (shape.type) { - case 'POLYGON': - case 'BRUSH': - case 'FREE_HAND': { - shape.points = vectorArrayToBase64(shape.points); - break; - } - - case 'COMPOUND_PATH': { - shape.points = vectorArrayToBase64(shape.points); - shape.holes = shape.holes.map(vectorArrayToBase64); - break; - } - - case 'IMAGE_GUIDE': { - shape.imageData = imageToBase64(shape.imageData); - break; - } - - default: { - break; - } - } - return shape; - } - for (const spaceId in spaces) { const space = { matrix: { metadata: { type: 'Matrix4', library: 'three.js' }, elements: Array.from(spaces[spaceId].matrix.elements) }, - objects: spaces[spaceId].objectIds.map(createShapeData) + objects: spaces[spaceId].objectIds.map(mapToShapes).filter(filter).map(createShapeData) }; if (spaceId === 'world') { @@ -53,8 +59,5 @@ export default function sketchDataToJSON({ objectsById, spaces }) { } } - return { - data: JSON.stringify(data), - appVersion: VERSION - }; + return data; }