From 2812720be6d24d81cf0b0d94d53a50b20cfe3126 Mon Sep 17 00:00:00 2001
From: Ray Schamp <ray@scratch.mit.edu>
Date: Mon, 10 Dec 2018 18:21:28 -0500
Subject: [PATCH] Manually save using xhr

Resolves #3950.

Unfortunately the design of scratch-storage doesn't make having multiple distinct POST urls easy at the moment. So for the time being, just make this request ourselves.
---
 src/lib/project-saver-hoc.jsx | 51 +++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 11 deletions(-)

diff --git a/src/lib/project-saver-hoc.jsx b/src/lib/project-saver-hoc.jsx
index df1dce40d..744316abc 100644
--- a/src/lib/project-saver-hoc.jsx
+++ b/src/lib/project-saver-hoc.jsx
@@ -1,8 +1,10 @@
 import bindAll from 'lodash.bindall';
 import React from 'react';
 import PropTypes from 'prop-types';
+import queryString from 'query-string';
 import {connect} from 'react-redux';
 import VM from 'scratch-vm';
+import xhr from 'xhr';
 
 import log from '../lib/log';
 import storage from '../lib/storage';
@@ -209,18 +211,45 @@ const ProjectSaverHOC = function (WrappedComponent) {
                     )
                 )
             ).then(() => {
-                const body = new FormData();
-                const sb3Json = new Blob([this.props.vm.toJSON()], {type: 'application/json'});
-                body.append('sb3_file', sb3Json, 'sb3_file');
-                for (const key in requestParams) {
-                    if (requestParams.hasOwnProperty(key)) body.append(key, requestParams[key]);
+                const opts = {
+                    body: this.props.vm.toJSON(),
+                    // If we set json:true then the body is double-stringified, so don't
+                    headers: {
+                        'Content-Type': 'application/json'
+                    },
+                    withCredentials: true
+                };
+                const creatingProject = projectId === null || typeof projectId === 'undefined';
+                let qs = queryString.stringify(requestParams);
+                if (qs) qs = `?${qs}`;
+                if (creatingProject) {
+                    Object.assign(opts, {
+                        method: 'post',
+                        url: `${storage.projectHost}/${qs}`
+                    });
+                } else {
+                    Object.assign(opts, {
+                        method: 'put',
+                        url: `${storage.projectHost}/${projectId}${qs}`
+                    });
                 }
-                return storage.store(
-                    storage.AssetType.Project,
-                    storage.DataFormat.JSON,
-                    body,
-                    projectId
-                );
+                return new Promise((resolve, reject) => {
+                    xhr(opts, (err, response) => {
+                        if (err) return reject(err);
+                        let body;
+                        try {
+                            // Since we didn't set json: true, we have to parse manually
+                            body = JSON.parse(response.body);
+                        } catch (e) {
+                            return reject(e);
+                        }
+                        body.id = projectId;
+                        if (creatingProject) {
+                            body.id = body['content-name'];
+                        }
+                        resolve(body);
+                    });
+                });
             })
                 .then(response => {
                     this.props.onSetProjectUnchanged();
-- 
GitLab