pxt-core 7.4.6 → 7.4.7

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 CHANGED
@@ -97876,14 +97876,15 @@ var pxt;
97876
97876
  let _client;
97877
97877
  function client() { return _client; }
97878
97878
  auth.client = client;
97879
- const PREFERENCES_DEBOUNCE_MS = 5 * 1000;
97880
- const PREFERENCES_DEBOUNCE_MAX_MS = 30 * 1000;
97879
+ const PREFERENCES_DEBOUNCE_MS = 1 * 1000;
97880
+ const PREFERENCES_DEBOUNCE_MAX_MS = 10 * 1000;
97881
97881
  let debouncePreferencesChangedTimeout = 0;
97882
97882
  let debouncePreferencesChangedStarted = 0;
97883
97883
  class AuthClient {
97884
97884
  constructor() {
97885
97885
  this.initialUserPreferences_ = undefined;
97886
97886
  this.initialAuthCheck_ = undefined;
97887
+ this.prefPatchOps = [];
97887
97888
  pxt.Util.assert(!_client);
97888
97889
  // Set global instance.
97889
97890
  _client = this;
@@ -98073,8 +98074,9 @@ var pxt;
98073
98074
  }
98074
98075
  return result.success;
98075
98076
  }
98076
- async patchUserPreferencesAsync(ops) {
98077
+ async patchUserPreferencesAsync(ops, immediate = false) {
98077
98078
  ops = Array.isArray(ops) ? ops : [ops];
98079
+ ops = ops.filter(op => !!op);
98078
98080
  if (!ops.length) {
98079
98081
  return;
98080
98082
  }
@@ -98086,10 +98088,27 @@ var pxt;
98086
98088
  return;
98087
98089
  }
98088
98090
  // If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
98091
+ // Replace matching patches in the queue
98092
+ ops.forEach((incoming, iIncoming) => {
98093
+ this.prefPatchOps.some((existing, iExisting) => {
98094
+ if (!ts.pxtc.jsonPatch.opsAreEqual(existing, incoming))
98095
+ return false;
98096
+ // Patches are equivalent, replace in queue
98097
+ this.prefPatchOps[iExisting] = incoming;
98098
+ // Clear from incoming so we don't add it below
98099
+ ops[iIncoming] = null;
98100
+ return true;
98101
+ });
98102
+ });
98103
+ // Add remaining ops to the queue
98104
+ ops.filter(op => !!op).forEach(op => this.prefPatchOps.push(op));
98089
98105
  clearTimeout(debouncePreferencesChangedTimeout);
98090
98106
  const savePrefs = async () => {
98091
98107
  debouncePreferencesChangedStarted = 0;
98092
- const result = await this.apiAsync('/api/user/preferences', ops, 'PATCH');
98108
+ // Clear queued patch ops before send.
98109
+ const prefPatchOps = this.prefPatchOps;
98110
+ this.prefPatchOps = [];
98111
+ const result = await this.apiAsync('/api/user/preferences', prefPatchOps, 'PATCH');
98093
98112
  if (result.success) {
98094
98113
  pxt.debug("Updating local user preferences w/ cloud data after result of POST");
98095
98114
  // Set user profile from returned value so we stay in-sync
@@ -98099,14 +98118,19 @@ var pxt;
98099
98118
  pxt.reportError("identity", "update preferences failed", result);
98100
98119
  }
98101
98120
  };
98102
- if (!debouncePreferencesChangedStarted) {
98103
- debouncePreferencesChangedStarted = pxt.U.now();
98104
- }
98105
- if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
98121
+ if (immediate) {
98106
98122
  await savePrefs();
98107
98123
  }
98108
98124
  else {
98109
- debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
98125
+ if (!debouncePreferencesChangedStarted) {
98126
+ debouncePreferencesChangedStarted = pxt.U.now();
98127
+ }
98128
+ if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
98129
+ await savePrefs();
98130
+ }
98131
+ else {
98132
+ debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
98133
+ }
98110
98134
  }
98111
98135
  }
98112
98136
  /*protected*/ hasUserId() {
@@ -98900,6 +98924,18 @@ var ts;
98900
98924
  return arr;
98901
98925
  }
98902
98926
  Util.reversed = reversed;
98927
+ function arrayEquals(a, b, compare = (c, d) => c === d) {
98928
+ if (a == b)
98929
+ return true;
98930
+ if (!a && b || !b && a || a.length !== b.length)
98931
+ return false;
98932
+ for (let i = 0; i < a.length; i++) {
98933
+ if (!compare(a[i], b[i]))
98934
+ return false;
98935
+ }
98936
+ return true;
98937
+ }
98938
+ Util.arrayEquals = arrayEquals;
98903
98939
  function iterMap(m, f) {
98904
98940
  Object.keys(m).forEach(k => f(k, m[k]));
98905
98941
  }
@@ -100723,6 +100759,10 @@ var ts;
100723
100759
  }
100724
100760
  }
100725
100761
  jsonPatch.patchInPlace = patchInPlace;
100762
+ function opsAreEqual(a, b) {
100763
+ return (a.op === b.op && pxtc.U.arrayEquals(a.path, b.path));
100764
+ }
100765
+ jsonPatch.opsAreEqual = opsAreEqual;
100726
100766
  })(jsonPatch = pxtc.jsonPatch || (pxtc.jsonPatch = {}));
100727
100767
  })(pxtc = ts.pxtc || (ts.pxtc = {}));
100728
100768
  })(ts || (ts = {}));
@@ -116191,8 +116231,8 @@ var pxt;
116191
116231
  if (a == b)
116192
116232
  return true;
116193
116233
  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) ||
116234
+ !pxt.U.arrayEquals(a.meta.tags, b.meta.tags) ||
116235
+ !pxt.U.arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
116196
116236
  a.meta.displayName !== b.meta.displayName)
116197
116237
  return false;
116198
116238
  switch (a.type) {
@@ -116201,7 +116241,7 @@ var pxt;
116201
116241
  return pxt.sprite.bitmapEquals(a.bitmap, b.bitmap);
116202
116242
  case "animation" /* Animation */:
116203
116243
  const bAnimation = b;
116204
- return a.interval === bAnimation.interval && arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
116244
+ return a.interval === bAnimation.interval && pxt.U.arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
116205
116245
  case "tilemap" /* Tilemap */:
116206
116246
  return a.data.equals(b.data);
116207
116247
  }
@@ -116323,17 +116363,6 @@ var pxt;
116323
116363
  }
116324
116364
  return id;
116325
116365
  }
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
116366
  function serializeTilemap(tilemap, id, name) {
116338
116367
  const tm = tilemap.tilemap.data();
116339
116368
  const data = new Uint8ClampedArray(5 + tm.data.length + tilemap.layers.data.length);
@@ -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
@@ -124,7 +124,8 @@ declare namespace pxt.auth {
124
124
  username?: string;
125
125
  avatarUrl?: string;
126
126
  }): Promise<boolean>;
127
- patchUserPreferencesAsync(ops: ts.pxtc.jsonPatch.PatchOperation | ts.pxtc.jsonPatch.PatchOperation[]): Promise<void>;
127
+ private prefPatchOps;
128
+ patchUserPreferencesAsync(ops: ts.pxtc.jsonPatch.PatchOperation | ts.pxtc.jsonPatch.PatchOperation[], immediate?: boolean): Promise<void>;
128
129
  hasUserId(): boolean;
129
130
  private fetchUserAsync;
130
131
  private setUserProfileAsync;
@@ -269,6 +270,7 @@ declare namespace ts.pxtc.Util {
269
270
  export function listsEqual<T>(a: T[], b: T[]): boolean;
270
271
  export function oops(msg?: string): Error;
271
272
  export function reversed<T>(arr: T[]): T[];
273
+ export function arrayEquals<U>(a: U[], b: U[], compare?: (c: U, d: U) => boolean): boolean;
272
274
  export function iterMap<T>(m: pxt.Map<T>, f: (k: string, v: T) => void): void;
273
275
  export function mapMap<T, S>(m: pxt.Map<T>, f: (k: string, v: T) => S): pxt.Map<S>;
274
276
  export function values<T>(m: pxt.Map<T>): T[];
@@ -464,6 +466,7 @@ declare namespace ts.pxtc.jsonPatch {
464
466
  * Applies a set of JSON Patch operations to the object.
465
467
  */
466
468
  function patchInPlace(obj: any, ops: PatchOperation[]): void;
469
+ function opsAreEqual(a: PatchOperation, b: PatchOperation): boolean;
467
470
  }
468
471
  declare namespace ts.pxtc.jsonPatch.tests {
469
472
  function diffTests(): void;
package/built/pxtlib.js CHANGED
@@ -190,14 +190,15 @@ var pxt;
190
190
  let _client;
191
191
  function client() { return _client; }
192
192
  auth.client = client;
193
- const PREFERENCES_DEBOUNCE_MS = 5 * 1000;
194
- const PREFERENCES_DEBOUNCE_MAX_MS = 30 * 1000;
193
+ const PREFERENCES_DEBOUNCE_MS = 1 * 1000;
194
+ const PREFERENCES_DEBOUNCE_MAX_MS = 10 * 1000;
195
195
  let debouncePreferencesChangedTimeout = 0;
196
196
  let debouncePreferencesChangedStarted = 0;
197
197
  class AuthClient {
198
198
  constructor() {
199
199
  this.initialUserPreferences_ = undefined;
200
200
  this.initialAuthCheck_ = undefined;
201
+ this.prefPatchOps = [];
201
202
  pxt.Util.assert(!_client);
202
203
  // Set global instance.
203
204
  _client = this;
@@ -387,8 +388,9 @@ var pxt;
387
388
  }
388
389
  return result.success;
389
390
  }
390
- async patchUserPreferencesAsync(ops) {
391
+ async patchUserPreferencesAsync(ops, immediate = false) {
391
392
  ops = Array.isArray(ops) ? ops : [ops];
393
+ ops = ops.filter(op => !!op);
392
394
  if (!ops.length) {
393
395
  return;
394
396
  }
@@ -400,10 +402,27 @@ var pxt;
400
402
  return;
401
403
  }
402
404
  // If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
405
+ // Replace matching patches in the queue
406
+ ops.forEach((incoming, iIncoming) => {
407
+ this.prefPatchOps.some((existing, iExisting) => {
408
+ if (!ts.pxtc.jsonPatch.opsAreEqual(existing, incoming))
409
+ return false;
410
+ // Patches are equivalent, replace in queue
411
+ this.prefPatchOps[iExisting] = incoming;
412
+ // Clear from incoming so we don't add it below
413
+ ops[iIncoming] = null;
414
+ return true;
415
+ });
416
+ });
417
+ // Add remaining ops to the queue
418
+ ops.filter(op => !!op).forEach(op => this.prefPatchOps.push(op));
403
419
  clearTimeout(debouncePreferencesChangedTimeout);
404
420
  const savePrefs = async () => {
405
421
  debouncePreferencesChangedStarted = 0;
406
- const result = await this.apiAsync('/api/user/preferences', ops, 'PATCH');
422
+ // Clear queued patch ops before send.
423
+ const prefPatchOps = this.prefPatchOps;
424
+ this.prefPatchOps = [];
425
+ const result = await this.apiAsync('/api/user/preferences', prefPatchOps, 'PATCH');
407
426
  if (result.success) {
408
427
  pxt.debug("Updating local user preferences w/ cloud data after result of POST");
409
428
  // Set user profile from returned value so we stay in-sync
@@ -413,14 +432,19 @@ var pxt;
413
432
  pxt.reportError("identity", "update preferences failed", result);
414
433
  }
415
434
  };
416
- if (!debouncePreferencesChangedStarted) {
417
- debouncePreferencesChangedStarted = pxt.U.now();
418
- }
419
- if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
435
+ if (immediate) {
420
436
  await savePrefs();
421
437
  }
422
438
  else {
423
- debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
439
+ if (!debouncePreferencesChangedStarted) {
440
+ debouncePreferencesChangedStarted = pxt.U.now();
441
+ }
442
+ if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
443
+ await savePrefs();
444
+ }
445
+ else {
446
+ debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
447
+ }
424
448
  }
425
449
  }
426
450
  /*protected*/ hasUserId() {
@@ -1214,6 +1238,18 @@ var ts;
1214
1238
  return arr;
1215
1239
  }
1216
1240
  Util.reversed = reversed;
1241
+ function arrayEquals(a, b, compare = (c, d) => c === d) {
1242
+ if (a == b)
1243
+ return true;
1244
+ if (!a && b || !b && a || a.length !== b.length)
1245
+ return false;
1246
+ for (let i = 0; i < a.length; i++) {
1247
+ if (!compare(a[i], b[i]))
1248
+ return false;
1249
+ }
1250
+ return true;
1251
+ }
1252
+ Util.arrayEquals = arrayEquals;
1217
1253
  function iterMap(m, f) {
1218
1254
  Object.keys(m).forEach(k => f(k, m[k]));
1219
1255
  }
@@ -3037,6 +3073,10 @@ var ts;
3037
3073
  }
3038
3074
  }
3039
3075
  jsonPatch.patchInPlace = patchInPlace;
3076
+ function opsAreEqual(a, b) {
3077
+ return (a.op === b.op && pxtc.U.arrayEquals(a.path, b.path));
3078
+ }
3079
+ jsonPatch.opsAreEqual = opsAreEqual;
3040
3080
  })(jsonPatch = pxtc.jsonPatch || (pxtc.jsonPatch = {}));
3041
3081
  })(pxtc = ts.pxtc || (ts.pxtc = {}));
3042
3082
  })(ts || (ts = {}));
@@ -18505,8 +18545,8 @@ var pxt;
18505
18545
  if (a == b)
18506
18546
  return true;
18507
18547
  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) ||
18548
+ !pxt.U.arrayEquals(a.meta.tags, b.meta.tags) ||
18549
+ !pxt.U.arrayEquals(a.meta.blockIDs, b.meta.blockIDs) ||
18510
18550
  a.meta.displayName !== b.meta.displayName)
18511
18551
  return false;
18512
18552
  switch (a.type) {
@@ -18515,7 +18555,7 @@ var pxt;
18515
18555
  return pxt.sprite.bitmapEquals(a.bitmap, b.bitmap);
18516
18556
  case "animation" /* Animation */:
18517
18557
  const bAnimation = b;
18518
- return a.interval === bAnimation.interval && arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
18558
+ return a.interval === bAnimation.interval && pxt.U.arrayEquals(a.frames, bAnimation.frames, pxt.sprite.bitmapEquals);
18519
18559
  case "tilemap" /* Tilemap */:
18520
18560
  return a.data.equals(b.data);
18521
18561
  }
@@ -18637,17 +18677,6 @@ var pxt;
18637
18677
  }
18638
18678
  return id;
18639
18679
  }
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
18680
  function serializeTilemap(tilemap, id, name) {
18652
18681
  const tm = tilemap.tilemap.data();
18653
18682
  const data = new Uint8ClampedArray(5 + tm.data.length + tilemap.layers.data.length);