Merge pull request #2315 from jmoenig/cloud-enhancements

Updates to cloud.js
pull/89/head
Jens Mönig 2019-01-25 12:04:09 +01:00 zatwierdzone przez GitHub
commit 1601dffddc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
2 zmienionych plików z 98 dodań i 91 usunięć

Wyświetl plik

@ -28,10 +28,12 @@
*/
// Global settings /////////////////////////////////////////////////////
// cloud.js should be able to exist indepent of Snap!
// (The module date is included for simplicity, but is not needed elsewhere.)
/*global modules, SnapSerializer, nop, hex_sha512, DialogBoxMorph, Color,
normalizeCanvas*/
/*global modules, hex_sha512*/
modules = modules || {};
modules.cloud = '2019-January-17';
// Global stuff
@ -45,10 +47,14 @@ function Cloud() {
}
Cloud.prototype.init = function () {
this.url = this.determineCloudDomain();
this.urlBasePath = '/api/v1';
this.url = this.determineCloudDomain() + this.urlBasePath;
this.username = null;
};
// Projects larger than this are rejected.
Cloud.MAX_FILE_SIZE = 10 * 1024 * 1024;
Cloud.prototype.knownDomains = {
'Snap!Cloud' : 'https://cloud.snap.berkeley.edu',
'Snap!Cloud (cs10)' : 'https://snap-cloud.cs10.org',
@ -144,6 +150,8 @@ Cloud.prototype.genericError = function () {
throw new Error(Cloud.genericErrorMessage);
};
// Low level functionality
Cloud.prototype.request = function (
@ -249,7 +257,7 @@ Cloud.prototype.initSession = function (onSuccess) {
'POST',
'/init',
function () { myself.checkCredentials(onSuccess); },
nop,
function () {},
null,
true
);
@ -369,7 +377,6 @@ Cloud.prototype.changePassword = function (
onError,
'Could not change password'
);
};
Cloud.prototype.resetPassword = function (username, onSuccess, onError) {
@ -395,79 +402,19 @@ Cloud.prototype.resendVerification = function (username, onSuccess, onError) {
// Projects
Cloud.prototype.saveProject = function (ide, onSuccess, onError) {
Cloud.prototype.saveProject = function (projectName, body, onSuccess, onError) {
// Expects a body object with the following paramters:
// xml, media, thumbnail, remixID (optional), notes (optional)
var myself = this;
this.checkCredentials(
function (username) {
if (username) {
var xml = ide.serializer.serialize(ide.stage),
thumbnail = normalizeCanvas(
ide.stage.thumbnail(
SnapSerializer.prototype.thumbnailSize
)).toDataURL(),
body, mediaSize, size;
ide.serializer.isCollectingMedia = true;
body = {
notes: ide.projectNotes,
xml: xml,
media: ide.hasChangedMedia ?
ide.serializer.mediaXML(ide.projectName) : null,
thumbnail: thumbnail,
remixID: ide.stage.remixID
};
ide.serializer.isCollectingMedia = false;
ide.serializer.flushMedia();
mediaSize = body.media ? body.media.length : 0;
size = body.xml.length + mediaSize;
if (mediaSize > 10485760) {
new DialogBoxMorph().inform(
'Snap!Cloud - Cannot Save Project',
'The media inside this project exceeds 10 MB.\n' +
'Please reduce the size of costumes or sounds.\n',
ide.world(),
ide.cloudIcon(null, new Color(180, 0, 0))
);
throw new Error('Project media exceeds 10 MB size limit');
}
// check if serialized data can be parsed back again
try {
ide.serializer.parse(body.xml);
} catch (err) {
ide.showMessage(
'Serialization of program data failed:\n' + err
);
throw new Error(
'Serialization of program data failed:\n' + err
);
}
if (body.media !== null) {
try {
ide.serializer.parse(body.media);
} catch (err) {
ide.showMessage(
'Serialization of media failed:\n' + err
);
throw new Error(
'Serialization of media failed:\n' + err
);
}
}
ide.serializer.isCollectingMedia = false;
ide.serializer.flushMedia();
ide.showMessage(
'Uploading ' + Math.round(size / 1024) + ' KB...'
);
myself.request(
'POST',
'/projects/' +
encodeURIComponent(username) +
'/' +
encodeURIComponent(ide.projectName),
encodeURIComponent(projectName),
onSuccess,
onError,
'Project could not be saved',

Wyświetl plik

@ -5583,17 +5583,85 @@ IDE_Morph.prototype.logout = function () {
);
};
IDE_Morph.prototype.saveProjectToCloud = function (name) {
var myself = this;
if (name) {
this.showMessage('Saving project\nto the cloud...');
this.setProjectName(name);
this.cloud.saveProject(
this,
function () {myself.showMessage('saved.', 2); },
this.cloudError()
IDE_Morph.prototype.buildProjectRequest = function () {
var xml = this.serializer.serialize(this.stage),
thumbnail = normalizeCanvas(
this.stage.thumbnail(
SnapSerializer.prototype.thumbnailSize
)).toDataURL(),
body;
this.serializer.isCollectingMedia = true;
body = {
notes: this.projectNotes,
xml: xml,
media: this.hasChangedMedia ?
this.serializer.mediaXML(this.projectName) : null,
thumbnail: thumbnail,
remixID: this.stage.remixID
};
this.serializer.isCollectingMedia = false;
this.serializer.flushMedia();
return body;
}
IDE_Morph.prototype.verifyProject = function (body) {
// Ensure the project is less than 10MB and serializes correctly.
var encodedBody = JSON.stringify(body);
if (encodedBody.length > Cloud.MAX_FILE_SIZE) {
new DialogBoxMorph().inform(
'Snap!Cloud - Cannot Save Project',
'The media inside this project exceeds 10 MB.\n' +
'Please reduce the size of costumes or sounds.\n',
this.world(),
this.cloudIcon(null, new Color(180, 0, 0))
);
return false;
}
console.log(encodedBody.length)
// check if serialized data can be parsed back again
try {
this.serializer.parse(body.xml);
} catch (err) {
this.showMessage('Serialization of program data failed:\n' + err);
return false;
}
if (body.media !== null) {
try {
this.serializer.parse(body.media);
} catch (err) {
this.showMessage('Serialization of media failed:\n' + err);
return false;
}
}
this.serializer.isCollectingMedia = false;
this.serializer.flushMedia();
return encodedBody.length;
}
IDE_Morph.prototype.saveProjectToCloud = function (name) {
var myself = this, projectBody, projectSize;
if (name) {
this.setProjectName(name);
}
this.showMessage('Saving project\nto the cloud...');
projectBody = this.buildProjectRequest();
projectSize = this.verifyProject(projectBody);
if (!projectSize) {return; } // Invalid Projects don't return anything.
this.showMessage(
'Uploading ' + Math.round(projectSize / 1024) + ' KB...'
);
this.cloud.saveProject(
this.projectName,
projectBody,
function () {myself.showMessage('saved.', 2); },
this.cloudError()
);
};
IDE_Morph.prototype.exportProjectMedia = function (name) {
@ -5804,11 +5872,11 @@ IDE_Morph.prototype.getURL = function (url, callback, responseType) {
async = callback instanceof Function,
myself = this,
rsp;
if (async) {
request.responseType = responseType || 'text';
if (async) {
request.responseType = responseType || 'text';
}
rsp = (!async || request.responseType === 'text') ? 'responseText'
: 'response';
: 'response';
try {
request.open('GET', url, async);
if (async) {
@ -6627,16 +6695,8 @@ ProjectDialogMorph.prototype.saveProject = function () {
};
ProjectDialogMorph.prototype.saveCloudProject = function () {
var myself = this;
this.ide.showMessage('Saving project\nto the cloud...');
this.ide.cloud.saveProject(
this.ide,
function () {
myself.ide.source = 'cloud';
myself.ide.showMessage('saved.', 2);
},
this.ide.cloudError()
);
this.ide.source = 'cloud';
this.ide.saveProjectToCloud();
this.destroy();
};