pxt-core 8.2.9 → 8.2.10
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 +6 -9
- package/built/pxtsim.js +6 -9
- package/built/target.js +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +1 -1
- package/built/web/pxtembed.js +1 -1
- package/built/web/pxtsim.js +1 -1
- package/built/web/react-common-authcode.css +83 -13
- package/built/web/react-common-skillmap.css +1 -1
- package/built/web/rtlreact-common-skillmap.css +1 -1
- package/built/web/rtlsemantic.css +1 -1
- package/built/web/semantic.css +1 -1
- package/package.json +1 -1
- package/react-common/components/share/Share.tsx +8 -21
- package/react-common/components/share/ShareInfo.tsx +136 -132
- package/react-common/components/share/SocialButton.tsx +36 -6
- package/react-common/components/share/ThumbnailRecorder.tsx +137 -0
- package/react-common/styles/controls/Button.less +30 -3
- package/react-common/styles/controls/Modal.less +6 -1
- package/react-common/styles/share/share.less +63 -7
- package/react-common/components/share/GifInfo.tsx +0 -63
- package/react-common/components/share/GifRecorder.tsx +0 -97
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
@media @mobileAndBelow {
|
|
28
|
-
.common-modal {
|
|
28
|
+
.common-modal, .wide > .common-modal {
|
|
29
29
|
width: 95%;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -121,6 +121,11 @@
|
|
|
121
121
|
max-height: unset;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
.wide > .common-modal {
|
|
125
|
+
width: 75%;
|
|
126
|
+
max-width: 60rem;
|
|
127
|
+
}
|
|
128
|
+
|
|
124
129
|
/****************************************************
|
|
125
130
|
* High Contrast *
|
|
126
131
|
****************************************************/
|
|
@@ -23,24 +23,37 @@
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
.project-share-info {
|
|
27
28
|
display: flex;
|
|
28
|
-
flex-direction:
|
|
29
|
+
flex-direction: row;
|
|
29
30
|
justify-content: center;
|
|
30
31
|
flex: 1;
|
|
31
32
|
|
|
32
33
|
> div {
|
|
33
34
|
margin-bottom: 1rem;
|
|
34
|
-
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.project-share-content {
|
|
38
|
+
flex-grow: 1;
|
|
39
|
+
|
|
40
|
+
.name-input .common-input-group {
|
|
41
|
+
height: 3rem;
|
|
42
|
+
margin-bottom: 0.5rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.common-checkbox {
|
|
46
|
+
margin-bottom: 0.5rem;
|
|
47
|
+
}
|
|
35
48
|
}
|
|
36
49
|
}
|
|
37
50
|
|
|
38
51
|
.project-share-title {
|
|
39
|
-
|
|
52
|
+
margin-bottom: 1rem;
|
|
40
53
|
|
|
41
54
|
h2 {
|
|
42
|
-
flex: 1;
|
|
43
55
|
margin: 0;
|
|
56
|
+
margin-bottom: 0.5rem
|
|
44
57
|
}
|
|
45
58
|
}
|
|
46
59
|
|
|
@@ -51,6 +64,9 @@
|
|
|
51
64
|
.project-share-thumbnail {
|
|
52
65
|
display: flex;
|
|
53
66
|
flex-direction: column;
|
|
67
|
+
min-width: 15rem;
|
|
68
|
+
align-items: center;
|
|
69
|
+
margin-right: 1rem;
|
|
54
70
|
|
|
55
71
|
.project-thumbnail-placeholder,
|
|
56
72
|
img {
|
|
@@ -58,6 +74,7 @@
|
|
|
58
74
|
width: 15rem;
|
|
59
75
|
height: 11.25rem;
|
|
60
76
|
background-color: rgba(0, 0, 0, 0.05);
|
|
77
|
+
margin-bottom: 1rem;
|
|
61
78
|
}
|
|
62
79
|
}
|
|
63
80
|
|
|
@@ -74,6 +91,7 @@
|
|
|
74
91
|
|
|
75
92
|
.share-publish-button {
|
|
76
93
|
height: 3rem;
|
|
94
|
+
margin-right: 1rem;
|
|
77
95
|
|
|
78
96
|
.common-spinner {
|
|
79
97
|
display: inline-block;
|
|
@@ -91,7 +109,7 @@
|
|
|
91
109
|
margin-bottom: 2rem;
|
|
92
110
|
|
|
93
111
|
.common-button {
|
|
94
|
-
margin-right:
|
|
112
|
+
margin-right: 0.5rem;
|
|
95
113
|
}
|
|
96
114
|
}
|
|
97
115
|
|
|
@@ -144,14 +162,52 @@
|
|
|
144
162
|
// Gif Recorder //
|
|
145
163
|
/////////////////////////////////////////
|
|
146
164
|
|
|
165
|
+
.gif-recorder-content {
|
|
166
|
+
display: flex;
|
|
167
|
+
flex-direction: row;
|
|
168
|
+
|
|
169
|
+
.thumbnail-controls {
|
|
170
|
+
display: flex;
|
|
171
|
+
flex-direction: column;
|
|
172
|
+
|
|
173
|
+
.thumbnail-preview {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-direction: column;
|
|
176
|
+
flex-grow: 1;
|
|
177
|
+
align-items: center;
|
|
178
|
+
|
|
179
|
+
& > div {
|
|
180
|
+
padding-bottom: 1rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.thumbnail-image,
|
|
184
|
+
.thumbnail-placeholder {
|
|
185
|
+
display: flex;
|
|
186
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
187
|
+
width: 10rem;
|
|
188
|
+
height: 7.5rem;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.gif-recorder-sim-embed {
|
|
195
|
+
flex-grow: 1;
|
|
196
|
+
padding-right: 1rem;
|
|
197
|
+
|
|
198
|
+
.simframe {
|
|
199
|
+
padding-bottom: 56.25%!important;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
147
203
|
.gif-recorder {
|
|
148
204
|
position: absolute;
|
|
149
205
|
display: flex;
|
|
150
206
|
flex-direction: column;
|
|
151
207
|
align-items: center;
|
|
152
208
|
|
|
153
|
-
bottom:
|
|
154
|
-
left:
|
|
209
|
+
bottom: 1rem;
|
|
210
|
+
left: 50vw;
|
|
155
211
|
padding: 1rem;
|
|
156
212
|
transform: translateX(-50%);
|
|
157
213
|
background: @white;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Button } from "../controls/Button";
|
|
3
|
-
import { GifRecorder } from "./GifRecorder";
|
|
4
|
-
|
|
5
|
-
export interface GifInfoProps {
|
|
6
|
-
initialUri?: string;
|
|
7
|
-
|
|
8
|
-
onApply: (uri: string) => void;
|
|
9
|
-
onCancel: () => void;
|
|
10
|
-
|
|
11
|
-
screenshotAsync?: () => Promise<string>;
|
|
12
|
-
gifRecordAsync?: () => Promise<void>;
|
|
13
|
-
gifRenderAsync?: () => Promise<string | void>;
|
|
14
|
-
gifAddFrame?: (dataUri: ImageData, delay?: number) => boolean;
|
|
15
|
-
|
|
16
|
-
registerSimulatorMsgHandler?: (handler: (msg: any) => void) => void;
|
|
17
|
-
unregisterSimulatorMsgHandler?: () => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const GifInfo = (props: GifInfoProps) => {
|
|
21
|
-
const { initialUri, onApply, onCancel, screenshotAsync, gifRecordAsync, gifRenderAsync, gifAddFrame,
|
|
22
|
-
registerSimulatorMsgHandler, unregisterSimulatorMsgHandler } = props;
|
|
23
|
-
const [ uri, setUri ] = React.useState(initialUri);
|
|
24
|
-
|
|
25
|
-
const handleApplyClick = (evt?: any) => {
|
|
26
|
-
onApply(uri);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const handleScreenshotClick = async () => {
|
|
30
|
-
const screenshotUri = await screenshotAsync();
|
|
31
|
-
setUri(screenshotUri);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const handleRecordStopClick = async () => {
|
|
35
|
-
const gifUri = await gifRenderAsync();
|
|
36
|
-
if (gifUri) setUri(gifUri);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return <>
|
|
40
|
-
<span className="thumbnail-label">{lf("Current Thumbnail")}</span>
|
|
41
|
-
<div className="thumbnail-image">
|
|
42
|
-
{uri
|
|
43
|
-
? <img src={uri} />
|
|
44
|
-
: <div className="thumbnail-placeholder" />
|
|
45
|
-
}
|
|
46
|
-
</div>
|
|
47
|
-
<div className="thumbnail-actions">
|
|
48
|
-
<Button className="primary"
|
|
49
|
-
title={lf("Apply")}
|
|
50
|
-
label={lf("Apply")}
|
|
51
|
-
onClick={handleApplyClick} />
|
|
52
|
-
<Button title={lf("Cancel")}
|
|
53
|
-
label={lf("Cancel")}
|
|
54
|
-
onClick={onCancel} />
|
|
55
|
-
</div>
|
|
56
|
-
<GifRecorder onScreenshot={screenshotAsync ? handleScreenshotClick : undefined}
|
|
57
|
-
onRecordStart={gifRecordAsync}
|
|
58
|
-
onRecordStop={handleRecordStopClick}
|
|
59
|
-
onGifFrame={gifAddFrame}
|
|
60
|
-
registerSimulatorMsgHandler={registerSimulatorMsgHandler}
|
|
61
|
-
unregisterSimulatorMsgHandler={unregisterSimulatorMsgHandler} />
|
|
62
|
-
</>
|
|
63
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Button } from "../controls/Button";
|
|
3
|
-
|
|
4
|
-
type RecorderState = "default" | "recording" | "rendering";
|
|
5
|
-
|
|
6
|
-
export interface GifRecorderProps {
|
|
7
|
-
onScreenshot?: () => void;
|
|
8
|
-
onRecordStart?: () => void;
|
|
9
|
-
onRecordStop?: () => Promise<void>;
|
|
10
|
-
onGifFrame?: (dataUri: ImageData, delay?: number) => boolean;
|
|
11
|
-
registerSimulatorMsgHandler?: (handler: (msg: any) => void) => void;
|
|
12
|
-
unregisterSimulatorMsgHandler?: () => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const GifRecorder = (props: GifRecorderProps) => {
|
|
16
|
-
const { onScreenshot, onRecordStart, onRecordStop, onGifFrame,
|
|
17
|
-
registerSimulatorMsgHandler, unregisterSimulatorMsgHandler } = props;
|
|
18
|
-
const [ recorderState, _setRecorderState ] = React.useState<RecorderState>("default");
|
|
19
|
-
const recorderStateRef = React.useRef(recorderState);
|
|
20
|
-
const targetTheme = pxt.appTarget.appTheme;
|
|
21
|
-
|
|
22
|
-
const setRecorderState = (state: RecorderState) => {
|
|
23
|
-
_setRecorderState(state);
|
|
24
|
-
recorderStateRef.current = state;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const onGifRecordStop = async () => {
|
|
28
|
-
setRecorderState("rendering");
|
|
29
|
-
await onRecordStop();
|
|
30
|
-
setRecorderState("default");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
34
|
-
const pressed = e.key.toLocaleLowerCase();
|
|
35
|
-
if (targetTheme.simScreenshotKey && pressed === targetTheme.simScreenshotKey.toLocaleLowerCase()) {
|
|
36
|
-
onScreenshot();
|
|
37
|
-
} else if (targetTheme.simGifKey && pressed === targetTheme.simGifKey.toLocaleLowerCase()) {
|
|
38
|
-
if (recorderStateRef.current === "recording") {
|
|
39
|
-
onGifRecordStop();
|
|
40
|
-
} else {
|
|
41
|
-
onGifRecordStart();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const handleSimulatorMsg = (e: any) => {
|
|
47
|
-
if (e.type === "screenshot") {
|
|
48
|
-
if (recorderStateRef.current === "recording") {
|
|
49
|
-
// Adds frame, returns true if we've exceeded the max frame count
|
|
50
|
-
if (onGifFrame(e.data, e.delay)) {
|
|
51
|
-
onGifRecordStop();
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
onScreenshot();
|
|
55
|
-
}
|
|
56
|
-
} else if (e.event === "start") {
|
|
57
|
-
onGifRecordStart();
|
|
58
|
-
} else if (e.event === "stop") {
|
|
59
|
-
onGifRecordStop();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
React.useEffect(() => {
|
|
64
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
65
|
-
if (registerSimulatorMsgHandler) registerSimulatorMsgHandler(handleSimulatorMsg);
|
|
66
|
-
|
|
67
|
-
return () => {
|
|
68
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
69
|
-
if (unregisterSimulatorMsgHandler) unregisterSimulatorMsgHandler();
|
|
70
|
-
}
|
|
71
|
-
}, []);
|
|
72
|
-
|
|
73
|
-
const onGifRecordStart = () => {
|
|
74
|
-
setRecorderState("recording");
|
|
75
|
-
onRecordStart();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const screenshotLabel = lf("Take screenshot ({0})", targetTheme.simScreenshotKey);
|
|
79
|
-
const startRecordingLabel = lf("Record game play ({0})", targetTheme.simGifKey);
|
|
80
|
-
const stopRecordingLabel = lf("Stop recording ({0})", targetTheme.simGifKey) ;
|
|
81
|
-
|
|
82
|
-
return <div className="gif-recorder">
|
|
83
|
-
<div className="gif-recorder-label">{lf("Pick your project thumbnail")}</div>
|
|
84
|
-
<div className="gif-recorder-actions">
|
|
85
|
-
{!!onScreenshot && <Button className="teal inverted"
|
|
86
|
-
title={screenshotLabel}
|
|
87
|
-
label={screenshotLabel}
|
|
88
|
-
leftIcon="fas fa-camera"
|
|
89
|
-
onClick={onScreenshot} />}
|
|
90
|
-
{!!onRecordStart && <Button className="teal inverted"
|
|
91
|
-
title={recorderState === "recording" ? stopRecordingLabel : startRecordingLabel}
|
|
92
|
-
label={recorderState === "recording" ? stopRecordingLabel : startRecordingLabel}
|
|
93
|
-
leftIcon={`fas fa-${recorderState === "recording" ? "square" : "circle"}`}
|
|
94
|
-
onClick={recorderState === "recording" ? onGifRecordStop : onGifRecordStart} />}
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
}
|