Merge pull request #2008 from cycomachead/new-cloud

New cloud (Try 2)
upd4.2
Jens Mönig 2018-02-08 08:30:23 +01:00 zatwierdzone przez GitHub
commit 0a25625537
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
4 zmienionych plików z 804 dodań i 839 usunięć

1162
cloud.js

Plik diff jest za duży Load Diff

438
gui.js
Wyświetl plik

@ -241,6 +241,10 @@ IDE_Morph.prototype.init = function (isAutoFill) {
this.corralBar = null;
this.corral = null;
this.embedPlayButton = null;
this.embedOverlay = null;
this.isEmbedMode = false;
this.isAutoFill = isAutoFill === undefined ? true : isAutoFill;
this.isAppMode = false;
this.isSmallStage = false;
@ -268,20 +272,13 @@ IDE_Morph.prototype.init = function (isAutoFill) {
IDE_Morph.prototype.openIn = function (world) {
var hash, usr, myself = this, urlLanguage = null;
// get persistent user data, if any
if (this.hasLocalStorage()) {
usr = localStorage['-snap-user'];
if (usr) {
usr = SnapCloud.parseResponse(usr)[0];
if (usr) {
SnapCloud.username = usr.username || null;
SnapCloud.password = usr.password || null;
if (SnapCloud.username) {
this.source = 'cloud';
}
SnapCloud.initSession(
function (username) {
if (username) {
myself.source = 'cloud';
}
}
}
);
this.buildPanes();
world.add(this);
@ -328,7 +325,10 @@ IDE_Morph.prototype.openIn = function (world) {
}
}
function applyFlags(dict) {
function applyFlags(dict) {
if (dict.embedMode) {
myself.setEmbedMode();
}
if (dict.editMode) {
myself.toggleAppMode(false);
} else {
@ -344,7 +344,7 @@ IDE_Morph.prototype.openIn = function (world) {
if (dict.noExitWarning) {
window.onbeforeunload = nop;
}
}
}
// dynamic notifications from non-source text files
// has some issues, commented out for now
@ -405,7 +405,8 @@ IDE_Morph.prototype.openIn = function (world) {
dict.Username = dict.Username.toLowerCase();
SnapCloud.getPublicProject(
SnapCloud.encodeDict(dict),
dict.ProjectName,
dict.Username,
function (projectData) {
var msg;
myself.nextSteps([
@ -442,10 +443,10 @@ IDE_Morph.prototype.openIn = function (world) {
// make sure to lowercase the username
dict = SnapCloud.parseDict(location.hash.substr(7));
dict.Username = dict.Username.toLowerCase();
SnapCloud.getPublicProject(
SnapCloud.encodeDict(dict),
dict.ProjectName,
dict.Username,
function (projectData) {
var msg;
myself.nextSteps([
@ -478,10 +479,10 @@ IDE_Morph.prototype.openIn = function (world) {
// make sure to lowercase the username
dict = SnapCloud.parseDict(location.hash.substr(4));
dict.Username = dict.Username.toLowerCase();
SnapCloud.getPublicProject(
SnapCloud.encodeDict(dict),
dict.ProjectName,
dict.Username,
function (projectData) {
myself.saveXMLAs(projectData, dict.ProjectName);
myself.showMessage(
@ -1724,7 +1725,24 @@ IDE_Morph.prototype.fixLayout = function (situation) {
if (situation !== 'refreshPalette') {
// stage
if (this.isAppMode) {
if (this.isEmbedMode) {
this.stage.setScale(Math.floor(Math.min(
this.width() / this.stage.dimensions.x,
this.height() / this.stage.dimensions.y
) * 10) / 10);
this.embedPlayButton.size = Math.floor(Math.min(
this.width(), this.height())) / 3;
this.embedPlayButton.setWidth(this.embedPlayButton.size);
this.embedPlayButton.setHeight(this.embedPlayButton.size);
if (this.embedOverlay) {
this.embedOverlay.setExtent(this.extent());
}
this.stage.setCenter(this.center());
this.embedPlayButton.setCenter(this.center());
} else if (this.isAppMode) {
this.stage.setScale(Math.floor(Math.min(
(this.width() - padding * 2) / this.stage.dimensions.x,
(this.height() - this.controlBar.height() * 2 - padding * 2)
@ -2559,15 +2577,12 @@ IDE_Morph.prototype.cloudMenu = function () {
function () {
myself.prompt('Author name…', function (usr) {
myself.prompt('Project name...', function (prj) {
var id = 'Username=' +
encodeURIComponent(usr.toLowerCase()) +
'&ProjectName=' +
encodeURIComponent(prj);
myself.showMessage(
'Fetching project\nfrom the cloud...'
);
SnapCloud.getPublicProject(
id,
prj,
usr,
function (projectData) {
var msg;
if (!Process.prototype.isCatchingErrors) {
@ -4659,6 +4674,28 @@ IDE_Morph.prototype.toggleSliderExecute = function () {
!ArgMorph.prototype.executeOnSliderEdit;
};
IDE_Morph.prototype.setEmbedMode = function () {
var myself = this;
this.embedOverlay = new Morph();
this.embedOverlay.color = new Color(128, 128, 128);
this.embedOverlay.alpha = 0.5;
this.embedPlayButton = new SymbolMorph('pointRight');
this.embedPlayButton.color = new Color(128, 255, 128);
this.embedPlayButton.mouseClickLeft = function () {
myself.runScripts();
myself.embedOverlay.destroy();
this.destroy();
};
this.isEmbedMode = true;
this.controlBar.hide();
this.add(this.embedOverlay);
this.add(this.embedPlayButton);
this.fixLayout();
};
IDE_Morph.prototype.toggleAppMode = function (appMode) {
var world = this.world(),
elements = [
@ -5095,21 +5132,11 @@ IDE_Morph.prototype.initializeCloud = function () {
new DialogBoxMorph(
null,
function (user) {
var pwh = hex_sha512(user.password),
str;
SnapCloud.login(
user.username,
pwh,
user.password,
user.choice,
function () {
if (user.choice) {
str = SnapCloud.encodeDict(
{
username: user.username,
password: pwh
}
);
localStorage['-snap-user'] = str;
}
myself.source = 'cloud';
myself.showMessage('now connected.', 2);
},
@ -5133,23 +5160,20 @@ IDE_Morph.prototype.initializeCloud = function () {
IDE_Morph.prototype.createCloudAccount = function () {
var myself = this,
world = this.world();
/*
// force-logout, commented out for now:
delete localStorage['-snap-user'];
SnapCloud.clear();
*/
new DialogBoxMorph(
null,
function (user) {
SnapCloud.signup(
user.username,
user.password,
user.passwordRepeat,
user.email,
function (txt, title) {
new DialogBoxMorph().inform(
title,
txt +
'.\n\nAn e-mail with your password\n' +
'has been sent to the address provided',
'.\n\nYou can now log in.',
world,
myself.cloudIcon(null, new Color(0, 180, 0))
);
@ -5174,11 +5198,7 @@ IDE_Morph.prototype.createCloudAccount = function () {
IDE_Morph.prototype.resetCloudPassword = function () {
var myself = this,
world = this.world();
/*
// force-logout, commented out for now:
delete localStorage['-snap-user'];
SnapCloud.clear();
*/
new DialogBoxMorph(
null,
function (user) {
@ -5221,8 +5241,8 @@ IDE_Morph.prototype.changeCloudPassword = function () {
SnapCloud.changePassword(
user.oldpassword,
user.password,
user.passwordRepeat,
function () {
myself.logout();
myself.showMessage('password has been changed.', 2);
},
myself.cloudError()
@ -5244,14 +5264,11 @@ IDE_Morph.prototype.changeCloudPassword = function () {
IDE_Morph.prototype.logout = function () {
var myself = this;
delete localStorage['-snap-user'];
SnapCloud.logout(
function () {
SnapCloud.clear();
myself.showMessage('disconnected.', 2);
},
function () {
SnapCloud.clear();
myself.showMessage('disconnected.', 2);
}
);
@ -5735,6 +5752,12 @@ ProjectDialogMorph.prototype.buildContents = function () {
this.unshareButton = this.addButton('unshareProject', 'Unshare');
this.shareButton.hide();
this.unshareButton.hide();
/*
this.publishButton = this.addButton('publishProject', 'Publish');
this.unpublishButton = this.addButton('unpublishProject', 'Unpublish');
this.publishButton.hide();
this.unpublishButton.hide();
*/
this.deleteButton = this.addButton('deleteProject', 'Delete');
this.addButton('cancel', 'Cancel');
@ -5882,16 +5905,8 @@ ProjectDialogMorph.prototype.buildFilterField = function () {
myself.listField.elements =
myself.projectList.filter(function (aProject) {
var name,
notes;
if (aProject.ProjectName) { // cloud
name = aProject.ProjectName;
notes = aProject.Notes;
} else { // local or examples
name = aProject.name;
var name = aProject.projectname || aProject.name,
notes = aProject.notes || '';
}
return name.toLowerCase().indexOf(text.toLowerCase()) > -1 ||
notes.toLowerCase().indexOf(text.toLowerCase()) > -1;
@ -5925,10 +5940,10 @@ ProjectDialogMorph.prototype.setSource = function (source) {
msg = myself.ide.showMessage('Updating\nproject list...');
this.projectList = [];
SnapCloud.getProjectList(
function (projectList) {
function (response) {
// Don't show cloud projects if user has since switch panes.
if (myself.source === 'cloud') {
myself.installCloudProjectList(projectList);
myself.installCloudProjectList(response.projects);
}
msg.destroy();
},
@ -6019,6 +6034,10 @@ ProjectDialogMorph.prototype.setSource = function (source) {
this.body.add(this.listField);
this.shareButton.hide();
this.unshareButton.hide();
/*
this.publishButton.hide();
this.unpublishButton.hide();
*/
if (this.source === 'local') {
this.deleteButton.show();
} else { // examples
@ -6058,9 +6077,9 @@ ProjectDialogMorph.prototype.getExamplesProjectList = function () {
ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
var myself = this;
this.projectList = pl || [];
this.projectList = pl[0] ? pl : [];
this.projectList.sort(function (x, y) {
return x.ProjectName.toLowerCase() < y.ProjectName.toLowerCase() ?
return x.projectname.toLowerCase() < y.projectname.toLowerCase() ?
-1 : 1;
});
@ -6069,15 +6088,19 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
this.projectList,
this.projectList.length > 0 ?
function (element) {
return element.ProjectName || element;
return element.projectname || element;
} : null,
[ // format: display shared project names bold
[
'bold',
function (proj) {return proj.Public === 'true'; }
function (proj) { return proj.ispublic; }
],
[
'italic',
function (proj) { return proj.ispublished; }
]
],
function () {myself.ok(); }
function () { myself.ok(); }
);
this.fixListFieldItemColors();
this.listField.fixLayout = nop;
@ -6091,17 +6114,25 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
this.listField.action = function (item) {
if (item === undefined) {return; }
if (myself.nameField) {
myself.nameField.setContents(item.ProjectName || '');
myself.nameField.setContents(item.projectname || '');
}
if (myself.task === 'open') {
myself.notesText.text = item.Notes || '';
myself.notesText.text = item.notes || '';
myself.notesText.drawNew();
myself.notesField.contents.adjustBounds();
myself.preview.texture = item.Thumbnail || null;
myself.preview.cachedTexture = null;
myself.preview.texture = '';
myself.preview.drawNew();
// we ask for the thumbnail when selecting a project
SnapCloud.getThumbnail(
null, // username is implicit
item.projectname,
function (thumbnail) {
myself.preview.texture = thumbnail;
myself.preview.cachedTexture = null;
myself.preview.drawNew();
});
(new SpeechBubbleMorph(new TextMorph(
localize('last changed') + '\n' + item.Updated,
localize('last changed') + '\n' + item.lastupdated,
null,
null,
null,
@ -6112,12 +6143,25 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
myself.preview.rightCenter().add(new Point(2, 0))
);
}
if (item.Public === 'true') {
if (item.ispublic) {
myself.shareButton.hide();
myself.unshareButton.show();
/*
if (item.ispublished) {
myself.publishButton.hide();
myself.unpublishButton.show();
} else {
myself.publishButton.show();
myself.unpublishButton.hide();
}
*/
} else {
myself.unshareButton.hide();
myself.shareButton.show();
/*
myself.publishButton.hide();
myself.unpublishButton.hide();
*/
}
myself.buttons.fixLayout();
myself.fixLayout();
@ -6175,30 +6219,21 @@ ProjectDialogMorph.prototype.openCloudProject = function (project) {
ProjectDialogMorph.prototype.rawOpenCloudProject = function (proj) {
var myself = this;
SnapCloud.reconnect(
function () {
SnapCloud.callService(
'getRawProject',
function (response) {
SnapCloud.disconnect();
/*
if (myself.world().currentKey === 16) {
myself.ide.download(response);
return;
}
*/
myself.ide.source = 'cloud';
myself.ide.droppedText(response);
if (proj.Public === 'true') {
location.hash = '#present:Username=' +
encodeURIComponent(SnapCloud.username) +
'&ProjectName=' +
encodeURIComponent(proj.ProjectName);
}
},
myself.ide.cloudError(),
[proj.ProjectName]
);
SnapCloud.getProject(
proj.projectname,
function (clouddata) {
myself.ide.source = 'cloud';
myself.ide.nextSteps([
function () {
myself.ide.openCloudDataString(clouddata);
}
]);
if (proj.ispublic) {
location.hash = '#present:Username=' +
encodeURIComponent(SnapCloud.username) +
'&ProjectName=' +
encodeURIComponent(proj.projectname);
}
},
myself.ide.cloudError()
);
@ -6211,11 +6246,12 @@ ProjectDialogMorph.prototype.saveProject = function () {
myself = this;
this.ide.projectNotes = notes || this.ide.projectNotes;
if (name) {
if (this.source === 'cloud') {
if (detect(
this.projectList,
function (item) {return item.ProjectName === name; }
function (item) {return item.projectName === name; }
)) {
this.ide.confirm(
localize(
@ -6284,26 +6320,20 @@ ProjectDialogMorph.prototype.deleteProject = function () {
this.ide.confirm(
localize(
'Are you sure you want to delete'
) + '\n"' + proj.ProjectName + '"?',
) + '\n"' + proj.projectname + '"?',
'Delete Project',
function () {
SnapCloud.reconnect(
SnapCloud.deleteProject(
proj.projectname,
null, // username is implicit
function () {
SnapCloud.callService(
'deleteProject',
function () {
SnapCloud.disconnect();
myself.ide.hasChangedMedia = true;
idx = myself.projectList.indexOf(proj);
myself.projectList.splice(idx, 1);
myself.installCloudProjectList(
myself.projectList
); // refresh list
},
myself.ide.cloudError(),
[proj.ProjectName]
);
},
myself.ide.hasChangedMedia = true;
idx = myself.projectList.indexOf(proj);
myself.projectList.splice(idx, 1);
myself.installCloudProjectList(
myself.projectList
); // refresh list
},
myself.ide.cloudError()
);
}
@ -6335,37 +6365,36 @@ ProjectDialogMorph.prototype.shareProject = function () {
if (proj) {
this.ide.confirm(
localize(
'Are you sure you want to publish'
) + '\n"' + proj.ProjectName + '"?',
'Are you sure you want to share'
) + '\n"' + proj.projectname + '"?',
'Share Project',
function () {
myself.ide.showMessage('sharing\nproject...');
SnapCloud.reconnect(
SnapCloud.shareProject(
proj.projectname,
null, // username is implicit
function () {
SnapCloud.callService(
'publishProject',
function () {
SnapCloud.disconnect();
proj.Public = 'true';
myself.unshareButton.show();
myself.shareButton.hide();
entry.label.isBold = true;
entry.label.drawNew();
entry.label.changed();
myself.buttons.fixLayout();
myself.drawNew();
myself.ide.showMessage('shared.', 2);
},
myself.ide.cloudError(),
[proj.ProjectName]
);
proj.ispublic = true;
myself.unshareButton.show();
myself.shareButton.hide();
/*
myself.publishButton.show();
myself.unpublishButton.hide();
*/
entry.label.isBold = true;
entry.label.drawNew();
entry.label.changed();
myself.buttons.fixLayout();
myself.drawNew();
myself.ide.showMessage('shared.', 2);
// Set the Shared URL if the project is currently open
if (proj.ProjectName === ide.projectName) {
if (proj.projectname === ide.projectName) {
var usr = SnapCloud.username,
projectId = 'Username=' +
encodeURIComponent(usr.toLowerCase()) +
'&ProjectName=' +
encodeURIComponent(proj.ProjectName);
encodeURIComponent(proj.projectname);
location.hash = 'present:' + projectId;
}
},
@ -6382,38 +6411,119 @@ ProjectDialogMorph.prototype.unshareProject = function () {
proj = this.listField.selected,
entry = this.listField.active;
if (proj) {
this.ide.confirm(
localize(
'Are you sure you want to unshare'
) + '\n"' + proj.projectname + '"?',
'Unshare Project',
function () {
myself.ide.showMessage('unsharing\nproject...');
SnapCloud.unshareProject(
proj.projectname,
null, // username is implicit
function () {
proj.ispublic = false;
myself.shareButton.show();
myself.unshareButton.hide();
/*
myself.publishButton.hide();
myself.unpublishButton.hide();
*/
entry.label.isBold = false;
entry.label.isItalic = false;
entry.label.drawNew();
entry.label.changed();
myself.buttons.fixLayout();
myself.drawNew();
myself.ide.showMessage('unshared.', 2);
if (proj.projectname === ide.projectName) {
location.hash = '';
}
},
myself.ide.cloudError()
);
}
);
}
};
ProjectDialogMorph.prototype.publishProject = function () {
var myself = this,
ide = this.ide,
proj = this.listField.selected,
entry = this.listField.active;
if (proj) {
this.ide.confirm(
localize(
'Are you sure you want to publish'
) + '\n"' + proj.projectname + '"?',
'Publish Project',
function () {
myself.ide.showMessage('publishing\nproject...');
SnapCloud.publishProject(
proj.projectname,
null, // username is implicit
function () {
proj.ispublished = true;
myself.unshareButton.show();
myself.shareButton.hide();
myself.publishButton.hide();
myself.unpublishButton.show();
entry.label.isItalic = true;
entry.label.drawNew();
entry.label.changed();
myself.buttons.fixLayout();
myself.drawNew();
myself.ide.showMessage('published.', 2);
// Set the Shared URL if the project is currently open
if (proj.projectname === ide.projectName) {
var usr = SnapCloud.username,
projectId = 'Username=' +
encodeURIComponent(usr.toLowerCase()) +
'&ProjectName=' +
encodeURIComponent(proj.projectname);
location.hash = 'present:' + projectId;
}
},
myself.ide.cloudError()
);
}
);
}
};
ProjectDialogMorph.prototype.unpublishProject = function () {
var myself = this,
ide = this.ide,
proj = this.listField.selected,
entry = this.listField.active;
if (proj) {
this.ide.confirm(
localize(
'Are you sure you want to unpublish'
) + '\n"' + proj.ProjectName + '"?',
'Unshare Project',
) + '\n"' + proj.projectname + '"?',
'Unpublish Project',
function () {
myself.ide.showMessage('unsharing\nproject...');
SnapCloud.reconnect(
myself.ide.showMessage('unpublishing\nproject...');
SnapCloud.unpublishProject(
proj.projectname,
null, // username is implicit
function () {
SnapCloud.callService(
'unpublishProject',
function () {
SnapCloud.disconnect();
proj.Public = 'false';
myself.shareButton.show();
myself.unshareButton.hide();
entry.label.isBold = false;
entry.label.drawNew();
entry.label.changed();
myself.buttons.fixLayout();
myself.drawNew();
myself.ide.showMessage('unshared.', 2);
},
myself.ide.cloudError(),
[proj.ProjectName]
);
// Remove the shared URL if the project is open.
if (proj.ProjectName === ide.projectName) {
location.hash = '';
}
proj.ispublished = false;
myself.unshareButton.show();
myself.shareButton.hide();
myself.publishButton.show();
myself.unpublishButton.hide();
entry.label.isItalic = false;
entry.label.drawNew();
entry.label.changed();
myself.buttons.fixLayout();
myself.drawNew();
myself.ide.showMessage('unpublished.', 2);
},
myself.ide.cloudError()
);

Wyświetl plik

@ -1626,7 +1626,7 @@ ______
130415
------
* Blocks: place sticky comments on World layer on dragging their anchor block
* Blocks: place sticky comments on World layer on dragging their anchor block
130416
------
@ -1704,7 +1704,7 @@ ______
130514
------
* paint.js: Paint editor, first version, contributed by Kartik Chandra, Yay!!
* Threads, Objects, Blocks: Broadcast & message enhancements: When I receive <any msg>, and getLastMessage reporter + watcher
* Threads, Objects, Blocks: Broadcast & message enhancements: When I receive <any msg>, and getLastMessage reporter + watcher
130515
------
@ -1726,7 +1726,7 @@ ______
130605
------
* Objects: fix for hiding 'getLastAnswer' and 'getTimer' primitives
* Objects: fix for hiding 'getLastAnswer' and 'getTimer' primitives
130606
------
@ -1837,7 +1837,7 @@ ______
130801
------
* Blocks, Threads: "whitespace" & other options in SPLIT reporter's dropdown
* Blocks: Italicize editable input options (e.g. for the SPLT block)
* Blocks: Italicize editable input options (e.g. for the SPLT block)
* Blocks: Undrop Reporters feature (in script areas' context menus)
130802
@ -2245,7 +2245,7 @@ ______
* Objects, GUI: duplicate and clone nested sprites
* GUI, Store: export and import nested sprites
* Objects: double clicking on a sprite in the stage selects it in the IDE
* Objects: added move option to the sprite context menu, lets the user move (nested) sprites in edit mode without changing their layering, and also sprites marked “undraggable”
* Objects: added move option to the sprite context menu, lets the user move (nested) sprites in edit mode without changing their layering, and also sprites marked “undraggable”
* updated Portuguese translation, thanks, Manuel!
* updated German translation
* Morphic: fixed #497 (prevent bubble shadows from getting cut-off)
@ -2285,7 +2285,7 @@ ______
140930
------
* Objects: fixed #593 match broadcast numbers with event hat blocks containing strings that can be parsed as numbers
* Objects: fixed #593 match broadcast numbers with event hat blocks containing strings that can be parsed as numbers
* BYOB: allow percent symbols in custom block texts (fix #361), thanks, @Gubolin!!
* Morphic: allow negative min/max values for sliders (fix #285), thanks, @Gubolin!!
* Objects: fixed #378 (disable context menus for boolean representations)
@ -2927,7 +2927,7 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
* Updated Simplified Chinese translation, thanks to @ubertao!
* Media import dialog with thumbnail, thanks to @ubertao!
== v4.0.7.2 ====
== v4.0.7.2 ====
160714
------
@ -3050,7 +3050,7 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
160924
------
* dont update the recursion cache when updating a custom block definition
* dont update the recursion cache when updating a custom block definition
160929
------
@ -3167,7 +3167,7 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
161206
------
* GUI: Switch to asynchronous loading of resources (costumes, sounds, libraries etc.)
* GUI: Switch to asynchronous loading of resources (costumes, sounds, libraries etc.)
* Morphic: Added support for dropping links to SVGs from other web pages onto the World
* GUI: Support importing unrasterized SVG_Costumes from the “Costumes” and “Backgrounds” dialog
@ -3348,7 +3348,7 @@ Fixes:
170201
------
* GUI: let costume icons indicate svg costumes
* GUI: let costume icons indicate svg costumes
170202
------
@ -3508,7 +3508,7 @@ Fixes:
170707
------
* Objects, GUI, Store: tweak naming of instantiating to “clone”, enable inheritance by default
* Objects, GUI: run “When I start as clone” scripts when manually cloning a sprite, only position at hand pointer if no such scripts exist
* Objects, GUI: run “When I start as clone” scripts when manually cloning a sprite, only position at hand pointer if no such scripts exist
* Morphic, Objects: confine turtle direction readout to 0-360 degrees, thanks, Cynthia for the bug report!!
170708
@ -3518,7 +3518,7 @@ Fixes:
170709
------
* Objects, Threads: added experimental (only shown in dev mode) “tell ... to ..." and “ask ... for ...” primitives
* Objects, Threads: added experimental (only shown in dev mode) “tell ... to ..." and “ask ... for ...” primitives
170711
------
@ -3759,14 +3759,14 @@ v4.1 Features:
Fixes:
* changed keyboard shortcut indicator for “find blocks” to “^”
* prevent Snap from “hanging” when encountering certain errors in visible stepping
* prevent Snap from “hanging” when encountering certain errors in visible stepping
* only mark implicit parameters if no formal ones exist
* optimized thread-launch and script highlighting to a single frame instead of formerly two
* changed direction attribute of sprites to automatically confine to 0-360 degrees
* fixed rotation-bug when flipping costumes in "only turn left/right" mode"
* fixed variable renaming (“refactoring”) bugs, thanks, Bernat!
* fixed “fill” block crash when applying the same color twice
* fixed occasional empty drop-down menu items named “close”
* fixed occasional empty drop-down menu items named “close”
* fixed some typos
* limited sprites' direction and coordinates to finite numbers
* made block vars transient for block libraries
@ -3925,6 +3925,10 @@ Translation Updates:
* Turkish
* Chinese
* Spanish
=== development ===
* New cloud API
* Russian
*** in development ***

Wyświetl plik

@ -2075,6 +2075,10 @@ DialogBoxMorph.prototype.promptCredentials = function (
emlLabel = labelText('foo');
inp.add(emlLabel);
inp.add(eml);
inp.add(labelText('Password:'));
inp.add(pw1);
inp.add(labelText('Repeat Password:'));
inp.add(pw2);
}
if (purpose === 'login') {
@ -2182,7 +2186,7 @@ DialogBoxMorph.prototype.promptCredentials = function (
if (purpose === 'login') {
checklist = [usr, pw1];
} else if (purpose === 'signup') {
checklist = [usr, bmn, byr, eml];
checklist = [usr, bmn, byr, eml, pw1, pw2];
} else if (purpose === 'changePassword') {
checklist = [opw, pw1, pw2];
} else if (purpose === 'resetPassword') {
@ -2205,12 +2209,12 @@ DialogBoxMorph.prototype.promptCredentials = function (
return false;
}
if (em.indexOf(' ') > -1 || em.indexOf('@') === -1
|| em.indexOf('.') === -1) {
|| em.indexOf('.') === -1 || em.length < 5) {
indicate(eml, 'please provide a valid\nemail address');
return false;
}
}
if (purpose === 'changePassword') {
if (purpose === 'changePassword' || purpose === 'signup') {
if (pw1.getValue().length < 6) {
indicate(pw1, 'password must be six\ncharacters or longer');
return false;
@ -2249,6 +2253,7 @@ DialogBoxMorph.prototype.promptCredentials = function (
email: eml.getValue(),
oldpassword: opw.getValue(),
password: pw1.getValue(),
passwordRepeat: pw2.getValue(),
choice: agree
};
};