pxt-core 7.4.7 → 7.4.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.
Files changed (39) hide show
  1. package/built/pxt.js +90 -53
  2. package/built/pxtblockly.js +1361 -1450
  3. package/built/pxtblocks.d.ts +4 -4
  4. package/built/pxtblocks.js +35 -80
  5. package/built/pxtlib.d.ts +11 -2
  6. package/built/pxtlib.js +90 -53
  7. package/built/target.js +1 -1
  8. package/built/web/blockly.css +1 -1
  9. package/built/web/main.js +1 -1
  10. package/built/web/pxtapp.js +1 -1
  11. package/built/web/pxtasseteditor.js +1 -1
  12. package/built/web/pxtblockly.js +1 -1
  13. package/built/web/pxtblocks.js +1 -1
  14. package/built/web/pxtembed.js +1 -1
  15. package/built/web/pxtlib.js +1 -1
  16. package/built/web/pxtworker.js +1 -1
  17. package/built/web/react-common.css +10 -5
  18. package/built/web/rtlblockly.css +1 -1
  19. package/built/web/rtlsemantic.css +2 -2
  20. package/built/web/semantic.css +2 -2
  21. package/built/web/skillmap/css/main.96b1b3f1.chunk.css +1 -0
  22. package/built/web/skillmap/js/2.7dd06a3a.chunk.js +2 -0
  23. package/built/web/skillmap/js/main.55881627.chunk.js +1 -0
  24. package/localtypings/blockly.d.ts +12268 -7535
  25. package/localtypings/pxtarget.d.ts +1 -0
  26. package/package.json +2 -2
  27. package/theme/blockly-core.less +22 -13
  28. package/theme/melodyeditor.less +2 -2
  29. package/theme/print.less +1 -1
  30. package/theme/pxt.less +0 -1
  31. package/theme/toolbox.less +1 -0
  32. package/webapp/public/blockly/blockly_compressed.js +1271 -1288
  33. package/webapp/public/blockly/blocks_compressed.js +47 -65
  34. package/webapp/public/blockly/msg/js/en.js +8 -17
  35. package/webapp/public/blockly/msg/json/en.json +6 -15
  36. package/webapp/public/skillmap.html +2 -2
  37. package/built/web/skillmap/css/main.70954d9b.chunk.css +0 -1
  38. package/built/web/skillmap/js/2.c64f6be2.chunk.js +0 -2
  39. package/built/web/skillmap/js/main.86ef11e3.chunk.js +0 -1
package/built/pxt.js CHANGED
@@ -97871,7 +97871,8 @@ 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; }
@@ -97884,7 +97885,7 @@ var pxt;
97884
97885
  constructor() {
97885
97886
  this.initialUserPreferences_ = undefined;
97886
97887
  this.initialAuthCheck_ = undefined;
97887
- this.prefPatchOps = [];
97888
+ this.patchQueue = [];
97888
97889
  pxt.Util.assert(!_client);
97889
97890
  // Set global instance.
97890
97891
  _client = this;
@@ -98074,62 +98075,86 @@ var pxt;
98074
98075
  }
98075
98076
  return result.success;
98076
98077
  }
98077
- async patchUserPreferencesAsync(ops, immediate = false) {
98078
- ops = Array.isArray(ops) ? ops : [ops];
98079
- ops = ops.filter(op => !!op);
98080
- if (!ops.length) {
98081
- return;
98082
- }
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
98083
98098
  const curPref = await this.userPreferencesAsync();
98084
- ts.pxtc.jsonPatch.patchInPlace(curPref, ops);
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);
98085
98105
  await this.setUserPreferencesAsync(curPref);
98086
- // If we're not logged in, non-persistent local state is all we'll use
98106
+ // If the user is not logged in, non-persistent local state is all we'll use (no sync to cloud)
98087
98107
  if (!await this.loggedInAsync()) {
98088
- return;
98108
+ return await defaultSuccessAsync();
98089
98109
  }
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));
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 });
98105
98113
  clearTimeout(debouncePreferencesChangedTimeout);
98106
- const savePrefs = async () => {
98114
+ const syncPrefs = async () => {
98107
98115
  debouncePreferencesChangedStarted = 0;
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');
98112
- if (result.success) {
98113
- pxt.debug("Updating local user preferences w/ cloud data after result of POST");
98114
- // Set user profile from returned value so we stay in-sync
98115
- this.setUserPreferencesAsync(result.resp);
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);
98116
98139
  }
98117
98140
  else {
98118
- pxt.reportError("identity", "update preferences failed", result);
98141
+ pxt.reportError("identity", "failed to patch preferences", patchResult);
98119
98142
  }
98143
+ return { success: patchResult.success, res: patchResult.resp };
98120
98144
  };
98121
- if (immediate) {
98122
- await savePrefs();
98145
+ if (opts.immediate) {
98146
+ return await syncPrefs();
98123
98147
  }
98124
98148
  else {
98125
98149
  if (!debouncePreferencesChangedStarted) {
98126
98150
  debouncePreferencesChangedStarted = pxt.U.now();
98127
98151
  }
98128
98152
  if (PREFERENCES_DEBOUNCE_MAX_MS < pxt.U.now() - debouncePreferencesChangedStarted) {
98129
- await savePrefs();
98153
+ return await syncPrefs();
98130
98154
  }
98131
98155
  else {
98132
- debouncePreferencesChangedTimeout = setTimeout(savePrefs, PREFERENCES_DEBOUNCE_MS);
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
98133
98158
  }
98134
98159
  }
98135
98160
  }
@@ -99211,6 +99236,18 @@ var ts;
99211
99236
  return r;
99212
99237
  }
99213
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;
99214
99251
  function toArray(a) {
99215
99252
  if (Array.isArray(a)) {
99216
99253
  return a;
@@ -101630,7 +101667,7 @@ var pxt;
101630
101667
  'pxt_controls_for': {
101631
101668
  name: pxt.Util.lf("a loop that repeats the number of times you say"),
101632
101669
  tooltip: pxt.Util.lf("Have the variable '{0}' take on the values from 0 to the end number, counting by 1, and do the specified blocks."),
101633
- url: 'blocks/loops/for',
101670
+ url: '/blocks/loops/for',
101634
101671
  category: 'loops',
101635
101672
  block: {
101636
101673
  message0: pxt.Util.lf("for %1 from 0 to %2"),
@@ -101641,7 +101678,7 @@ var pxt;
101641
101678
  'controls_simple_for': {
101642
101679
  name: pxt.Util.lf("a loop that repeats the number of times you say"),
101643
101680
  tooltip: pxt.Util.lf("Have the variable '{0}' take on the values from 0 to the end number, counting by 1, and do the specified blocks."),
101644
- url: 'blocks/loops/for',
101681
+ url: '/blocks/loops/for',
101645
101682
  category: 'loops',
101646
101683
  block: {
101647
101684
  message0: pxt.Util.lf("for %1 from 0 to %2"),
@@ -101652,7 +101689,7 @@ var pxt;
101652
101689
  'pxt_controls_for_of': {
101653
101690
  name: pxt.Util.lf("a loop that repeats for each value in an array"),
101654
101691
  tooltip: pxt.Util.lf("Have the variable '{0}' take the value of each item in the array one by one, and do the specified blocks."),
101655
- url: 'blocks/loops/for-of',
101692
+ url: '/blocks/loops/for-of',
101656
101693
  category: 'loops',
101657
101694
  block: {
101658
101695
  message0: pxt.Util.lf("for element %1 of %2"),
@@ -101663,7 +101700,7 @@ var pxt;
101663
101700
  'controls_for_of': {
101664
101701
  name: pxt.Util.lf("a loop that repeats for each value in an array"),
101665
101702
  tooltip: pxt.Util.lf("Have the variable '{0}' take the value of each item in the array one by one, and do the specified blocks."),
101666
- url: 'blocks/loops/for-of',
101703
+ url: '/blocks/loops/for-of',
101667
101704
  category: 'loops',
101668
101705
  block: {
101669
101706
  message0: pxt.Util.lf("for element %1 of %2"),
@@ -101948,7 +101985,7 @@ var pxt;
101948
101985
  'text': {
101949
101986
  name: pxt.Util.lf("a piece of text"),
101950
101987
  tooltip: pxt.Util.lf("A letter, word, or line of text."),
101951
- url: 'types/string',
101988
+ url: '/types/string',
101952
101989
  category: 'text',
101953
101990
  block: {
101954
101991
  search: pxt.Util.lf("a piece of text") // Only used for search; this string is not surfaced in the block's text
@@ -101957,7 +101994,7 @@ var pxt;
101957
101994
  'text_length': {
101958
101995
  name: pxt.Util.lf("number of characters in the string"),
101959
101996
  tooltip: pxt.Util.lf("Returns the number of letters (including spaces) in the provided text."),
101960
- url: 'reference/text/length',
101997
+ url: '/reference/text/length',
101961
101998
  category: 'text',
101962
101999
  block: {
101963
102000
  TEXT_LENGTH_TITLE: pxt.Util.lf("length of %1")
@@ -101966,7 +102003,7 @@ var pxt;
101966
102003
  'text_join': {
101967
102004
  name: pxt.Util.lf("join items to create text"),
101968
102005
  tooltip: pxt.Util.lf("Create a piece of text by joining together any number of items."),
101969
- url: 'reference/text/join',
102006
+ url: '/reference/text/join',
101970
102007
  category: 'text',
101971
102008
  block: {
101972
102009
  TEXT_JOIN_TITLE_CREATEWITH: pxt.Util.lf("join")
@@ -101975,7 +102012,7 @@ var pxt;
101975
102012
  'procedures_defnoreturn': {
101976
102013
  name: pxt.Util.lf("define the function"),
101977
102014
  tooltip: pxt.Util.lf("Create a function."),
101978
- url: 'types/function/define',
102015
+ url: '/types/function/define',
101979
102016
  category: 'functions',
101980
102017
  block: {
101981
102018
  PROCEDURES_DEFNORETURN_TITLE: pxt.Util.lf("function"),
@@ -101985,7 +102022,7 @@ var pxt;
101985
102022
  'procedures_callnoreturn': {
101986
102023
  name: pxt.Util.lf("call the function"),
101987
102024
  tooltip: pxt.Util.lf("Call the user-defined function."),
101988
- url: 'types/function/call',
102025
+ url: '/types/function/call',
101989
102026
  category: 'functions',
101990
102027
  block: {
101991
102028
  PROCEDURES_CALLNORETURN_TITLE: pxt.Util.lf("call function")
@@ -101994,7 +102031,7 @@ var pxt;
101994
102031
  'function_return': {
101995
102032
  name: pxt.Util.lf("return a value from within a function"),
101996
102033
  tooltip: pxt.Util.lf("Return a value from within a user-defined function."),
101997
- url: 'types/function/return',
102034
+ url: '/types/function/return',
101998
102035
  category: 'functions',
101999
102036
  block: {
102000
102037
  message_with_value: pxt.Util.lf("return %1"),
@@ -102004,7 +102041,7 @@ var pxt;
102004
102041
  'function_definition': {
102005
102042
  name: pxt.Util.lf("define the function"),
102006
102043
  tooltip: pxt.Util.lf("Create a function."),
102007
- url: 'types/function/define',
102044
+ url: '/types/function/define',
102008
102045
  category: 'functions',
102009
102046
  block: {
102010
102047
  FUNCTIONS_EDIT_OPTION: pxt.Util.lf("Edit Function")
@@ -102013,7 +102050,7 @@ var pxt;
102013
102050
  'function_call': {
102014
102051
  name: pxt.Util.lf("call the function"),
102015
102052
  tooltip: pxt.Util.lf("Call the user-defined function."),
102016
- url: 'types/function/call',
102053
+ url: '/types/function/call',
102017
102054
  category: 'functions',
102018
102055
  block: {
102019
102056
  FUNCTIONS_CALL_TITLE: pxt.Util.lf("call"),
@@ -102023,7 +102060,7 @@ var pxt;
102023
102060
  'function_call_output': {
102024
102061
  name: pxt.Util.lf("call the function with a return value"),
102025
102062
  tooltip: pxt.Util.lf("Call the user-defined function with a return value."),
102026
- url: 'types/function/call',
102063
+ url: '/types/function/call',
102027
102064
  category: 'functions',
102028
102065
  block: {}
102029
102066
  }