pxt-core 7.3.7 → 7.3.11

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/cli.js CHANGED
@@ -1768,7 +1768,9 @@ function buildSemanticUIAsync(parsed) {
1768
1768
  // Append icons.css to semantic.css (custom pxt icons)
1769
1769
  const iconsFile = (pkg["name"] == "pxt-core") ? 'built/web/icons.css' : 'node_modules/pxt-core/built/web/icons.css';
1770
1770
  const iconsCss = fs.readFileSync(iconsFile, "utf-8");
1771
- semCss = semCss + "\n" + iconsCss;
1771
+ const reactCommonFile = (pkg["name"] == "pxt-core") ? 'built/web/react-common.css' : 'node_modules/pxt-core/built/web/react-common.css';
1772
+ const reactCommonCss = fs.readFileSync(reactCommonFile, "utf-8");
1773
+ semCss = semCss + "\n" + iconsCss + "\n" + reactCommonCss;
1772
1774
  nodeutil.writeFileSync('built/web/semantic.css', semCss);
1773
1775
  }).then(() => {
1774
1776
  // generate blockly css
@@ -1836,6 +1838,7 @@ function buildSkillMapAsync(parsed) {
1836
1838
  nodeutil.cp("node_modules/pxt-core/built/pxtlib.js", `${skillmapRoot}/public/blb`);
1837
1839
  nodeutil.cp("built/web/semantic.css", `${skillmapRoot}/public/blb`);
1838
1840
  nodeutil.cp("node_modules/pxt-core/built/web/icons.css", `${skillmapRoot}/public/blb`);
1841
+ nodeutil.cp("node_modules/pxt-core/built/web/react-common.css", `${skillmapRoot}/public/blb`);
1839
1842
  // copy 'assets' over from docs/static
1840
1843
  nodeutil.cpR("docs/static/skillmap/assets", `${skillmapRoot}/public/assets`);
1841
1844
  if (docsPath) {
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,7 +98074,7 @@ 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];
98078
98079
  if (!ops.length) {
98079
98080
  return;
@@ -98086,10 +98087,15 @@ var pxt;
98086
98087
  return;
98087
98088
  }
98088
98089
  // If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
98090
+ // Accumulate the ops and send to cloud in batch.
98091
+ this.prefPatchOps.push(...ops);
98089
98092
  clearTimeout(debouncePreferencesChangedTimeout);
98090
98093
  const savePrefs = async () => {
98091
98094
  debouncePreferencesChangedStarted = 0;
98092
- const result = await this.apiAsync('/api/user/preferences', ops, 'PATCH');
98095
+ // Clear queued patch ops before send.
98096
+ const prefPatchOps = this.prefPatchOps;
98097
+ this.prefPatchOps = [];
98098
+ const result = await this.apiAsync('/api/user/preferences', prefPatchOps, 'PATCH');
98093
98099
  if (result.success) {
98094
98100
  pxt.debug("Updating local user preferences w/ cloud data after result of POST");
98095
98101
  // Set user profile from returned value so we stay in-sync
@@ -98099,14 +98105,19 @@ var pxt;
98099
98105
  pxt.reportError("identity", "update preferences failed", result);
98100
98106
  }
98101
98107
  };
98102
- if (!debouncePreferencesChangedStarted) {
98103
- debouncePreferencesChangedStarted = pxt.U.now();
98104
- }
98105
- if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
98108
+ if (immediate) {
98106
98109
  await savePrefs();
98107
98110
  }
98108
98111
  else {
98109
- debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
98112
+ if (!debouncePreferencesChangedStarted) {
98113
+ debouncePreferencesChangedStarted = pxt.U.now();
98114
+ }
98115
+ if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
98116
+ await savePrefs();
98117
+ }
98118
+ else {
98119
+ debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
98120
+ }
98110
98121
  }
98111
98122
  }
98112
98123
  /*protected*/ hasUserId() {
@@ -98356,6 +98367,17 @@ var pxt;
98356
98367
  }
98357
98368
  }
98358
98369
  auth.generateUserProfilePicDataUrl = generateUserProfilePicDataUrl;
98370
+ /**
98371
+ * Checks only the ID and sourceURL
98372
+ */
98373
+ function badgeEquals(badgeA, badgeB) {
98374
+ return badgeA.id === badgeB.id && badgeA.sourceURL === badgeB.sourceURL;
98375
+ }
98376
+ auth.badgeEquals = badgeEquals;
98377
+ function hasBadge(preferences, badge) {
98378
+ return preferences.badges.some(toCheck => badgeEquals(toCheck, badge));
98379
+ }
98380
+ auth.hasBadge = hasBadge;
98359
98381
  })(auth = pxt.auth || (pxt.auth = {}));
98360
98382
  })(pxt || (pxt = {}));
98361
98383
  // Needs to be in its own file to avoid a circular dependency: util.ts -> main.ts -> util.ts
@@ -139048,6 +139070,7 @@ var ts;
139048
139070
  }
139049
139071
  service.snippetAddsDefinitions = snippetAddsDefinitions;
139050
139072
  function getSnippet(context, fn, decl, python, recursionDepth = 0) {
139073
+ var _a;
139051
139074
  // TODO: a lot of this is duplicate logic with blocklyloader.ts:buildBlockFromDef; we should
139052
139075
  // unify these approaches
139053
139076
  let { apis, takenNames, blocksInfo, screenSize, checker } = context;
@@ -139080,10 +139103,15 @@ var ts;
139080
139103
  if (attrs.shim === "TD_ID" && recursionDepth && decl.parameters.length) {
139081
139104
  return getParameterDefault(decl.parameters[0]);
139082
139105
  }
139106
+ const element = fn;
139107
+ const params = pxt.blocks.compileInfo(element);
139083
139108
  const blocksById = blocksInfo.blocksById;
139084
139109
  // TODO: move out of getSnippet for general reuse
139110
+ const blockParameters = ((_a = attrs._def) === null || _a === void 0 ? void 0 : _a.parameters.filter(param => !!params.definitionNameToParam[param.name]).map(param => params.definitionNameToParam[param.name].actualName)) || [];
139085
139111
  const includedParameters = decl.parameters ? decl.parameters
139086
- .filter(param => !param.initializer && !param.questionToken) : [];
139112
+ // Only keep required parameters and parameters included in the blockdef
139113
+ .filter(param => (!param.initializer && !param.questionToken)
139114
+ || (blockParameters.indexOf(param.name.getText()) >= 0)) : [];
139087
139115
  const args = includedParameters
139088
139116
  .map(getParameterDefault)
139089
139117
  .map(p =>
@@ -139093,7 +139121,6 @@ var ts;
139093
139121
  default: p,
139094
139122
  isLiteral: true
139095
139123
  }));
139096
- const element = fn;
139097
139124
  if (element.attributes.block) {
139098
139125
  if (element.attributes.defaultInstance) {
139099
139126
  snippetPrefix = element.attributes.defaultInstance;
@@ -139141,7 +139168,6 @@ var ts;
139141
139168
  isInstance = true;
139142
139169
  }
139143
139170
  else if (element.kind == 1 /* Method */ || element.kind == 2 /* Property */) {
139144
- const params = pxt.blocks.compileInfo(element);
139145
139171
  if (params.thisParameter) {
139146
139172
  let varName = undefined;
139147
139173
  if (params.thisParameter.definitionName) {
@@ -157637,7 +157663,9 @@ function buildSemanticUIAsync(parsed) {
157637
157663
  // Append icons.css to semantic.css (custom pxt icons)
157638
157664
  const iconsFile = (pkg["name"] == "pxt-core") ? 'built/web/icons.css' : 'node_modules/pxt-core/built/web/icons.css';
157639
157665
  const iconsCss = fs.readFileSync(iconsFile, "utf-8");
157640
- semCss = semCss + "\n" + iconsCss;
157666
+ const reactCommonFile = (pkg["name"] == "pxt-core") ? 'built/web/react-common.css' : 'node_modules/pxt-core/built/web/react-common.css';
157667
+ const reactCommonCss = fs.readFileSync(reactCommonFile, "utf-8");
157668
+ semCss = semCss + "\n" + iconsCss + "\n" + reactCommonCss;
157641
157669
  nodeutil.writeFileSync('built/web/semantic.css', semCss);
157642
157670
  }).then(() => {
157643
157671
  // generate blockly css
@@ -157705,6 +157733,7 @@ function buildSkillMapAsync(parsed) {
157705
157733
  nodeutil.cp("node_modules/pxt-core/built/pxtlib.js", `${skillmapRoot}/public/blb`);
157706
157734
  nodeutil.cp("built/web/semantic.css", `${skillmapRoot}/public/blb`);
157707
157735
  nodeutil.cp("node_modules/pxt-core/built/web/icons.css", `${skillmapRoot}/public/blb`);
157736
+ nodeutil.cp("node_modules/pxt-core/built/web/react-common.css", `${skillmapRoot}/public/blb`);
157708
157737
  // copy 'assets' over from docs/static
157709
157738
  nodeutil.cpR("docs/static/skillmap/assets", `${skillmapRoot}/public/assets`);
157710
157739
  if (docsPath) {
@@ -18255,6 +18255,7 @@ var ts;
18255
18255
  }
18256
18256
  service.snippetAddsDefinitions = snippetAddsDefinitions;
18257
18257
  function getSnippet(context, fn, decl, python, recursionDepth = 0) {
18258
+ var _a;
18258
18259
  // TODO: a lot of this is duplicate logic with blocklyloader.ts:buildBlockFromDef; we should
18259
18260
  // unify these approaches
18260
18261
  let { apis, takenNames, blocksInfo, screenSize, checker } = context;
@@ -18287,10 +18288,15 @@ var ts;
18287
18288
  if (attrs.shim === "TD_ID" && recursionDepth && decl.parameters.length) {
18288
18289
  return getParameterDefault(decl.parameters[0]);
18289
18290
  }
18291
+ const element = fn;
18292
+ const params = pxt.blocks.compileInfo(element);
18290
18293
  const blocksById = blocksInfo.blocksById;
18291
18294
  // TODO: move out of getSnippet for general reuse
18295
+ const blockParameters = ((_a = attrs._def) === null || _a === void 0 ? void 0 : _a.parameters.filter(param => !!params.definitionNameToParam[param.name]).map(param => params.definitionNameToParam[param.name].actualName)) || [];
18292
18296
  const includedParameters = decl.parameters ? decl.parameters
18293
- .filter(param => !param.initializer && !param.questionToken) : [];
18297
+ // Only keep required parameters and parameters included in the blockdef
18298
+ .filter(param => (!param.initializer && !param.questionToken)
18299
+ || (blockParameters.indexOf(param.name.getText()) >= 0)) : [];
18294
18300
  const args = includedParameters
18295
18301
  .map(getParameterDefault)
18296
18302
  .map(p =>
@@ -18300,7 +18306,6 @@ var ts;
18300
18306
  default: p,
18301
18307
  isLiteral: true
18302
18308
  }));
18303
- const element = fn;
18304
18309
  if (element.attributes.block) {
18305
18310
  if (element.attributes.defaultInstance) {
18306
18311
  snippetPrefix = element.attributes.defaultInstance;
@@ -18348,7 +18353,6 @@ var ts;
18348
18353
  isInstance = true;
18349
18354
  }
18350
18355
  else if (element.kind == 1 /* Method */ || element.kind == 2 /* Property */) {
18351
- const params = pxt.blocks.compileInfo(element);
18352
18356
  if (params.thisParameter) {
18353
18357
  let varName = undefined;
18354
18358
  if (params.thisParameter.definitionName) {
@@ -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
@@ -54,6 +54,9 @@ declare namespace pxt.auth {
54
54
  mapProgress: any;
55
55
  completedTags: any;
56
56
  };
57
+ type UserBadgeState = {
58
+ badges: Badge[];
59
+ };
57
60
  /**
58
61
  * User preference state that should be synced with the cloud.
59
62
  */
@@ -62,6 +65,7 @@ declare namespace pxt.auth {
62
65
  highContrast?: boolean;
63
66
  reader?: string;
64
67
  skillmap?: UserSkillmapState;
68
+ badges?: UserBadgeState;
65
69
  };
66
70
  const DEFAULT_USER_PREFERENCES: () => UserPreferences;
67
71
  /**
@@ -120,7 +124,8 @@ declare namespace pxt.auth {
120
124
  username?: string;
121
125
  avatarUrl?: string;
122
126
  }): Promise<boolean>;
123
- 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>;
124
129
  hasUserId(): boolean;
125
130
  private fetchUserAsync;
126
131
  private setUserProfileAsync;
@@ -165,6 +170,11 @@ declare namespace pxt.auth {
165
170
  function userName(user: pxt.auth.UserProfile): string;
166
171
  function userInitials(user: pxt.auth.UserProfile): string;
167
172
  function generateUserProfilePicDataUrl(profile: pxt.auth.UserProfile): void;
173
+ /**
174
+ * Checks only the ID and sourceURL
175
+ */
176
+ function badgeEquals(badgeA: pxt.auth.Badge, badgeB: pxt.auth.Badge): boolean;
177
+ function hasBadge(preferences: pxt.auth.UserBadgeState, badge: pxt.auth.Badge): boolean;
168
178
  }
169
179
  declare namespace pxt {
170
180
  interface TelemetryEventOptions {
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,7 +388,7 @@ 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];
392
393
  if (!ops.length) {
393
394
  return;
@@ -400,10 +401,15 @@ var pxt;
400
401
  return;
401
402
  }
402
403
  // If the user is logged in, save to cloud, but debounce the api call as this can be called frequently from skillmaps
404
+ // Accumulate the ops and send to cloud in batch.
405
+ this.prefPatchOps.push(...ops);
403
406
  clearTimeout(debouncePreferencesChangedTimeout);
404
407
  const savePrefs = async () => {
405
408
  debouncePreferencesChangedStarted = 0;
406
- const result = await this.apiAsync('/api/user/preferences', ops, 'PATCH');
409
+ // Clear queued patch ops before send.
410
+ const prefPatchOps = this.prefPatchOps;
411
+ this.prefPatchOps = [];
412
+ const result = await this.apiAsync('/api/user/preferences', prefPatchOps, 'PATCH');
407
413
  if (result.success) {
408
414
  pxt.debug("Updating local user preferences w/ cloud data after result of POST");
409
415
  // Set user profile from returned value so we stay in-sync
@@ -413,14 +419,19 @@ var pxt;
413
419
  pxt.reportError("identity", "update preferences failed", result);
414
420
  }
415
421
  };
416
- if (!debouncePreferencesChangedStarted) {
417
- debouncePreferencesChangedStarted = pxt.U.now();
418
- }
419
- if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
422
+ if (immediate) {
420
423
  await savePrefs();
421
424
  }
422
425
  else {
423
- debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
426
+ if (!debouncePreferencesChangedStarted) {
427
+ debouncePreferencesChangedStarted = pxt.U.now();
428
+ }
429
+ if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
430
+ await savePrefs();
431
+ }
432
+ else {
433
+ debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
434
+ }
424
435
  }
425
436
  }
426
437
  /*protected*/ hasUserId() {
@@ -670,6 +681,17 @@ var pxt;
670
681
  }
671
682
  }
672
683
  auth.generateUserProfilePicDataUrl = generateUserProfilePicDataUrl;
684
+ /**
685
+ * Checks only the ID and sourceURL
686
+ */
687
+ function badgeEquals(badgeA, badgeB) {
688
+ return badgeA.id === badgeB.id && badgeA.sourceURL === badgeB.sourceURL;
689
+ }
690
+ auth.badgeEquals = badgeEquals;
691
+ function hasBadge(preferences, badge) {
692
+ return preferences.badges.some(toCheck => badgeEquals(toCheck, badge));
693
+ }
694
+ auth.hasBadge = hasBadge;
673
695
  })(auth = pxt.auth || (pxt.auth = {}));
674
696
  })(pxt || (pxt = {}));
675
697
  // Needs to be in its own file to avoid a circular dependency: util.ts -> main.ts -> util.ts