pxt-core 8.2.9 → 8.2.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/pxt.js +40 -20
- package/built/pxtsim.d.ts +9 -0
- package/built/pxtsim.js +40 -20
- 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 +160 -32
- 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 +142 -132
- package/react-common/components/share/SocialButton.tsx +36 -6
- package/react-common/components/share/ThumbnailRecorder.tsx +149 -0
- package/react-common/styles/controls/Button.less +30 -3
- package/react-common/styles/controls/Modal.less +7 -2
- package/react-common/styles/share/share.less +169 -31
- package/react-common/components/share/GifInfo.tsx +0 -63
- package/react-common/components/share/GifRecorder.tsx +0 -97
|
@@ -230,21 +230,30 @@
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
/****************************************************
|
|
233
|
-
*
|
|
233
|
+
* Square Buttons *
|
|
234
234
|
****************************************************/
|
|
235
235
|
|
|
236
|
-
.common-button.
|
|
236
|
+
.common-button.square-button {
|
|
237
237
|
width: 3rem;
|
|
238
238
|
height: 3rem;
|
|
239
239
|
overflow: hidden;
|
|
240
240
|
padding: 0;
|
|
241
|
-
border-radius: 2rem;
|
|
242
241
|
|
|
243
242
|
i, i.fas, i.far {
|
|
244
243
|
margin: 0;
|
|
245
244
|
}
|
|
246
245
|
}
|
|
247
246
|
|
|
247
|
+
|
|
248
|
+
/****************************************************
|
|
249
|
+
* Circle Buttons *
|
|
250
|
+
****************************************************/
|
|
251
|
+
|
|
252
|
+
.common-button.circle-button {
|
|
253
|
+
&:extend(.common-button.square-button);
|
|
254
|
+
border-radius: 2rem;
|
|
255
|
+
}
|
|
256
|
+
|
|
248
257
|
.common-button.circle-button:focus::after {
|
|
249
258
|
border-radius: 2rem;
|
|
250
259
|
}
|
|
@@ -253,6 +262,14 @@
|
|
|
253
262
|
* Social Buttons *
|
|
254
263
|
****************************************************/
|
|
255
264
|
|
|
265
|
+
.common-button.social-button {
|
|
266
|
+
font-size: 1.5rem;
|
|
267
|
+
|
|
268
|
+
img {
|
|
269
|
+
max-width: 100%;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
256
273
|
.common-button.facebook {
|
|
257
274
|
background: #4267B2;
|
|
258
275
|
color: @buttonTextColorDarkBackground;
|
|
@@ -273,6 +290,16 @@
|
|
|
273
290
|
color: @buttonTextColorDarkBackground;
|
|
274
291
|
}
|
|
275
292
|
|
|
293
|
+
.common-button.whatsapp {
|
|
294
|
+
background: #59CE72;
|
|
295
|
+
color: @buttonTextColorDarkBackground;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.common-button.microsoft-teams {
|
|
299
|
+
background: #35258F;
|
|
300
|
+
color: @buttonTextColorDarkBackground;
|
|
301
|
+
}
|
|
302
|
+
|
|
276
303
|
/****************************************************
|
|
277
304
|
* High Contrast *
|
|
278
305
|
****************************************************/
|
|
@@ -23,25 +23,34 @@
|
|
|
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
|
-
|
|
34
|
-
|
|
33
|
+
.project-share-content {
|
|
34
|
+
flex-grow: 1;
|
|
35
|
+
|
|
36
|
+
.name-input .common-input-group {
|
|
37
|
+
height: 3rem;
|
|
38
|
+
margin-bottom: 0.5rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.common-checkbox {
|
|
42
|
+
margin-bottom: 0.5rem;
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
.project-share-title {
|
|
39
|
-
|
|
48
|
+
margin-bottom: 1rem;
|
|
49
|
+
}
|
|
40
50
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
51
|
+
.project-share-label {
|
|
52
|
+
font-weight: 700;
|
|
53
|
+
margin-bottom: 0.5rem;
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
#project-share-dropdown {
|
|
@@ -51,6 +60,9 @@
|
|
|
51
60
|
.project-share-thumbnail {
|
|
52
61
|
display: flex;
|
|
53
62
|
flex-direction: column;
|
|
63
|
+
min-width: 15rem;
|
|
64
|
+
align-items: center;
|
|
65
|
+
margin-right: 1rem;
|
|
54
66
|
|
|
55
67
|
.project-thumbnail-placeholder,
|
|
56
68
|
img {
|
|
@@ -58,6 +70,18 @@
|
|
|
58
70
|
width: 15rem;
|
|
59
71
|
height: 11.25rem;
|
|
60
72
|
background-color: rgba(0, 0, 0, 0.05);
|
|
73
|
+
margin-bottom: 1rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.project-thumbnail-placeholder {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
|
|
81
|
+
.common-spinner {
|
|
82
|
+
width: 5rem;
|
|
83
|
+
height: 5rem;
|
|
84
|
+
}
|
|
61
85
|
}
|
|
62
86
|
}
|
|
63
87
|
|
|
@@ -74,41 +98,40 @@
|
|
|
74
98
|
|
|
75
99
|
.share-publish-button {
|
|
76
100
|
height: 3rem;
|
|
101
|
+
margin-right: 1rem;
|
|
77
102
|
|
|
78
103
|
.common-spinner {
|
|
79
104
|
display: inline-block;
|
|
80
105
|
}
|
|
81
106
|
}
|
|
82
107
|
|
|
108
|
+
|
|
83
109
|
/////////////////////////////////////////
|
|
84
110
|
// Embed //
|
|
85
111
|
/////////////////////////////////////////
|
|
86
112
|
|
|
87
113
|
.project-share-actions {
|
|
88
114
|
display: flex;
|
|
115
|
+
flex-direction: row;
|
|
89
116
|
margin-top: 1rem;
|
|
90
117
|
position: relative;
|
|
91
118
|
margin-bottom: 2rem;
|
|
119
|
+
}
|
|
92
120
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
121
|
+
.project-share-social {
|
|
122
|
+
display: flex;
|
|
123
|
+
flex-direction: row;
|
|
124
|
+
flex-grow: 1;
|
|
125
|
+
flex-wrap: wrap;
|
|
126
|
+
gap: 0.5rem;
|
|
96
127
|
}
|
|
97
128
|
|
|
98
129
|
.project-share-text {
|
|
99
130
|
margin-bottom: 1rem;
|
|
100
131
|
}
|
|
101
132
|
|
|
102
|
-
.common-button.menu-button.project-qrcode {
|
|
103
|
-
|
|
104
|
-
right: 0;
|
|
105
|
-
height: 6rem;
|
|
106
|
-
padding: 0.5rem;
|
|
107
|
-
top: -0.5rem;
|
|
108
|
-
|
|
109
|
-
img {
|
|
110
|
-
height: 5rem;
|
|
111
|
-
}
|
|
133
|
+
.common-button.menu-button.project-qrcode img {
|
|
134
|
+
height: 5rem;
|
|
112
135
|
}
|
|
113
136
|
|
|
114
137
|
.common-button.menu-button.project-qrcode:focus::after {
|
|
@@ -144,19 +167,59 @@
|
|
|
144
167
|
// Gif Recorder //
|
|
145
168
|
/////////////////////////////////////////
|
|
146
169
|
|
|
170
|
+
.gif-recorder-content {
|
|
171
|
+
display: flex;
|
|
172
|
+
flex-direction: row;
|
|
173
|
+
align-items: center;
|
|
174
|
+
|
|
175
|
+
.thumbnail-controls {
|
|
176
|
+
display: flex;
|
|
177
|
+
flex-direction: column;
|
|
178
|
+
padding: 0 4rem;
|
|
179
|
+
|
|
180
|
+
.thumbnail-preview {
|
|
181
|
+
display: flex;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
flex-grow: 1;
|
|
184
|
+
align-items: center;
|
|
185
|
+
|
|
186
|
+
& > div {
|
|
187
|
+
padding-bottom: 1rem;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.thumbnail-image,
|
|
191
|
+
.thumbnail-placeholder {
|
|
192
|
+
display: flex;
|
|
193
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
194
|
+
width: 15rem;
|
|
195
|
+
height: 12.25rem;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.thumbnail-actions {
|
|
200
|
+
display: flex;
|
|
201
|
+
flex-direction: row;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.gif-recorder-sim-embed {
|
|
207
|
+
flex-grow: 1;
|
|
208
|
+
padding-right: 1rem;
|
|
209
|
+
|
|
210
|
+
.simframe {
|
|
211
|
+
padding-bottom: 56.25%!important;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.gif-recorder-sim {
|
|
216
|
+
flex-grow: 1;
|
|
217
|
+
}
|
|
218
|
+
|
|
147
219
|
.gif-recorder {
|
|
148
|
-
position: absolute;
|
|
149
220
|
display: flex;
|
|
150
221
|
flex-direction: column;
|
|
151
222
|
align-items: center;
|
|
152
|
-
|
|
153
|
-
bottom: 0;
|
|
154
|
-
left: calc(~'(100vw - 25rem)/2');
|
|
155
|
-
padding: 1rem;
|
|
156
|
-
transform: translateX(-50%);
|
|
157
|
-
background: @white;
|
|
158
|
-
border: @teal;
|
|
159
|
-
border-radius: 0.2rem;
|
|
160
223
|
font-family: @segoeUIFont;
|
|
161
224
|
}
|
|
162
225
|
|
|
@@ -176,4 +239,79 @@
|
|
|
176
239
|
background-color: rgba(0, 0, 0, 0.05);
|
|
177
240
|
width: 24.5rem;
|
|
178
241
|
height: 18.375rem;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.thumbnail-header {
|
|
245
|
+
display: flex;
|
|
246
|
+
flex-direction: row;
|
|
247
|
+
|
|
248
|
+
.project-share-label {
|
|
249
|
+
flex-grow: 1;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.common-button.link-button {
|
|
253
|
+
margin-bottom: 0.5rem;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
/////////////////////////////////////////
|
|
259
|
+
// Mobile //
|
|
260
|
+
/////////////////////////////////////////
|
|
261
|
+
|
|
262
|
+
#root.miniSim:not(.fullscreensim) .gif-recorder-sim div.simframe {
|
|
263
|
+
width: 100%;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@media @tabletAndBelow {
|
|
267
|
+
.gif-recorder-content .thumbnail-controls {
|
|
268
|
+
padding: 0 2rem;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@media @mobileAndBelow {
|
|
273
|
+
.project-share-info, .gif-recorder-content {
|
|
274
|
+
flex-direction: column;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.gif-recorder-sim {
|
|
278
|
+
width: 100%;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.gif-recorder-actions {
|
|
282
|
+
width: 100%;
|
|
283
|
+
|
|
284
|
+
.spacer {
|
|
285
|
+
flex-grow: 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.gif-recorder-actions .common-button:not(.mobile-only) {
|
|
290
|
+
width: 3rem;
|
|
291
|
+
height: 3rem;
|
|
292
|
+
overflow: hidden;
|
|
293
|
+
padding: 0;
|
|
294
|
+
|
|
295
|
+
i, i.fas, i.far {
|
|
296
|
+
margin: 0;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.common-button-label {
|
|
300
|
+
display: none;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.gif-recorder-content {
|
|
305
|
+
&.has-uri {
|
|
306
|
+
.gif-recorder-sim {
|
|
307
|
+
display: none;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
&:not(.has-uri) {
|
|
312
|
+
.thumbnail-controls {
|
|
313
|
+
display: none;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
179
317
|
}
|
|
@@ -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
|
-
}
|