pxt-core 7.4.5 → 7.4.9
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 +60 -28
- package/built/pxteditor.d.ts +1 -1
- package/built/pxtlib.d.ts +9 -1
- package/built/pxtlib.js +60 -28
- package/built/target.js +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/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/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.ea4b3e23.chunk.js +1 -0
- package/localtypings/pxtarget.d.ts +4 -0
- package/package.json +1 -1
- package/theme/common.less +0 -28
- package/theme/highcontrast.less +4 -0
- package/theme/pxt.less +0 -1
- 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.prefPatchOps = [];
|
|
97887
97889
|
pxt.Util.assert(!_client);
|
|
97888
97890
|
// Set global instance.
|
|
97889
97891
|
_client = this;
|
|
@@ -98073,23 +98075,41 @@ var pxt;
|
|
|
98073
98075
|
}
|
|
98074
98076
|
return result.success;
|
|
98075
98077
|
}
|
|
98076
|
-
async patchUserPreferencesAsync(ops) {
|
|
98078
|
+
async patchUserPreferencesAsync(ops, immediate = false) {
|
|
98077
98079
|
ops = Array.isArray(ops) ? ops : [ops];
|
|
98080
|
+
ops = ops.filter(op => !!op);
|
|
98081
|
+
const curPref = await this.userPreferencesAsync();
|
|
98078
98082
|
if (!ops.length) {
|
|
98079
|
-
return;
|
|
98083
|
+
return { success: true, res: curPref };
|
|
98080
98084
|
}
|
|
98081
|
-
const curPref = await this.userPreferencesAsync();
|
|
98082
98085
|
ts.pxtc.jsonPatch.patchInPlace(curPref, ops);
|
|
98083
98086
|
await this.setUserPreferencesAsync(curPref);
|
|
98084
98087
|
// If we're not logged in, non-persistent local state is all we'll use
|
|
98085
98088
|
if (!await this.loggedInAsync()) {
|
|
98086
|
-
return;
|
|
98089
|
+
return { success: true, res: curPref };
|
|
98087
98090
|
}
|
|
98088
98091
|
// If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
|
|
98092
|
+
// Replace matching patches in the queue
|
|
98093
|
+
ops.forEach((incoming, iIncoming) => {
|
|
98094
|
+
this.prefPatchOps.some((existing, iExisting) => {
|
|
98095
|
+
if (!ts.pxtc.jsonPatch.opsAreEqual(existing, incoming))
|
|
98096
|
+
return false;
|
|
98097
|
+
// Patches are equivalent, replace in queue
|
|
98098
|
+
this.prefPatchOps[iExisting] = incoming;
|
|
98099
|
+
// Clear from incoming so we don't add it below
|
|
98100
|
+
ops[iIncoming] = null;
|
|
98101
|
+
return true;
|
|
98102
|
+
});
|
|
98103
|
+
});
|
|
98104
|
+
// Add remaining ops to the queue
|
|
98105
|
+
ops.filter(op => !!op).forEach(op => this.prefPatchOps.push(op));
|
|
98089
98106
|
clearTimeout(debouncePreferencesChangedTimeout);
|
|
98090
98107
|
const savePrefs = async () => {
|
|
98091
98108
|
debouncePreferencesChangedStarted = 0;
|
|
98092
|
-
|
|
98109
|
+
// Clear queued patch ops before send.
|
|
98110
|
+
const prefPatchOps = this.prefPatchOps;
|
|
98111
|
+
this.prefPatchOps = [];
|
|
98112
|
+
const result = await this.apiAsync('/api/user/preferences', prefPatchOps, 'PATCH');
|
|
98093
98113
|
if (result.success) {
|
|
98094
98114
|
pxt.debug("Updating local user preferences w/ cloud data after result of POST");
|
|
98095
98115
|
// Set user profile from returned value so we stay in-sync
|
|
@@ -98098,15 +98118,22 @@ var pxt;
|
|
|
98098
98118
|
else {
|
|
98099
98119
|
pxt.reportError("identity", "update preferences failed", result);
|
|
98100
98120
|
}
|
|
98121
|
+
return { success: result.success, res: result.resp };
|
|
98101
98122
|
};
|
|
98102
|
-
if (
|
|
98103
|
-
|
|
98104
|
-
}
|
|
98105
|
-
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
98106
|
-
await savePrefs();
|
|
98123
|
+
if (immediate) {
|
|
98124
|
+
return await savePrefs();
|
|
98107
98125
|
}
|
|
98108
98126
|
else {
|
|
98109
|
-
|
|
98127
|
+
if (!debouncePreferencesChangedStarted) {
|
|
98128
|
+
debouncePreferencesChangedStarted = pxt.U.now();
|
|
98129
|
+
}
|
|
98130
|
+
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
98131
|
+
return await savePrefs();
|
|
98132
|
+
}
|
|
98133
|
+
else {
|
|
98134
|
+
debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
|
|
98135
|
+
return { success: false, res: undefined }; // This needs to be implemented correctly to return a promise with the debouncer
|
|
98136
|
+
}
|
|
98110
98137
|
}
|
|
98111
98138
|
}
|
|
98112
98139
|
/*protected*/ hasUserId() {
|
|
@@ -98900,6 +98927,18 @@ var ts;
|
|
|
98900
98927
|
return arr;
|
|
98901
98928
|
}
|
|
98902
98929
|
Util.reversed = reversed;
|
|
98930
|
+
function arrayEquals(a, b, compare = (c, d) => c === d) {
|
|
98931
|
+
if (a == b)
|
|
98932
|
+
return true;
|
|
98933
|
+
if (!a && b || !b && a || a.length !== b.length)
|
|
98934
|
+
return false;
|
|
98935
|
+
for (let i = 0; i < a.length; i++) {
|
|
98936
|
+
if (!compare(a[i], b[i]))
|
|
98937
|
+
return false;
|
|
98938
|
+
}
|
|
98939
|
+
return true;
|
|
98940
|
+
}
|
|
98941
|
+
Util.arrayEquals = arrayEquals;
|
|
98903
98942
|
function iterMap(m, f) {
|
|
98904
98943
|
Object.keys(m).forEach(k => f(k, m[k]));
|
|
98905
98944
|
}
|
|
@@ -100723,6 +100762,10 @@ var ts;
|
|
|
100723
100762
|
}
|
|
100724
100763
|
}
|
|
100725
100764
|
jsonPatch.patchInPlace = patchInPlace;
|
|
100765
|
+
function opsAreEqual(a, b) {
|
|
100766
|
+
return (a.op === b.op && pxtc.U.arrayEquals(a.path, b.path));
|
|
100767
|
+
}
|
|
100768
|
+
jsonPatch.opsAreEqual = opsAreEqual;
|
|
100726
100769
|
})(jsonPatch = pxtc.jsonPatch || (pxtc.jsonPatch = {}));
|
|
100727
100770
|
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
100728
100771
|
})(ts || (ts = {}));
|
|
@@ -116191,8 +116234,8 @@ var pxt;
|
|
|
116191
116234
|
if (a == b)
|
|
116192
116235
|
return true;
|
|
116193
116236
|
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) ||
|
|
116237
|
+
!pxt.U.arrayEquals(a.meta.tags, b.meta.tags) ||
|
|
116238
|
+
!pxt.U.arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
|
|
116196
116239
|
a.meta.displayName !== b.meta.displayName)
|
|
116197
116240
|
return false;
|
|
116198
116241
|
switch (a.type) {
|
|
@@ -116201,7 +116244,7 @@ var pxt;
|
|
|
116201
116244
|
return pxt.sprite.bitmapEquals(a.bitmap, b.bitmap);
|
|
116202
116245
|
case "animation" /* Animation */:
|
|
116203
116246
|
const bAnimation = b;
|
|
116204
|
-
return a.interval === bAnimation.interval && arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
|
|
116247
|
+
return a.interval === bAnimation.interval && pxt.U.arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
|
|
116205
116248
|
case "tilemap" /* Tilemap */:
|
|
116206
116249
|
return a.data.equals(b.data);
|
|
116207
116250
|
}
|
|
@@ -116323,17 +116366,6 @@ var pxt;
|
|
|
116323
116366
|
}
|
|
116324
116367
|
return id;
|
|
116325
116368
|
}
|
|
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
116369
|
function serializeTilemap(tilemap, id, name) {
|
|
116338
116370
|
const tm = tilemap.tilemap.data();
|
|
116339
116371
|
const data = new Uint8ClampedArray(5 + tm.data.length + tilemap.layers.data.length);
|
package/built/pxteditor.d.ts
CHANGED
|
@@ -543,7 +543,7 @@ declare namespace pxt.editor {
|
|
|
543
543
|
message?: string;
|
|
544
544
|
data?: Map<string | number>;
|
|
545
545
|
}
|
|
546
|
-
type EditorMessageTutorialEventRequest = EditorMessageTutorialProgressEventRequest | EditorMessageTutorialCompletedEventRequest | EditorMessageTutorialLoadedEventRequest;
|
|
546
|
+
type EditorMessageTutorialEventRequest = EditorMessageTutorialProgressEventRequest | EditorMessageTutorialCompletedEventRequest | EditorMessageTutorialLoadedEventRequest | EditorMessageTutorialExitEventRequest;
|
|
547
547
|
interface EditorMessageTutorialProgressEventRequest extends EditorMessageRequest {
|
|
548
548
|
action: "tutorialevent";
|
|
549
549
|
tutorialEvent: "progress";
|
package/built/pxtlib.d.ts
CHANGED
|
@@ -57,6 +57,10 @@ declare namespace pxt.auth {
|
|
|
57
57
|
type UserBadgeState = {
|
|
58
58
|
badges: Badge[];
|
|
59
59
|
};
|
|
60
|
+
type SetPrefResult = {
|
|
61
|
+
success: boolean;
|
|
62
|
+
res: UserPreferences;
|
|
63
|
+
};
|
|
60
64
|
/**
|
|
61
65
|
* User preference state that should be synced with the cloud.
|
|
62
66
|
*/
|
|
@@ -66,6 +70,7 @@ declare namespace pxt.auth {
|
|
|
66
70
|
reader?: string;
|
|
67
71
|
skillmap?: UserSkillmapState;
|
|
68
72
|
badges?: UserBadgeState;
|
|
73
|
+
email?: boolean;
|
|
69
74
|
};
|
|
70
75
|
const DEFAULT_USER_PREFERENCES: () => UserPreferences;
|
|
71
76
|
/**
|
|
@@ -124,7 +129,8 @@ declare namespace pxt.auth {
|
|
|
124
129
|
username?: string;
|
|
125
130
|
avatarUrl?: string;
|
|
126
131
|
}): Promise<boolean>;
|
|
127
|
-
|
|
132
|
+
private prefPatchOps;
|
|
133
|
+
patchUserPreferencesAsync(ops: ts.pxtc.jsonPatch.PatchOperation | ts.pxtc.jsonPatch.PatchOperation[], immediate?: boolean): Promise<SetPrefResult>;
|
|
128
134
|
hasUserId(): boolean;
|
|
129
135
|
private fetchUserAsync;
|
|
130
136
|
private setUserProfileAsync;
|
|
@@ -269,6 +275,7 @@ declare namespace ts.pxtc.Util {
|
|
|
269
275
|
export function listsEqual<T>(a: T[], b: T[]): boolean;
|
|
270
276
|
export function oops(msg?: string): Error;
|
|
271
277
|
export function reversed<T>(arr: T[]): T[];
|
|
278
|
+
export function arrayEquals<U>(a: U[], b: U[], compare?: (c: U, d: U) => boolean): boolean;
|
|
272
279
|
export function iterMap<T>(m: pxt.Map<T>, f: (k: string, v: T) => void): void;
|
|
273
280
|
export function mapMap<T, S>(m: pxt.Map<T>, f: (k: string, v: T) => S): pxt.Map<S>;
|
|
274
281
|
export function values<T>(m: pxt.Map<T>): T[];
|
|
@@ -464,6 +471,7 @@ declare namespace ts.pxtc.jsonPatch {
|
|
|
464
471
|
* Applies a set of JSON Patch operations to the object.
|
|
465
472
|
*/
|
|
466
473
|
function patchInPlace(obj: any, ops: PatchOperation[]): void;
|
|
474
|
+
function opsAreEqual(a: PatchOperation, b: PatchOperation): boolean;
|
|
467
475
|
}
|
|
468
476
|
declare namespace ts.pxtc.jsonPatch.tests {
|
|
469
477
|
function diffTests(): void;
|
package/built/pxtlib.js
CHANGED
|
@@ -185,19 +185,21 @@ var pxt;
|
|
|
185
185
|
highContrast: false,
|
|
186
186
|
language: pxt.appTarget.appTheme.defaultLocale,
|
|
187
187
|
reader: "",
|
|
188
|
-
skillmap: { mapProgress: {}, completedTags: {} }
|
|
188
|
+
skillmap: { mapProgress: {}, completedTags: {} },
|
|
189
|
+
email: false
|
|
189
190
|
});
|
|
190
191
|
let _client;
|
|
191
192
|
function client() { return _client; }
|
|
192
193
|
auth.client = client;
|
|
193
|
-
const PREFERENCES_DEBOUNCE_MS =
|
|
194
|
-
const PREFERENCES_DEBOUNCE_MAX_MS =
|
|
194
|
+
const PREFERENCES_DEBOUNCE_MS = 1 * 1000;
|
|
195
|
+
const PREFERENCES_DEBOUNCE_MAX_MS = 10 * 1000;
|
|
195
196
|
let debouncePreferencesChangedTimeout = 0;
|
|
196
197
|
let debouncePreferencesChangedStarted = 0;
|
|
197
198
|
class AuthClient {
|
|
198
199
|
constructor() {
|
|
199
200
|
this.initialUserPreferences_ = undefined;
|
|
200
201
|
this.initialAuthCheck_ = undefined;
|
|
202
|
+
this.prefPatchOps = [];
|
|
201
203
|
pxt.Util.assert(!_client);
|
|
202
204
|
// Set global instance.
|
|
203
205
|
_client = this;
|
|
@@ -387,23 +389,41 @@ var pxt;
|
|
|
387
389
|
}
|
|
388
390
|
return result.success;
|
|
389
391
|
}
|
|
390
|
-
async patchUserPreferencesAsync(ops) {
|
|
392
|
+
async patchUserPreferencesAsync(ops, immediate = false) {
|
|
391
393
|
ops = Array.isArray(ops) ? ops : [ops];
|
|
394
|
+
ops = ops.filter(op => !!op);
|
|
395
|
+
const curPref = await this.userPreferencesAsync();
|
|
392
396
|
if (!ops.length) {
|
|
393
|
-
return;
|
|
397
|
+
return { success: true, res: curPref };
|
|
394
398
|
}
|
|
395
|
-
const curPref = await this.userPreferencesAsync();
|
|
396
399
|
ts.pxtc.jsonPatch.patchInPlace(curPref, ops);
|
|
397
400
|
await this.setUserPreferencesAsync(curPref);
|
|
398
401
|
// If we're not logged in, non-persistent local state is all we'll use
|
|
399
402
|
if (!await this.loggedInAsync()) {
|
|
400
|
-
return;
|
|
403
|
+
return { success: true, res: curPref };
|
|
401
404
|
}
|
|
402
405
|
// If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
|
|
406
|
+
// Replace matching patches in the queue
|
|
407
|
+
ops.forEach((incoming, iIncoming) => {
|
|
408
|
+
this.prefPatchOps.some((existing, iExisting) => {
|
|
409
|
+
if (!ts.pxtc.jsonPatch.opsAreEqual(existing, incoming))
|
|
410
|
+
return false;
|
|
411
|
+
// Patches are equivalent, replace in queue
|
|
412
|
+
this.prefPatchOps[iExisting] = incoming;
|
|
413
|
+
// Clear from incoming so we don't add it below
|
|
414
|
+
ops[iIncoming] = null;
|
|
415
|
+
return true;
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
// Add remaining ops to the queue
|
|
419
|
+
ops.filter(op => !!op).forEach(op => this.prefPatchOps.push(op));
|
|
403
420
|
clearTimeout(debouncePreferencesChangedTimeout);
|
|
404
421
|
const savePrefs = async () => {
|
|
405
422
|
debouncePreferencesChangedStarted = 0;
|
|
406
|
-
|
|
423
|
+
// Clear queued patch ops before send.
|
|
424
|
+
const prefPatchOps = this.prefPatchOps;
|
|
425
|
+
this.prefPatchOps = [];
|
|
426
|
+
const result = await this.apiAsync('/api/user/preferences', prefPatchOps, 'PATCH');
|
|
407
427
|
if (result.success) {
|
|
408
428
|
pxt.debug("Updating local user preferences w/ cloud data after result of POST");
|
|
409
429
|
// Set user profile from returned value so we stay in-sync
|
|
@@ -412,15 +432,22 @@ var pxt;
|
|
|
412
432
|
else {
|
|
413
433
|
pxt.reportError("identity", "update preferences failed", result);
|
|
414
434
|
}
|
|
435
|
+
return { success: result.success, res: result.resp };
|
|
415
436
|
};
|
|
416
|
-
if (
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
420
|
-
await savePrefs();
|
|
437
|
+
if (immediate) {
|
|
438
|
+
return await savePrefs();
|
|
421
439
|
}
|
|
422
440
|
else {
|
|
423
|
-
|
|
441
|
+
if (!debouncePreferencesChangedStarted) {
|
|
442
|
+
debouncePreferencesChangedStarted = pxt.U.now();
|
|
443
|
+
}
|
|
444
|
+
if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
|
|
445
|
+
return await savePrefs();
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
|
|
449
|
+
return { success: false, res: undefined }; // This needs to be implemented correctly to return a promise with the debouncer
|
|
450
|
+
}
|
|
424
451
|
}
|
|
425
452
|
}
|
|
426
453
|
/*protected*/ hasUserId() {
|
|
@@ -1214,6 +1241,18 @@ var ts;
|
|
|
1214
1241
|
return arr;
|
|
1215
1242
|
}
|
|
1216
1243
|
Util.reversed = reversed;
|
|
1244
|
+
function arrayEquals(a, b, compare = (c, d) => c === d) {
|
|
1245
|
+
if (a == b)
|
|
1246
|
+
return true;
|
|
1247
|
+
if (!a && b || !b && a || a.length !== b.length)
|
|
1248
|
+
return false;
|
|
1249
|
+
for (let i = 0; i < a.length; i++) {
|
|
1250
|
+
if (!compare(a[i], b[i]))
|
|
1251
|
+
return false;
|
|
1252
|
+
}
|
|
1253
|
+
return true;
|
|
1254
|
+
}
|
|
1255
|
+
Util.arrayEquals = arrayEquals;
|
|
1217
1256
|
function iterMap(m, f) {
|
|
1218
1257
|
Object.keys(m).forEach(k => f(k, m[k]));
|
|
1219
1258
|
}
|
|
@@ -3037,6 +3076,10 @@ var ts;
|
|
|
3037
3076
|
}
|
|
3038
3077
|
}
|
|
3039
3078
|
jsonPatch.patchInPlace = patchInPlace;
|
|
3079
|
+
function opsAreEqual(a, b) {
|
|
3080
|
+
return (a.op === b.op && pxtc.U.arrayEquals(a.path, b.path));
|
|
3081
|
+
}
|
|
3082
|
+
jsonPatch.opsAreEqual = opsAreEqual;
|
|
3040
3083
|
})(jsonPatch = pxtc.jsonPatch || (pxtc.jsonPatch = {}));
|
|
3041
3084
|
})(pxtc = ts.pxtc || (ts.pxtc = {}));
|
|
3042
3085
|
})(ts || (ts = {}));
|
|
@@ -18505,8 +18548,8 @@ var pxt;
|
|
|
18505
18548
|
if (a == b)
|
|
18506
18549
|
return true;
|
|
18507
18550
|
if (a.id !== b.id || a.type !== b.type ||
|
|
18508
|
-
!arrayEquals(a.meta.tags, b.meta.tags) ||
|
|
18509
|
-
!arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
|
|
18551
|
+
!pxt.U.arrayEquals(a.meta.tags, b.meta.tags) ||
|
|
18552
|
+
!pxt.U.arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
|
|
18510
18553
|
a.meta.displayName !== b.meta.displayName)
|
|
18511
18554
|
return false;
|
|
18512
18555
|
switch (a.type) {
|
|
@@ -18515,7 +18558,7 @@ var pxt;
|
|
|
18515
18558
|
return pxt.sprite.bitmapEquals(a.bitmap, b.bitmap);
|
|
18516
18559
|
case "animation" /* Animation */:
|
|
18517
18560
|
const bAnimation = b;
|
|
18518
|
-
return a.interval === bAnimation.interval && arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
|
|
18561
|
+
return a.interval === bAnimation.interval && pxt.U.arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
|
|
18519
18562
|
case "tilemap" /* Tilemap */:
|
|
18520
18563
|
return a.data.equals(b.data);
|
|
18521
18564
|
}
|
|
@@ -18637,17 +18680,6 @@ var pxt;
|
|
|
18637
18680
|
}
|
|
18638
18681
|
return id;
|
|
18639
18682
|
}
|
|
18640
|
-
function arrayEquals(a, b, compare = (c, d) => c === d) {
|
|
18641
|
-
if (a == b)
|
|
18642
|
-
return true;
|
|
18643
|
-
if (!a && b || !b && a || a.length !== b.length)
|
|
18644
|
-
return false;
|
|
18645
|
-
for (let i = 0; i < a.length; i++) {
|
|
18646
|
-
if (!compare(a[i], b[i]))
|
|
18647
|
-
return false;
|
|
18648
|
-
}
|
|
18649
|
-
return true;
|
|
18650
|
-
}
|
|
18651
18683
|
function serializeTilemap(tilemap, id, name) {
|
|
18652
18684
|
const tm = tilemap.tilemap.data();
|
|
18653
18685
|
const data = new Uint8ClampedArray(5 + tm.data.length + tilemap.layers.data.length);
|