Skip to content

Commit d298516

Browse files
authored
Add project description to settings editor and share dialog (#11036)
1 parent fc85d27 commit d298516

File tree

11 files changed

+163
-65
lines changed

11 files changed

+163
-65
lines changed

localtypings/pxtarget.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ declare namespace pxt {
540540
enabledFeatures?: pxt.Map<FeatureFlag>;
541541
forceEnableAiErrorHelp?: boolean; // Enables the AI Error Help feature, regardless of geo setting.
542542
shareHomepageContent?: boolean; // Show buttons to share links to homepage content more easily
543+
showProjectDescription?: boolean; // Show project description in pxtjson editor and share dialog
543544
}
544545

545546
interface DownloadDialogTheme {

localtypings/pxteditor.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ declare namespace pxt.editor {
989989

990990
anonymousPublishHeaderByIdAsync(headerId: string, projectName?: string): Promise<ShareData>;
991991
publishCurrentHeaderAsync(persistent: boolean, screenshotUri?: string): Promise<string>;
992-
publishAsync (name: string, screenshotUri?: string, forceAnonymous?: boolean): Promise<ShareData>;
992+
publishAsync (name: string, description?: string,screenshotUri?: string, forceAnonymous?: boolean): Promise<ShareData>;
993993

994994
startStopSimulator(opts?: SimulatorStartOptions): void;
995995
stopSimulator(unload?: boolean, opts?: SimulatorStartOptions): void;

react-common/components/share/Share.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface ShareData {
1818

1919
export interface ShareProps {
2020
projectName: string;
21+
projectDescription?: string;
2122
screenshotUri?: string;
2223
isLoggedIn?: boolean;
2324
hasProjectBeenPersistentShared?: boolean;
@@ -26,13 +27,14 @@ export interface ShareProps {
2627
kind?: "multiplayer" | "vscode" | "share"; // Arcade: Was the share dialog opened specifically for hosting a multiplayer game?
2728
setAnonymousSharePreference?: (anonymousByDefault: boolean) => void;
2829
simRecorder: SimRecorder;
29-
publishAsync: (name: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
30+
publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
3031
onClose: () => void;
3132
}
3233

3334
export const Share = (props: ShareProps) => {
3435
const {
3536
projectName,
37+
projectDescription,
3638
screenshotUri,
3739
isLoggedIn,
3840
simRecorder,
@@ -47,6 +49,7 @@ export const Share = (props: ShareProps) => {
4749

4850
return <div className="project-share">
4951
<ShareInfo projectName={projectName}
52+
projectDescription={projectDescription}
5053
isLoggedIn={isLoggedIn}
5154
screenshotUri={screenshotUri}
5255
simRecorder={simRecorder}

react-common/components/share/ShareInfo.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ const vscodeDevUrl = "https://vscode.dev/edu/makecode/"
2020

2121
export interface ShareInfoProps {
2222
projectName: string;
23-
description?: string;
23+
projectDescription?: string;
2424
screenshotUri?: string;
2525
isLoggedIn?: boolean;
2626
hasProjectBeenPersistentShared?: boolean;
2727
simRecorder: SimRecorder;
28-
publishAsync: (name: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
28+
publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
2929
isMultiplayerGame?: boolean; // Arcade: Does the game being shared have multiplayer enabled?
3030
kind?: "multiplayer" | "vscode" | "share"; // Arcade: Was the share dialog opened specifically for hosting a multiplayer game?
3131
anonymousShareByDefault?: boolean;
@@ -37,7 +37,7 @@ export interface ShareInfoProps {
3737
export const ShareInfo = (props: ShareInfoProps) => {
3838
const {
3939
projectName,
40-
description,
40+
projectDescription,
4141
screenshotUri,
4242
isLoggedIn,
4343
simRecorder,
@@ -50,6 +50,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
5050
onClose,
5151
} = props;
5252
const [ name, setName ] = React.useState(projectName);
53+
const [ description, setDescription ] = React.useState(projectDescription);
5354
const [ thumbnailUri, setThumbnailUri ] = React.useState(screenshotUri);
5455
const [ shareState, setShareState ] = React.useState<"share" | "gifrecord" | "publish" | "publish-vscode" | "publishing">("share");
5556
const [ shareData, setShareData ] = React.useState<ShareData>();
@@ -95,7 +96,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
9596
const handlePublishClick = async () => {
9697
setShareState("publishing");
9798
setLastShareWasAnonymous(isAnonymous);
98-
let publishedShareData = await publishAsync(name, thumbnailUri, isAnonymous);
99+
let publishedShareData = await publishAsync(name, description, thumbnailUri, isAnonymous);
99100
setShareData(publishedShareData);
100101
if (!publishedShareData?.error) setShareState("publish");
101102
else setShareState("share")
@@ -104,7 +105,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
104105
const handlePublishInVscodeClick = async () => {
105106
setShareState("publishing");
106107
setLastShareWasAnonymous(isAnonymous);
107-
let publishedShareData = await publishAsync(name, thumbnailUri, isAnonymous);
108+
let publishedShareData = await publishAsync(name, description, thumbnailUri, isAnonymous);
108109
setShareData(publishedShareData);
109110
if (!publishedShareData?.error) {
110111
setShareState("publish-vscode");
@@ -238,9 +239,9 @@ export const ShareInfo = (props: ShareInfoProps) => {
238239
const handleMultiplayerShareConfirmClick = async () => {
239240
setShareState("publishing");
240241
setIsShowingMultiConfirmation(false);
241-
setLastShareWasAnonymous(isAnonymous);
242+
setLastShareWasAnonymous(isAnonymous);
242243

243-
const publishedShareData = await publishAsync(name, thumbnailUri, isAnonymous);
244+
const publishedShareData = await publishAsync(name, description, thumbnailUri, isAnonymous);
244245

245246
// TODO multiplayer: This won't work on staging (parseScriptId domains check doesn't include staging urls)
246247
// but those wouldn't load anyways (as staging multiplayer is currently fetching games from prod links)
@@ -322,7 +323,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
322323
if (setAnonymousSharePreference) setAnonymousSharePreference(!newValue);
323324
}
324325

325-
const inputTitle = prePublish ? lf("Project Title") :
326+
const inputTitle = prePublish ? lf("Project Name") :
326327
(shareState === "publish-vscode" ? lf("Share Successful") : lf("Project Link"));
327328

328329
const shareAttemptWasAnonymous = lastShareWasAnonymous === undefined ? isAnonymous : lastShareWasAnonymous;
@@ -378,6 +379,19 @@ export const ShareInfo = (props: ShareInfoProps) => {
378379
onBlur={setName}
379380
onEnterKey={setName}
380381
preserveValueOnBlur={true} />
382+
{pxt.appTarget.appTheme.showProjectDescription && <>
383+
<div className="project-share-title project-share-label" id="share-description-title">
384+
{lf("Project Description")}
385+
</div>
386+
<Textarea
387+
ariaDescribedBy="share-description-title"
388+
ariaLabel={lf("Type a description for your project")}
389+
initialValue={projectDescription || ''}
390+
onChange={setDescription}
391+
id="projectDescriptionTextareaShare"
392+
resize="vertical"
393+
/>
394+
</>}
381395
{isLoggedIn && hasProjectBeenPersistentShared && <Checkbox
382396
id="persistent-share-checkbox"
383397
label={lf("Update existing share link for this project")}

react-common/styles/controls/Textarea.less

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
pointer-events: none;
2222
}
2323

24+
.common-textarea-wrapper {
25+
&.resize-both .common-textarea { resize: both; }
26+
&.resize-horizontal .common-textarea { resize: horizontal; }
27+
&.resize-vertical .common-textarea { resize: vertical; }
28+
}
29+
2430
.common-textarea {
2531
width: 100%;
2632
min-width: 0;
@@ -32,10 +38,7 @@
3238
background: none transparent;
3339
text-overflow: ellipsis;
3440
resize: none;
35-
36-
&.resize-both { resize: both; }
37-
&.resize-horizontal { resize: horizontal; }
38-
&.resize-vertical { resize: vertical; }
41+
min-height: 5rem;
3942
}
4043

4144

react-common/styles/share/share.less

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@
5555
.common-editor-toggle-outer {
5656
z-index: 1;
5757
}
58+
59+
.common-textarea {
60+
max-height: 12rem;
61+
}
62+
63+
.common-textarea-wrapper {
64+
margin-bottom: 1rem;
65+
}
5866
}
5967
}
6068

theme/pxt.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
@import 'asset-editor';
3030
@import 'semantic-ui-overrides';
3131
@import 'ai-error-explanation-text';
32+
@import 'pxtjson';
3233

3334
@import 'light';
3435
@import 'accessibility';

theme/pxtjson.less

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.pxt-json-settings {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 0.5rem;
5+
}

webapp/src/app.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4445,10 +4445,10 @@ export class ProjectView
44454445
return this.getShareUrl(script.shortid || script.id, false);
44464446
}
44474447

4448-
async publishAsync (name: string, screenshotUri?: string, forceAnonymous?: boolean): Promise<pxt.editor.ShareData> {
4448+
async publishAsync (name: string, description?: string,screenshotUri?: string, forceAnonymous?: boolean): Promise<pxt.editor.ShareData> {
44494449
pxt.tickEvent("menu.embed.publish", undefined, { interactiveConsent: true });
4450-
if (name && this.state.projectName != name) {
4451-
await this.updateHeaderNameAsync(name);
4450+
if ((name && this.state.projectName != name) || description) {
4451+
await this.updateHeaderNameAsync(name, description);
44524452
}
44534453

44544454
const hasIdentity = auth.hasIdentity() && this.isLoggedIn();
@@ -4595,13 +4595,14 @@ export class ProjectView
45954595
}
45964596
}
45974597

4598-
updateHeaderNameAsync(name: string): Promise<void> {
4598+
updateHeaderNameAsync(name: string, description?: string): Promise<void> {
45994599
// nothing to do?
4600-
if (pkg.mainPkg.config.name == name)
4600+
if (pkg.mainPkg.config.name == name && (!description || pkg.mainPkg.config.description == description))
46014601
return Promise.resolve();
46024602

46034603
//Save the name in the target MainPackage as well
46044604
pkg.mainPkg.config.name = name;
4605+
pkg.mainPkg.config.description = description || pkg.mainPkg.config.description;
46054606

46064607
pxt.debug('saving project name to ' + name);
46074608
let f = pkg.mainEditorPkg().lookupFile("this/" + pxt.CONFIG_NAME);

0 commit comments

Comments
 (0)