pxt-core 7.4.6 → 7.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/built/pxt.js +105 -39
- package/built/pxtblockly.js +1359 -1448
- package/built/pxtblocks.d.ts +4 -4
- package/built/pxtblocks.js +35 -80
- package/built/pxteditor.d.ts +1 -1
- package/built/pxtlib.d.ts +13 -1
- package/built/pxtlib.js +105 -39
- package/built/target.js +1 -1
- package/built/web/blockly.css +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +1 -1
- package/built/web/pxtasseteditor.js +1 -1
- package/built/web/pxtblockly.js +1 -1
- package/built/web/pxtblocks.js +1 -1
- package/built/web/pxtembed.js +1 -1
- package/built/web/pxtlib.js +1 -1
- package/built/web/pxtworker.js +1 -1
- package/built/web/react-common.css +85 -18
- package/built/web/rtlblockly.css +1 -1
- package/built/web/rtlsemantic.css +2 -2
- package/built/web/semantic.css +2 -2
- package/built/web/skillmap/css/main.96b1b3f1.chunk.css +1 -0
- package/built/web/skillmap/js/2.7dd06a3a.chunk.js +2 -0
- package/built/web/skillmap/js/main.d5bb4f6b.chunk.js +1 -0
- package/localtypings/blockly.d.ts +12268 -7535
- package/localtypings/pxtarget.d.ts +1 -0
- package/package.json +2 -2
- package/theme/blockly-core.less +22 -13
- package/theme/common.less +0 -28
- package/theme/highcontrast.less +4 -0
- package/theme/melodyeditor.less +2 -2
- package/theme/print.less +1 -1
- package/theme/pxt.less +0 -1
- package/theme/toolbox.less +1 -0
- package/webapp/public/blockly/blockly_compressed.js +1269 -1286
- package/webapp/public/blockly/blocks_compressed.js +47 -65
- package/webapp/public/blockly/msg/js/en.js +8 -17
- package/webapp/public/blockly/msg/json/en.json +6 -15
- package/webapp/public/skillmap.html +2 -2
- package/built/web/skillmap/css/main.2461a333.chunk.css +0 -1
- package/built/web/skillmap/js/2.9cb94aa0.chunk.js +0 -2
- package/built/web/skillmap/js/main.c49acd24.chunk.js +0 -1
package/built/pxt.js
CHANGED
|
@@ -97871,19 +97871,21 @@ var pxt;
|
|
|
97871
97871
|
highContrast: false,
|
|
97872
97872
|
language: pxt.appTarget.appTheme.defaultLocale,
|
|
97873
97873
|
reader: "",
|
|
97874
|
-
skillmap: { mapProgress: {}, completedTags: {} }
|
|
97874
|
+
skillmap: { mapProgress: {}, completedTags: {} },
|
|
97875
|
+
email: false
|
|
97875
97876
|
});
|
|
97876
97877
|
let _client;
|
|
97877
97878
|
function client() { return _client; }
|
|
97878
97879
|
auth.client = client;
|
|
97879
|
-
const PREFERENCES_DEBOUNCE_MS =
|
|
97880
|
-
const PREFERENCES_DEBOUNCE_MAX_MS =
|
|
97880
|
+
const PREFERENCES_DEBOUNCE_MS = 1 * 1000;
|
|
97881
|
+
const PREFERENCES_DEBOUNCE_MAX_MS = 10 * 1000;
|
|
97881
97882
|
let debouncePreferencesChangedTimeout = 0;
|
|
97882
97883
|
let debouncePreferencesChangedStarted = 0;
|
|
97883
97884
|
class AuthClient {
|
|
97884
97885
|
constructor() {
|
|
97885
97886
|
this.initialUserPreferences_ = undefined;
|
|
97886
97887
|
this.initialAuthCheck_ = undefined;
|
|
97888
|
+
this.patchQueue = [];
|
|
97887
97889
|
pxt.Util.assert(!_client);
|
|
97888
97890
|
// Set global instance.
|
|
97889
97891
|
_client = this;
|
|
@@ -98073,40 +98075,87 @@ var pxt;
|
|
|
98073
98075
|
}
|
|
98074
98076
|
return result.success;
|
|
98075
98077
|
}
|
|
98076
|
-
async patchUserPreferencesAsync(
|
|
98077
|
-
|
|
98078
|
-
|
|
98079
|
-
|
|
98080
|
-
|
|
98078
|
+
async patchUserPreferencesAsync(patchOps, opts = {}) {
|
|
98079
|
+
const defaultSuccessAsync = async () => ({ success: true, res: await this.userPreferencesAsync() });
|
|
98080
|
+
patchOps = Array.isArray(patchOps) ? patchOps : [patchOps];
|
|
98081
|
+
patchOps = patchOps.filter(op => !!op);
|
|
98082
|
+
if (!patchOps.length) {
|
|
98083
|
+
return await defaultSuccessAsync();
|
|
98084
|
+
}
|
|
98085
|
+
const patchDiff = (pSrc, ops, filter) => {
|
|
98086
|
+
// Apply patches to pDst and return the diff as a set of new patch ops.
|
|
98087
|
+
const pDst = pxt.U.deepCopy(pSrc);
|
|
98088
|
+
ts.pxtc.jsonPatch.patchInPlace(pDst, ops);
|
|
98089
|
+
let diff = ts.pxtc.jsonPatch.diff(pSrc, pDst);
|
|
98090
|
+
// Run caller-provided filter
|
|
98091
|
+
if (diff.length && filter) {
|
|
98092
|
+
diff = diff.filter(filter);
|
|
98093
|
+
}
|
|
98094
|
+
return diff;
|
|
98095
|
+
};
|
|
98096
|
+
// Process incoming patch operations to produce a more fine-grained set of diffs. Incoming patches may be overly destructive
|
|
98097
|
+
// Apply the patch in isolation and get the diff from original
|
|
98081
98098
|
const curPref = await this.userPreferencesAsync();
|
|
98082
|
-
|
|
98099
|
+
const diff = patchDiff(curPref, patchOps, opts.filter);
|
|
98100
|
+
if (!diff.length) {
|
|
98101
|
+
return await defaultSuccessAsync();
|
|
98102
|
+
}
|
|
98103
|
+
// Apply the new diff to the current state
|
|
98104
|
+
ts.pxtc.jsonPatch.patchInPlace(curPref, diff);
|
|
98083
98105
|
await this.setUserPreferencesAsync(curPref);
|
|
98084
|
-
// If
|
|
98106
|
+
// If the user is not logged in, non-persistent local state is all we'll use (no sync to cloud)
|
|
98085
98107
|
if (!await this.loggedInAsync()) {
|
|
98086
|
-
return;
|
|
98108
|
+
return await defaultSuccessAsync();
|
|
98087
98109
|
}
|
|
98088
|
-
// If the user is logged in,
|
|
98110
|
+
// If the user is logged in, sync to cloud, but debounce the api call as this can be called frequently from skillmaps
|
|
98111
|
+
// Queue the patch for sync with backend
|
|
98112
|
+
this.patchQueue.push({ ops: patchOps, filter: opts.filter });
|
|
98089
98113
|
clearTimeout(debouncePreferencesChangedTimeout);
|
|
98090
|
-
const
|
|
98114
|
+
const syncPrefs = async () => {
|
|
98091
98115
|
debouncePreferencesChangedStarted = 0;
|
|
98092
|
-
|
|
98093
|
-
|
|
98094
|
-
|
|
98095
|
-
|
|
98096
|
-
|
|
98116
|
+
if (!this.patchQueue.length) {
|
|
98117
|
+
return await defaultSuccessAsync();
|
|
98118
|
+
}
|
|
98119
|
+
// Fetch latest prefs from remote
|
|
98120
|
+
const getResult = await this.apiAsync('/api/user/preferences');
|
|
98121
|
+
if (!getResult.success) {
|
|
98122
|
+
pxt.reportError("identity", "failed to fetch preferences for patch", getResult);
|
|
98123
|
+
return { success: false, res: undefined };
|
|
98124
|
+
}
|
|
98125
|
+
// Apply queued patches to the remote state in isolation and develop a final diff to send to the backend
|
|
98126
|
+
const remotePrefs = pxt.U.deepCopy(getResult.resp);
|
|
98127
|
+
const patchQueue = this.patchQueue;
|
|
98128
|
+
this.patchQueue = []; // Reset the queue
|
|
98129
|
+
patchQueue.forEach(patch => {
|
|
98130
|
+
const diff = patchDiff(remotePrefs, patch.ops, patch.filter);
|
|
98131
|
+
ts.pxtc.jsonPatch.patchInPlace(remotePrefs, diff);
|
|
98132
|
+
});
|
|
98133
|
+
// Diff the original and patched remote states to get a final set of patch operations
|
|
98134
|
+
const finalOps = pxtc.jsonPatch.diff(getResult.resp, remotePrefs);
|
|
98135
|
+
const patchResult = await this.apiAsync('/api/user/preferences', finalOps, 'PATCH');
|
|
98136
|
+
if (patchResult.success) {
|
|
98137
|
+
// Set user profile from returned value so we stay in sync
|
|
98138
|
+
this.setUserPreferencesAsync(patchResult.resp);
|
|
98097
98139
|
}
|
|
98098
98140
|
else {
|
|
98099
|
-
pxt.reportError("identity", "
|
|
98141
|
+
pxt.reportError("identity", "failed to patch preferences", patchResult);
|
|
98100
98142
|
}
|
|
98143
|
+
return { success: patchResult.success, res: patchResult.resp };
|
|
98101
98144
|
};
|
|
98102
|
-
if (
|
|
98103
|
-
|
|
98104
|
-
}
|
|
98105
|
-
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
98106
|
-
await savePrefs();
|
|
98145
|
+
if (opts.immediate) {
|
|
98146
|
+
return await syncPrefs();
|
|
98107
98147
|
}
|
|
98108
98148
|
else {
|
|
98109
|
-
|
|
98149
|
+
if (!debouncePreferencesChangedStarted) {
|
|
98150
|
+
debouncePreferencesChangedStarted = pxt.U.now();
|
|
98151
|
+
}
|
|
98152
|
+
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
98153
|
+
return await syncPrefs();
|
|
98154
|
+
}
|
|
98155
|
+
else {
|
|
98156
|
+
debouncePreferencesChangedTimeout = setTimeout(syncPrefs, PREFERENCES_DEBOUNCE_MS);
|
|
98157
|
+
return { success: false, res: undefined }; // This needs to be implemented correctly to return a promise with the debouncer
|
|
98158
|
+
}
|
|
98110
98159
|
}
|
|
98111
98160
|
}
|
|
98112
98161
|
/*protected*/ hasUserId() {
|
|
@@ -98900,6 +98949,18 @@ var ts;
|
|
|
98900
98949
|
return arr;
|
|
98901
98950
|
}
|
|
98902
98951
|
Util.reversed = reversed;
|
|
98952
|
+
function arrayEquals(a, b, compare = (c, d) => c === d) {
|
|
98953
|
+
if (a == b)
|
|
98954
|
+
return true;
|
|
98955
|
+
if (!a && b || !b && a || a.length !== b.length)
|
|
98956
|
+
return false;
|
|
98957
|
+
for (let i = 0; i < a.length; i++) {
|
|
98958
|
+
if (!compare(a[i], b[i]))
|
|
98959
|
+
return false;
|
|
98960
|
+
}
|
|
98961
|
+
return true;
|
|
98962
|
+
}
|
|
98963
|
+
Util.arrayEquals = arrayEquals;
|
|
98903
98964
|
function iterMap(m, f) {
|
|
98904
98965
|
Object.keys(m).forEach(k => f(k, m[k]));
|
|
98905
98966
|
}
|
|
@@ -99175,6 +99236,18 @@ var ts;
|
|
|
99175
99236
|
return r;
|
|
99176
99237
|
}
|
|
99177
99238
|
Util.toSet = toSet;
|
|
99239
|
+
function deepCopy(src) {
|
|
99240
|
+
if (typeof src !== "object" || src === null) {
|
|
99241
|
+
return src;
|
|
99242
|
+
}
|
|
99243
|
+
const dst = Array.isArray(src) ? [] : {};
|
|
99244
|
+
for (const key in src) {
|
|
99245
|
+
const value = src[key];
|
|
99246
|
+
dst[key] = deepCopy(value);
|
|
99247
|
+
}
|
|
99248
|
+
return dst;
|
|
99249
|
+
}
|
|
99250
|
+
Util.deepCopy = deepCopy;
|
|
99178
99251
|
function toArray(a) {
|
|
99179
99252
|
if (Array.isArray(a)) {
|
|
99180
99253
|
return a;
|
|
@@ -100723,6 +100796,10 @@ var ts;
|
|
|
100723
100796
|
}
|
|
100724
100797
|
}
|
|
100725
100798
|
jsonPatch.patchInPlace = patchInPlace;
|
|
100799
|
+
function opsAreEqual(a, b) {
|
|
100800
|
+
return (a.op === b.op && pxtc.U.arrayEquals(a.path, b.path));
|
|
100801
|
+
}
|
|
100802
|
+
jsonPatch.opsAreEqual = opsAreEqual;
|
|
100726
100803
|
})(jsonPatch = pxtc.jsonPatch || (pxtc.jsonPatch = {}));
|
|
100727
100804
|
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
100728
100805
|
})(ts || (ts = {}));
|
|
@@ -116191,8 +116268,8 @@ var pxt;
|
|
|
116191
116268
|
if (a == b)
|
|
116192
116269
|
return true;
|
|
116193
116270
|
if (a.id !== b.id || a.type !== b.type ||
|
|
116194
|
-
!arrayEquals(a.meta.tags, b.meta.tags) ||
|
|
116195
|
-
!arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
|
|
116271
|
+
!pxt.U.arrayEquals(a.meta.tags, b.meta.tags) ||
|
|
116272
|
+
!pxt.U.arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
|
|
116196
116273
|
a.meta.displayName !== b.meta.displayName)
|
|
116197
116274
|
return false;
|
|
116198
116275
|
switch (a.type) {
|
|
@@ -116201,7 +116278,7 @@ var pxt;
|
|
|
116201
116278
|
return pxt.sprite.bitmapEquals(a.bitmap, b.bitmap);
|
|
116202
116279
|
case "animation" /* Animation */:
|
|
116203
116280
|
const bAnimation = b;
|
|
116204
|
-
return a.interval === bAnimation.interval && arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
|
|
116281
|
+
return a.interval === bAnimation.interval && pxt.U.arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
|
|
116205
116282
|
case "tilemap" /* Tilemap */:
|
|
116206
116283
|
return a.data.equals(b.data);
|
|
116207
116284
|
}
|
|
@@ -116323,17 +116400,6 @@ var pxt;
|
|
|
116323
116400
|
}
|
|
116324
116401
|
return id;
|
|
116325
116402
|
}
|
|
116326
|
-
function arrayEquals(a, b, compare = (c, d) => c === d) {
|
|
116327
|
-
if (a == b)
|
|
116328
|
-
return true;
|
|
116329
|
-
if (!a && b || !b && a || a.length !== b.length)
|
|
116330
|
-
return false;
|
|
116331
|
-
for (let i = 0; i < a.length; i++) {
|
|
116332
|
-
if (!compare(a[i], b[i]))
|
|
116333
|
-
return false;
|
|
116334
|
-
}
|
|
116335
|
-
return true;
|
|
116336
|
-
}
|
|
116337
116403
|
function serializeTilemap(tilemap, id, name) {
|
|
116338
116404
|
const tm = tilemap.tilemap.data();
|
|
116339
116405
|
const data = new Uint8ClampedArray(5 + tm.data.length + tilemap.layers.data.length);
|