pxt-core 9.1.1 → 9.1.2
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 +85 -29
- package/built/pxteditor.d.ts +7 -2
- package/built/pxteditor.js +6 -0
- package/built/pxtlib.d.ts +0 -1
- package/built/pxtlib.js +57 -22
- package/built/pxtsim.d.ts +8 -0
- package/built/pxtsim.js +28 -7
- package/built/target.js +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +1 -1
- package/built/web/pxteditor.js +1 -1
- package/built/web/pxtembed.js +2 -2
- package/built/web/pxtlib.js +1 -1
- package/built/web/pxtsim.js +1 -1
- package/built/web/pxtworker.js +1 -1
- package/built/web/react-common-authcode.css +1 -1
- package/built/web/react-common-multiplayer.css +1 -1
- package/built/web/react-common-skillmap.css +1 -1
- package/built/web/rtlreact-common-authcode.css +1 -1
- package/built/web/rtlreact-common-multiplayer.css +1 -1
- package/built/web/rtlreact-common-skillmap.css +1 -1
- package/built/web/rtlsemantic.css +2 -2
- package/built/web/semantic.css +2 -2
- package/built/web/skillmap/js/{main.b6e4b712.js → main.a9bdebe3.js} +2 -2
- package/common-docs/identity/sign-in.md +7 -15
- package/localtypings/pxtarget.d.ts +2 -0
- package/package.json +1 -1
- package/react-common/components/profile/Profile.tsx +15 -0
- package/react-common/styles/profile/profile.less +12 -0
- package/theme/common.less +9 -6
- package/theme/themes/pxt/globals/site.variables +1 -1
- package/theme/tutorial-sidebar.less +2 -2
- package/webapp/public/skillmap.html +1 -1
package/built/pxt.js
CHANGED
|
@@ -97876,6 +97876,7 @@ var pxt;
|
|
|
97876
97876
|
const AUTH_LOGIN_STATE_KEY = "login-state"; // stored in local storage.
|
|
97877
97877
|
const AUTH_USER_STATE_KEY = "user-state"; // stored in local storage.
|
|
97878
97878
|
const X_PXT_TARGET = "x-pxt-target"; // header passed in auth rest calls.
|
|
97879
|
+
const INTERACTIVE_LOGIN_UNTIL = "interactive-login-until"; // hint whether to prompt user or try SSO first.
|
|
97879
97880
|
let authDisabled = false;
|
|
97880
97881
|
auth.DEFAULT_USER_PREFERENCES = () => ({
|
|
97881
97882
|
highContrast: false,
|
|
@@ -97901,19 +97902,29 @@ var pxt;
|
|
|
97901
97902
|
// Last known auth token state. This is provided as a convenience for legacy methods that cannot be made async.
|
|
97902
97903
|
// Preference hasAuthTokenAsync() over taking a dependency on this cached value.
|
|
97903
97904
|
auth.cachedHasAuthToken = false;
|
|
97904
|
-
async function
|
|
97905
|
-
|
|
97905
|
+
async function setLocalStorageValueAsync(key, value) {
|
|
97906
|
+
if (!!value)
|
|
97907
|
+
return await pxt.storage.shared.setAsync(AUTH_CONTAINER, key, value);
|
|
97908
|
+
else
|
|
97909
|
+
return await pxt.storage.shared.delAsync(AUTH_CONTAINER, key);
|
|
97910
|
+
}
|
|
97911
|
+
async function getLocalStorageValueAsync(key) {
|
|
97906
97912
|
try {
|
|
97907
|
-
|
|
97913
|
+
return await pxt.storage.shared.getAsync(AUTH_CONTAINER, key);
|
|
97908
97914
|
}
|
|
97909
|
-
catch (_a) {
|
|
97915
|
+
catch (_a) {
|
|
97916
|
+
return undefined;
|
|
97917
|
+
}
|
|
97918
|
+
}
|
|
97919
|
+
async function getAuthTokenAsync() {
|
|
97920
|
+
const token = await getLocalStorageValueAsync(CSRF_TOKEN_KEY);
|
|
97910
97921
|
auth.cachedHasAuthToken = !!token;
|
|
97911
97922
|
return token;
|
|
97912
97923
|
}
|
|
97913
97924
|
auth.getAuthTokenAsync = getAuthTokenAsync;
|
|
97914
97925
|
async function setAuthTokenAsync(token) {
|
|
97915
97926
|
auth.cachedHasAuthToken = !!token;
|
|
97916
|
-
return await
|
|
97927
|
+
return await setLocalStorageValueAsync(CSRF_TOKEN_KEY, token);
|
|
97917
97928
|
}
|
|
97918
97929
|
async function hasAuthTokenAsync() {
|
|
97919
97930
|
return !!(await getAuthTokenAsync());
|
|
@@ -97921,7 +97932,7 @@ var pxt;
|
|
|
97921
97932
|
auth.hasAuthTokenAsync = hasAuthTokenAsync;
|
|
97922
97933
|
async function delAuthTokenAsync() {
|
|
97923
97934
|
auth.cachedHasAuthToken = false;
|
|
97924
|
-
return await
|
|
97935
|
+
return await setLocalStorageValueAsync(CSRF_TOKEN_KEY, undefined);
|
|
97925
97936
|
}
|
|
97926
97937
|
async function getUserStateAsync() {
|
|
97927
97938
|
let userState;
|
|
@@ -97984,16 +97995,20 @@ var pxt;
|
|
|
97984
97995
|
idp,
|
|
97985
97996
|
persistent
|
|
97986
97997
|
};
|
|
97998
|
+
// Should the user be prompted to interactively login, or can we try to silently login?
|
|
97999
|
+
const interactiveUntil = parseInt(await getLocalStorageValueAsync(INTERACTIVE_LOGIN_UNTIL));
|
|
98000
|
+
const interactiveLogin = (interactiveUntil || 0) > Date.now();
|
|
97987
98001
|
// Redirect to the login endpoint.
|
|
97988
98002
|
const loginUrl = pxt.Util.stringifyQueryString('/api/auth/login', {
|
|
97989
98003
|
response_type: "token",
|
|
97990
98004
|
provider: idp,
|
|
97991
98005
|
persistent,
|
|
97992
|
-
redirect_uri: `${window.location.origin}${window.location.pathname}?authcallback=1&state=${loginState.key}
|
|
98006
|
+
redirect_uri: `${window.location.origin}${window.location.pathname}?authcallback=1&state=${loginState.key}`,
|
|
98007
|
+
prompt: interactiveLogin ? "select_account" : "silent"
|
|
97993
98008
|
});
|
|
97994
98009
|
const apiResult = await this.apiAsync(loginUrl);
|
|
97995
98010
|
if (apiResult.success) {
|
|
97996
|
-
loginState.authCodeVerifier = apiResult.resp.authCodeVerifier;
|
|
98011
|
+
loginState.authCodeVerifier = apiResult.resp.authCodeVerifier; // will be undefined unless configured for the target
|
|
97997
98012
|
await pxt.storage.shared.setAsync(AUTH_CONTAINER, AUTH_LOGIN_STATE_KEY, loginState);
|
|
97998
98013
|
pxt.tickEvent('auth.login.start', { 'provider': idp });
|
|
97999
98014
|
window.location.href = apiResult.resp.loginUrl;
|
|
@@ -98012,13 +98027,15 @@ var pxt;
|
|
|
98012
98027
|
if (!hasIdentity()) {
|
|
98013
98028
|
return;
|
|
98014
98029
|
}
|
|
98015
|
-
// Clear local auth state so we can no longer make authenticated requests.
|
|
98016
|
-
await this.clearAuthStateAsync();
|
|
98017
98030
|
await AuthClient.staticLogoutAsync(continuationHash);
|
|
98018
98031
|
try {
|
|
98019
|
-
await this.
|
|
98032
|
+
await this.onStateCleared();
|
|
98020
98033
|
}
|
|
98021
98034
|
catch (_a) { }
|
|
98035
|
+
try {
|
|
98036
|
+
await this.onSignedOut();
|
|
98037
|
+
}
|
|
98038
|
+
catch (_b) { }
|
|
98022
98039
|
}
|
|
98023
98040
|
/**
|
|
98024
98041
|
* Sign out the user and clear the auth token cookie.
|
|
@@ -98028,19 +98045,39 @@ var pxt;
|
|
|
98028
98045
|
return;
|
|
98029
98046
|
}
|
|
98030
98047
|
pxt.tickEvent('auth.logout');
|
|
98031
|
-
//
|
|
98048
|
+
// Indicate that for the next minute, signin should be interactive.
|
|
98049
|
+
// Use case: SSO signed in with the wrong account. User wants to sign in with a different account.
|
|
98050
|
+
await setLocalStorageValueAsync(INTERACTIVE_LOGIN_UNTIL, (Date.now() + 60000).toString());
|
|
98051
|
+
continuationHash = continuationHash ? continuationHash.startsWith('#') ? continuationHash : `#${continuationHash}` : "";
|
|
98052
|
+
const clientRedirect = `${window.location.origin}${window.location.pathname}${window.location.search}${continuationHash}`;
|
|
98053
|
+
// Tell backend to clear the http-only auth cookie.
|
|
98054
|
+
let logoutUri = "";
|
|
98032
98055
|
try {
|
|
98033
|
-
|
|
98056
|
+
const uri = pxt.Util.stringifyQueryString('/api/auth/logout', {
|
|
98057
|
+
redirect_uri: clientRedirect,
|
|
98058
|
+
authcallback: '1'
|
|
98059
|
+
});
|
|
98060
|
+
const apiResult = await AuthClient.staticApiAsync(uri);
|
|
98061
|
+
if (apiResult.success) {
|
|
98062
|
+
logoutUri = apiResult.resp.logoutUrl;
|
|
98063
|
+
}
|
|
98064
|
+
}
|
|
98065
|
+
catch (_a) {
|
|
98066
|
+
// Ignore errors.
|
|
98034
98067
|
}
|
|
98035
|
-
catch (_a) { }
|
|
98036
98068
|
// Clear local auth state so we can no longer make authenticated requests.
|
|
98037
98069
|
await delAuthTokenAsync();
|
|
98038
98070
|
await delUserStateAsync();
|
|
98039
|
-
// Redirect to home screen
|
|
98040
98071
|
if (pxt.BrowserUtils.hasWindow()) {
|
|
98041
|
-
|
|
98042
|
-
|
|
98043
|
-
|
|
98072
|
+
if (logoutUri) {
|
|
98073
|
+
// Redirect to logout endpoint
|
|
98074
|
+
window.location.href = logoutUri;
|
|
98075
|
+
}
|
|
98076
|
+
else {
|
|
98077
|
+
// Redirect to home screen
|
|
98078
|
+
window.location.href = clientRedirect;
|
|
98079
|
+
location.reload();
|
|
98080
|
+
}
|
|
98044
98081
|
}
|
|
98045
98082
|
}
|
|
98046
98083
|
async deleteProfileAsync() {
|
|
@@ -98436,6 +98473,8 @@ var pxt;
|
|
|
98436
98473
|
// without its cookie-based counterpart. When "Remember me" is false,
|
|
98437
98474
|
// the cookie is not persisted.
|
|
98438
98475
|
await setAuthTokenAsync(authToken);
|
|
98476
|
+
// Clear interactive login flag. Next auth request will try silent SSO first.
|
|
98477
|
+
await setLocalStorageValueAsync(INTERACTIVE_LOGIN_UNTIL, undefined);
|
|
98439
98478
|
pxt.tickEvent('auth.login.success', { 'provider': loginState.idp });
|
|
98440
98479
|
} while (false);
|
|
98441
98480
|
// Clear url parameters and redirect to the callback location.
|
|
@@ -102460,10 +102499,6 @@ var pxt;
|
|
|
102460
102499
|
return typeof window != "undefined" && !!window.PointerEvent;
|
|
102461
102500
|
}
|
|
102462
102501
|
BrowserUtils.hasPointerEvents = hasPointerEvents;
|
|
102463
|
-
function hasSaveAs() {
|
|
102464
|
-
return isEdge() || isIE() || isFirefox();
|
|
102465
|
-
}
|
|
102466
|
-
BrowserUtils.hasSaveAs = hasSaveAs;
|
|
102467
102502
|
function os() {
|
|
102468
102503
|
if (isWindows())
|
|
102469
102504
|
return "windows";
|
|
@@ -155238,6 +155273,13 @@ var pxsim;
|
|
|
155238
155273
|
}
|
|
155239
155274
|
}
|
|
155240
155275
|
pxsim.Runtime = Runtime;
|
|
155276
|
+
function setParentMuteState(state) {
|
|
155277
|
+
Runtime.postMessage({
|
|
155278
|
+
type: "setmutebuttonstate",
|
|
155279
|
+
state
|
|
155280
|
+
});
|
|
155281
|
+
}
|
|
155282
|
+
pxsim.setParentMuteState = setParentMuteState;
|
|
155241
155283
|
class PerfCounter {
|
|
155242
155284
|
constructor(name) {
|
|
155243
155285
|
this.name = name;
|
|
@@ -155898,8 +155940,19 @@ var pxsim;
|
|
|
155898
155940
|
this.setFrameState(frame);
|
|
155899
155941
|
return true;
|
|
155900
155942
|
}
|
|
155943
|
+
handleDeferredMessages(frame) {
|
|
155944
|
+
var _a, _b, _c;
|
|
155945
|
+
if (frame.dataset["loading"]) {
|
|
155946
|
+
delete frame.dataset["loading"];
|
|
155947
|
+
(_b = (_a = this.deferredMessages) === null || _a === void 0 ? void 0 : _a.filter(defMsg => defMsg[0] === frame)) === null || _b === void 0 ? void 0 : _b.forEach(defMsg => {
|
|
155948
|
+
const [_, msg] = defMsg;
|
|
155949
|
+
this.postMessageCore(frame, msg);
|
|
155950
|
+
});
|
|
155951
|
+
this.deferredMessages = (_c = this.deferredMessages) === null || _c === void 0 ? void 0 : _c.filter(defMsg => defMsg[0] !== frame);
|
|
155952
|
+
}
|
|
155953
|
+
}
|
|
155901
155954
|
handleMessage(msg, source) {
|
|
155902
|
-
var _a, _b, _c
|
|
155955
|
+
var _a, _b, _c;
|
|
155903
155956
|
switch (msg.type || '') {
|
|
155904
155957
|
case 'ready': {
|
|
155905
155958
|
const frameid = msg.frameid;
|
|
@@ -155910,12 +155963,7 @@ var pxsim;
|
|
|
155910
155963
|
this.startFrame(frame);
|
|
155911
155964
|
if (this.options.revealElement)
|
|
155912
155965
|
this.options.revealElement(frame);
|
|
155913
|
-
|
|
155914
|
-
(_c = (_b = this.deferredMessages) === null || _b === void 0 ? void 0 : _b.filter(defMsg => defMsg[0] === frame)) === null || _c === void 0 ? void 0 : _c.forEach(defMsg => {
|
|
155915
|
-
const [_, msg] = defMsg;
|
|
155916
|
-
this.postMessageCore(frame, msg);
|
|
155917
|
-
});
|
|
155918
|
-
this.deferredMessages = (_d = this.deferredMessages) === null || _d === void 0 ? void 0 : _d.filter(defMsg => defMsg[0] !== frame);
|
|
155966
|
+
this.handleDeferredMessages(frame);
|
|
155919
155967
|
}
|
|
155920
155968
|
if (this.options.onSimulatorReady)
|
|
155921
155969
|
this.options.onSimulatorReady();
|
|
@@ -155930,6 +155978,7 @@ var pxsim;
|
|
|
155930
155978
|
switch (stmsg.state) {
|
|
155931
155979
|
case "running":
|
|
155932
155980
|
this.setState(SimulatorState.Running);
|
|
155981
|
+
this.handleDeferredMessages(frame);
|
|
155933
155982
|
break;
|
|
155934
155983
|
case "killed":
|
|
155935
155984
|
this.setState(SimulatorState.Stopped);
|
|
@@ -155966,6 +156015,9 @@ var pxsim;
|
|
|
155966
156015
|
if (this.options.onTopLevelCodeEnd)
|
|
155967
156016
|
this.options.onTopLevelCodeEnd();
|
|
155968
156017
|
break;
|
|
156018
|
+
case 'setmutebuttonstate':
|
|
156019
|
+
(_c = (_b = this.options).onMuteButtonStateChange) === null || _c === void 0 ? void 0 : _c.call(_b, msg.state);
|
|
156020
|
+
break;
|
|
155969
156021
|
default:
|
|
155970
156022
|
this.postMessage(msg, source);
|
|
155971
156023
|
break;
|
|
@@ -156370,6 +156422,10 @@ var pxsim;
|
|
|
156370
156422
|
ctx.resume();
|
|
156371
156423
|
}
|
|
156372
156424
|
AudioContextManager.mute = mute;
|
|
156425
|
+
function isMuted() {
|
|
156426
|
+
return _mute;
|
|
156427
|
+
}
|
|
156428
|
+
AudioContextManager.isMuted = isMuted;
|
|
156373
156429
|
function stopTone() {
|
|
156374
156430
|
setCurrentToneGain(0);
|
|
156375
156431
|
_frequency = 0;
|
package/built/pxteditor.d.ts
CHANGED
|
@@ -36,6 +36,11 @@ declare namespace pxt.editor {
|
|
|
36
36
|
HeaderOnly = "errorListHeader",
|
|
37
37
|
Expanded = "errorListExpanded"
|
|
38
38
|
}
|
|
39
|
+
enum MuteState {
|
|
40
|
+
Muted = "muted",
|
|
41
|
+
Unmuted = "unmuted",
|
|
42
|
+
Disabled = "disabled"
|
|
43
|
+
}
|
|
39
44
|
interface IAppProps {
|
|
40
45
|
}
|
|
41
46
|
interface IAppState {
|
|
@@ -64,7 +69,7 @@ declare namespace pxt.editor {
|
|
|
64
69
|
showParts?: boolean;
|
|
65
70
|
fullscreen?: boolean;
|
|
66
71
|
showMiniSim?: boolean;
|
|
67
|
-
mute?:
|
|
72
|
+
mute?: MuteState;
|
|
68
73
|
embedSimView?: boolean;
|
|
69
74
|
editorPosition?: {
|
|
70
75
|
lineNumber: number;
|
|
@@ -275,7 +280,7 @@ declare namespace pxt.editor {
|
|
|
275
280
|
toggleTrace(intervalSpeed?: number): void;
|
|
276
281
|
setTrace(enabled: boolean, intervalSpeed?: number): void;
|
|
277
282
|
toggleMute(): void;
|
|
278
|
-
setMute(
|
|
283
|
+
setMute(state: MuteState): void;
|
|
279
284
|
openInstructions(): void;
|
|
280
285
|
closeFlyout(): void;
|
|
281
286
|
printCode(): void;
|
package/built/pxteditor.js
CHANGED
|
@@ -19,6 +19,12 @@ var pxt;
|
|
|
19
19
|
ErrorListState["HeaderOnly"] = "errorListHeader";
|
|
20
20
|
ErrorListState["Expanded"] = "errorListExpanded";
|
|
21
21
|
})(ErrorListState = editor.ErrorListState || (editor.ErrorListState = {}));
|
|
22
|
+
let MuteState;
|
|
23
|
+
(function (MuteState) {
|
|
24
|
+
MuteState["Muted"] = "muted";
|
|
25
|
+
MuteState["Unmuted"] = "unmuted";
|
|
26
|
+
MuteState["Disabled"] = "disabled";
|
|
27
|
+
})(MuteState = editor.MuteState || (editor.MuteState = {}));
|
|
22
28
|
let FilterState;
|
|
23
29
|
(function (FilterState) {
|
|
24
30
|
FilterState[FilterState["Hidden"] = 0] = "Hidden";
|
package/built/pxtlib.d.ts
CHANGED
|
@@ -727,7 +727,6 @@ declare namespace pxt.BrowserUtils {
|
|
|
727
727
|
export function noSharedLocalStorage(): boolean;
|
|
728
728
|
export function useOldTutorialLayout(): boolean;
|
|
729
729
|
export function hasPointerEvents(): boolean;
|
|
730
|
-
export function hasSaveAs(): boolean;
|
|
731
730
|
export function os(): string;
|
|
732
731
|
export function browser(): string;
|
|
733
732
|
export function browserVersion(): string;
|
package/built/pxtlib.js
CHANGED
|
@@ -190,6 +190,7 @@ var pxt;
|
|
|
190
190
|
const AUTH_LOGIN_STATE_KEY = "login-state"; // stored in local storage.
|
|
191
191
|
const AUTH_USER_STATE_KEY = "user-state"; // stored in local storage.
|
|
192
192
|
const X_PXT_TARGET = "x-pxt-target"; // header passed in auth rest calls.
|
|
193
|
+
const INTERACTIVE_LOGIN_UNTIL = "interactive-login-until"; // hint whether to prompt user or try SSO first.
|
|
193
194
|
let authDisabled = false;
|
|
194
195
|
auth.DEFAULT_USER_PREFERENCES = () => ({
|
|
195
196
|
highContrast: false,
|
|
@@ -215,19 +216,29 @@ var pxt;
|
|
|
215
216
|
// Last known auth token state. This is provided as a convenience for legacy methods that cannot be made async.
|
|
216
217
|
// Preference hasAuthTokenAsync() over taking a dependency on this cached value.
|
|
217
218
|
auth.cachedHasAuthToken = false;
|
|
218
|
-
async function
|
|
219
|
-
|
|
219
|
+
async function setLocalStorageValueAsync(key, value) {
|
|
220
|
+
if (!!value)
|
|
221
|
+
return await pxt.storage.shared.setAsync(AUTH_CONTAINER, key, value);
|
|
222
|
+
else
|
|
223
|
+
return await pxt.storage.shared.delAsync(AUTH_CONTAINER, key);
|
|
224
|
+
}
|
|
225
|
+
async function getLocalStorageValueAsync(key) {
|
|
220
226
|
try {
|
|
221
|
-
|
|
227
|
+
return await pxt.storage.shared.getAsync(AUTH_CONTAINER, key);
|
|
228
|
+
}
|
|
229
|
+
catch (_a) {
|
|
230
|
+
return undefined;
|
|
222
231
|
}
|
|
223
|
-
|
|
232
|
+
}
|
|
233
|
+
async function getAuthTokenAsync() {
|
|
234
|
+
const token = await getLocalStorageValueAsync(CSRF_TOKEN_KEY);
|
|
224
235
|
auth.cachedHasAuthToken = !!token;
|
|
225
236
|
return token;
|
|
226
237
|
}
|
|
227
238
|
auth.getAuthTokenAsync = getAuthTokenAsync;
|
|
228
239
|
async function setAuthTokenAsync(token) {
|
|
229
240
|
auth.cachedHasAuthToken = !!token;
|
|
230
|
-
return await
|
|
241
|
+
return await setLocalStorageValueAsync(CSRF_TOKEN_KEY, token);
|
|
231
242
|
}
|
|
232
243
|
async function hasAuthTokenAsync() {
|
|
233
244
|
return !!(await getAuthTokenAsync());
|
|
@@ -235,7 +246,7 @@ var pxt;
|
|
|
235
246
|
auth.hasAuthTokenAsync = hasAuthTokenAsync;
|
|
236
247
|
async function delAuthTokenAsync() {
|
|
237
248
|
auth.cachedHasAuthToken = false;
|
|
238
|
-
return await
|
|
249
|
+
return await setLocalStorageValueAsync(CSRF_TOKEN_KEY, undefined);
|
|
239
250
|
}
|
|
240
251
|
async function getUserStateAsync() {
|
|
241
252
|
let userState;
|
|
@@ -298,16 +309,20 @@ var pxt;
|
|
|
298
309
|
idp,
|
|
299
310
|
persistent
|
|
300
311
|
};
|
|
312
|
+
// Should the user be prompted to interactively login, or can we try to silently login?
|
|
313
|
+
const interactiveUntil = parseInt(await getLocalStorageValueAsync(INTERACTIVE_LOGIN_UNTIL));
|
|
314
|
+
const interactiveLogin = (interactiveUntil || 0) > Date.now();
|
|
301
315
|
// Redirect to the login endpoint.
|
|
302
316
|
const loginUrl = pxt.Util.stringifyQueryString('/api/auth/login', {
|
|
303
317
|
response_type: "token",
|
|
304
318
|
provider: idp,
|
|
305
319
|
persistent,
|
|
306
|
-
redirect_uri: `${window.location.origin}${window.location.pathname}?authcallback=1&state=${loginState.key}
|
|
320
|
+
redirect_uri: `${window.location.origin}${window.location.pathname}?authcallback=1&state=${loginState.key}`,
|
|
321
|
+
prompt: interactiveLogin ? "select_account" : "silent"
|
|
307
322
|
});
|
|
308
323
|
const apiResult = await this.apiAsync(loginUrl);
|
|
309
324
|
if (apiResult.success) {
|
|
310
|
-
loginState.authCodeVerifier = apiResult.resp.authCodeVerifier;
|
|
325
|
+
loginState.authCodeVerifier = apiResult.resp.authCodeVerifier; // will be undefined unless configured for the target
|
|
311
326
|
await pxt.storage.shared.setAsync(AUTH_CONTAINER, AUTH_LOGIN_STATE_KEY, loginState);
|
|
312
327
|
pxt.tickEvent('auth.login.start', { 'provider': idp });
|
|
313
328
|
window.location.href = apiResult.resp.loginUrl;
|
|
@@ -326,13 +341,15 @@ var pxt;
|
|
|
326
341
|
if (!hasIdentity()) {
|
|
327
342
|
return;
|
|
328
343
|
}
|
|
329
|
-
// Clear local auth state so we can no longer make authenticated requests.
|
|
330
|
-
await this.clearAuthStateAsync();
|
|
331
344
|
await AuthClient.staticLogoutAsync(continuationHash);
|
|
332
345
|
try {
|
|
333
|
-
await this.
|
|
346
|
+
await this.onStateCleared();
|
|
334
347
|
}
|
|
335
348
|
catch (_a) { }
|
|
349
|
+
try {
|
|
350
|
+
await this.onSignedOut();
|
|
351
|
+
}
|
|
352
|
+
catch (_b) { }
|
|
336
353
|
}
|
|
337
354
|
/**
|
|
338
355
|
* Sign out the user and clear the auth token cookie.
|
|
@@ -342,19 +359,39 @@ var pxt;
|
|
|
342
359
|
return;
|
|
343
360
|
}
|
|
344
361
|
pxt.tickEvent('auth.logout');
|
|
345
|
-
//
|
|
362
|
+
// Indicate that for the next minute, signin should be interactive.
|
|
363
|
+
// Use case: SSO signed in with the wrong account. User wants to sign in with a different account.
|
|
364
|
+
await setLocalStorageValueAsync(INTERACTIVE_LOGIN_UNTIL, (Date.now() + 60000).toString());
|
|
365
|
+
continuationHash = continuationHash ? continuationHash.startsWith('#') ? continuationHash : `#${continuationHash}` : "";
|
|
366
|
+
const clientRedirect = `${window.location.origin}${window.location.pathname}${window.location.search}${continuationHash}`;
|
|
367
|
+
// Tell backend to clear the http-only auth cookie.
|
|
368
|
+
let logoutUri = "";
|
|
346
369
|
try {
|
|
347
|
-
|
|
370
|
+
const uri = pxt.Util.stringifyQueryString('/api/auth/logout', {
|
|
371
|
+
redirect_uri: clientRedirect,
|
|
372
|
+
authcallback: '1'
|
|
373
|
+
});
|
|
374
|
+
const apiResult = await AuthClient.staticApiAsync(uri);
|
|
375
|
+
if (apiResult.success) {
|
|
376
|
+
logoutUri = apiResult.resp.logoutUrl;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch (_a) {
|
|
380
|
+
// Ignore errors.
|
|
348
381
|
}
|
|
349
|
-
catch (_a) { }
|
|
350
382
|
// Clear local auth state so we can no longer make authenticated requests.
|
|
351
383
|
await delAuthTokenAsync();
|
|
352
384
|
await delUserStateAsync();
|
|
353
|
-
// Redirect to home screen
|
|
354
385
|
if (pxt.BrowserUtils.hasWindow()) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
386
|
+
if (logoutUri) {
|
|
387
|
+
// Redirect to logout endpoint
|
|
388
|
+
window.location.href = logoutUri;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// Redirect to home screen
|
|
392
|
+
window.location.href = clientRedirect;
|
|
393
|
+
location.reload();
|
|
394
|
+
}
|
|
358
395
|
}
|
|
359
396
|
}
|
|
360
397
|
async deleteProfileAsync() {
|
|
@@ -750,6 +787,8 @@ var pxt;
|
|
|
750
787
|
// without its cookie-based counterpart. When "Remember me" is false,
|
|
751
788
|
// the cookie is not persisted.
|
|
752
789
|
await setAuthTokenAsync(authToken);
|
|
790
|
+
// Clear interactive login flag. Next auth request will try silent SSO first.
|
|
791
|
+
await setLocalStorageValueAsync(INTERACTIVE_LOGIN_UNTIL, undefined);
|
|
753
792
|
pxt.tickEvent('auth.login.success', { 'provider': loginState.idp });
|
|
754
793
|
} while (false);
|
|
755
794
|
// Clear url parameters and redirect to the callback location.
|
|
@@ -4774,10 +4813,6 @@ var pxt;
|
|
|
4774
4813
|
return typeof window != "undefined" && !!window.PointerEvent;
|
|
4775
4814
|
}
|
|
4776
4815
|
BrowserUtils.hasPointerEvents = hasPointerEvents;
|
|
4777
|
-
function hasSaveAs() {
|
|
4778
|
-
return isEdge() || isIE() || isFirefox();
|
|
4779
|
-
}
|
|
4780
|
-
BrowserUtils.hasSaveAs = hasSaveAs;
|
|
4781
4816
|
function os() {
|
|
4782
4817
|
if (isWindows())
|
|
4783
4818
|
return "windows";
|
package/built/pxtsim.d.ts
CHANGED
|
@@ -556,6 +556,10 @@ declare namespace pxsim {
|
|
|
556
556
|
part: "background-color" | "button-stroke" | "text-color" | "button-fill" | "dpad-fill";
|
|
557
557
|
color: string;
|
|
558
558
|
}
|
|
559
|
+
interface SetMuteButtonStateMessage extends SimulatorMessage {
|
|
560
|
+
type: "setmutebuttonstate";
|
|
561
|
+
state: "muted" | "unmuted" | "disabled";
|
|
562
|
+
}
|
|
559
563
|
namespace multiplayer {
|
|
560
564
|
type MessageBase = {
|
|
561
565
|
type: "multiplayer";
|
|
@@ -1255,6 +1259,7 @@ declare namespace pxsim {
|
|
|
1255
1259
|
cleanScheduledExpired(): void;
|
|
1256
1260
|
registerUserInteraction(): void;
|
|
1257
1261
|
}
|
|
1262
|
+
function setParentMuteState(state: "muted" | "unmuted" | "disabled"): void;
|
|
1258
1263
|
class PerfCounter {
|
|
1259
1264
|
name: string;
|
|
1260
1265
|
start: number;
|
|
@@ -1279,6 +1284,7 @@ declare namespace pxsim {
|
|
|
1279
1284
|
onSimulatorReady?: () => void;
|
|
1280
1285
|
onSimulatorCommand?: (msg: pxsim.SimulatorCommandMessage) => void;
|
|
1281
1286
|
onTopLevelCodeEnd?: () => void;
|
|
1287
|
+
onMuteButtonStateChange?: (state: "muted" | "unmuted" | "disabled") => void;
|
|
1282
1288
|
simUrl?: string;
|
|
1283
1289
|
stoppedClass?: string;
|
|
1284
1290
|
invalidatedClass?: string;
|
|
@@ -1409,6 +1415,7 @@ declare namespace pxsim {
|
|
|
1409
1415
|
areBreakpointsSet(): boolean;
|
|
1410
1416
|
private start;
|
|
1411
1417
|
private startFrame;
|
|
1418
|
+
private handleDeferredMessages;
|
|
1412
1419
|
private handleMessage;
|
|
1413
1420
|
private addEventListeners;
|
|
1414
1421
|
private removeEventListeners;
|
|
@@ -1492,6 +1499,7 @@ declare namespace pxsim {
|
|
|
1492
1499
|
function isAudioElementActive(): boolean;
|
|
1493
1500
|
let soundEventCallback: (ev: "playinstructions" | "muteallchannels", data?: Uint8Array) => void;
|
|
1494
1501
|
function mute(mute: boolean): void;
|
|
1502
|
+
function isMuted(): boolean;
|
|
1495
1503
|
function stopAll(): void;
|
|
1496
1504
|
function stop(): void;
|
|
1497
1505
|
function onStopAll(handler: () => void): void;
|
package/built/pxtsim.js
CHANGED
|
@@ -5992,6 +5992,13 @@ var pxsim;
|
|
|
5992
5992
|
}
|
|
5993
5993
|
}
|
|
5994
5994
|
pxsim.Runtime = Runtime;
|
|
5995
|
+
function setParentMuteState(state) {
|
|
5996
|
+
Runtime.postMessage({
|
|
5997
|
+
type: "setmutebuttonstate",
|
|
5998
|
+
state
|
|
5999
|
+
});
|
|
6000
|
+
}
|
|
6001
|
+
pxsim.setParentMuteState = setParentMuteState;
|
|
5995
6002
|
class PerfCounter {
|
|
5996
6003
|
constructor(name) {
|
|
5997
6004
|
this.name = name;
|
|
@@ -6652,8 +6659,19 @@ var pxsim;
|
|
|
6652
6659
|
this.setFrameState(frame);
|
|
6653
6660
|
return true;
|
|
6654
6661
|
}
|
|
6662
|
+
handleDeferredMessages(frame) {
|
|
6663
|
+
var _a, _b, _c;
|
|
6664
|
+
if (frame.dataset["loading"]) {
|
|
6665
|
+
delete frame.dataset["loading"];
|
|
6666
|
+
(_b = (_a = this.deferredMessages) === null || _a === void 0 ? void 0 : _a.filter(defMsg => defMsg[0] === frame)) === null || _b === void 0 ? void 0 : _b.forEach(defMsg => {
|
|
6667
|
+
const [_, msg] = defMsg;
|
|
6668
|
+
this.postMessageCore(frame, msg);
|
|
6669
|
+
});
|
|
6670
|
+
this.deferredMessages = (_c = this.deferredMessages) === null || _c === void 0 ? void 0 : _c.filter(defMsg => defMsg[0] !== frame);
|
|
6671
|
+
}
|
|
6672
|
+
}
|
|
6655
6673
|
handleMessage(msg, source) {
|
|
6656
|
-
var _a, _b, _c
|
|
6674
|
+
var _a, _b, _c;
|
|
6657
6675
|
switch (msg.type || '') {
|
|
6658
6676
|
case 'ready': {
|
|
6659
6677
|
const frameid = msg.frameid;
|
|
@@ -6664,12 +6682,7 @@ var pxsim;
|
|
|
6664
6682
|
this.startFrame(frame);
|
|
6665
6683
|
if (this.options.revealElement)
|
|
6666
6684
|
this.options.revealElement(frame);
|
|
6667
|
-
|
|
6668
|
-
(_c = (_b = this.deferredMessages) === null || _b === void 0 ? void 0 : _b.filter(defMsg => defMsg[0] === frame)) === null || _c === void 0 ? void 0 : _c.forEach(defMsg => {
|
|
6669
|
-
const [_, msg] = defMsg;
|
|
6670
|
-
this.postMessageCore(frame, msg);
|
|
6671
|
-
});
|
|
6672
|
-
this.deferredMessages = (_d = this.deferredMessages) === null || _d === void 0 ? void 0 : _d.filter(defMsg => defMsg[0] !== frame);
|
|
6685
|
+
this.handleDeferredMessages(frame);
|
|
6673
6686
|
}
|
|
6674
6687
|
if (this.options.onSimulatorReady)
|
|
6675
6688
|
this.options.onSimulatorReady();
|
|
@@ -6684,6 +6697,7 @@ var pxsim;
|
|
|
6684
6697
|
switch (stmsg.state) {
|
|
6685
6698
|
case "running":
|
|
6686
6699
|
this.setState(SimulatorState.Running);
|
|
6700
|
+
this.handleDeferredMessages(frame);
|
|
6687
6701
|
break;
|
|
6688
6702
|
case "killed":
|
|
6689
6703
|
this.setState(SimulatorState.Stopped);
|
|
@@ -6720,6 +6734,9 @@ var pxsim;
|
|
|
6720
6734
|
if (this.options.onTopLevelCodeEnd)
|
|
6721
6735
|
this.options.onTopLevelCodeEnd();
|
|
6722
6736
|
break;
|
|
6737
|
+
case 'setmutebuttonstate':
|
|
6738
|
+
(_c = (_b = this.options).onMuteButtonStateChange) === null || _c === void 0 ? void 0 : _c.call(_b, msg.state);
|
|
6739
|
+
break;
|
|
6723
6740
|
default:
|
|
6724
6741
|
this.postMessage(msg, source);
|
|
6725
6742
|
break;
|
|
@@ -7124,6 +7141,10 @@ var pxsim;
|
|
|
7124
7141
|
ctx.resume();
|
|
7125
7142
|
}
|
|
7126
7143
|
AudioContextManager.mute = mute;
|
|
7144
|
+
function isMuted() {
|
|
7145
|
+
return _mute;
|
|
7146
|
+
}
|
|
7147
|
+
AudioContextManager.isMuted = isMuted;
|
|
7127
7148
|
function stopTone() {
|
|
7128
7149
|
setCurrentToneGain(0);
|
|
7129
7150
|
_frequency = 0;
|