Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions localtypings/pxtarget.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ declare namespace pxt {
enabledFeatures?: pxt.Map<FeatureFlag>;
forceEnableAiErrorHelp?: boolean; // Enables the AI Error Help feature, regardless of geo setting.
shareHomepageContent?: boolean; // Show buttons to share links to homepage content more easily
showProjectDescription?: boolean; // Show project description in pxtjson editor and share dialog
}

interface DownloadDialogTheme {
Expand Down
2 changes: 1 addition & 1 deletion localtypings/pxteditor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ declare namespace pxt.editor {

anonymousPublishHeaderByIdAsync(headerId: string, projectName?: string): Promise<ShareData>;
publishCurrentHeaderAsync(persistent: boolean, screenshotUri?: string): Promise<string>;
publishAsync (name: string, screenshotUri?: string, forceAnonymous?: boolean): Promise<ShareData>;
publishAsync (name: string, description?: string,screenshotUri?: string, forceAnonymous?: boolean): Promise<ShareData>;

startStopSimulator(opts?: SimulatorStartOptions): void;
stopSimulator(unload?: boolean, opts?: SimulatorStartOptions): void;
Expand Down
5 changes: 4 additions & 1 deletion react-common/components/share/Share.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface ShareData {

export interface ShareProps {
projectName: string;
projectDescription?: string;
screenshotUri?: string;
isLoggedIn?: boolean;
hasProjectBeenPersistentShared?: boolean;
Expand All @@ -26,13 +27,14 @@ export interface ShareProps {
kind?: "multiplayer" | "vscode" | "share"; // Arcade: Was the share dialog opened specifically for hosting a multiplayer game?
setAnonymousSharePreference?: (anonymousByDefault: boolean) => void;
simRecorder: SimRecorder;
publishAsync: (name: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
onClose: () => void;
}

export const Share = (props: ShareProps) => {
const {
projectName,
projectDescription,
screenshotUri,
isLoggedIn,
simRecorder,
Expand All @@ -47,6 +49,7 @@ export const Share = (props: ShareProps) => {

return <div className="project-share">
<ShareInfo projectName={projectName}
projectDescription={projectDescription}
isLoggedIn={isLoggedIn}
screenshotUri={screenshotUri}
simRecorder={simRecorder}
Expand Down
30 changes: 22 additions & 8 deletions react-common/components/share/ShareInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ const vscodeDevUrl = "https://vscode.dev/edu/makecode/"

export interface ShareInfoProps {
projectName: string;
description?: string;
projectDescription?: string;
screenshotUri?: string;
isLoggedIn?: boolean;
hasProjectBeenPersistentShared?: boolean;
simRecorder: SimRecorder;
publishAsync: (name: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
isMultiplayerGame?: boolean; // Arcade: Does the game being shared have multiplayer enabled?
kind?: "multiplayer" | "vscode" | "share"; // Arcade: Was the share dialog opened specifically for hosting a multiplayer game?
anonymousShareByDefault?: boolean;
Expand All @@ -37,7 +37,7 @@ export interface ShareInfoProps {
export const ShareInfo = (props: ShareInfoProps) => {
const {
projectName,
description,
projectDescription,
screenshotUri,
isLoggedIn,
simRecorder,
Expand All @@ -50,6 +50,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
onClose,
} = props;
const [ name, setName ] = React.useState(projectName);
const [ description, setDescription ] = React.useState(projectDescription);
const [ thumbnailUri, setThumbnailUri ] = React.useState(screenshotUri);
const [ shareState, setShareState ] = React.useState<"share" | "gifrecord" | "publish" | "publish-vscode" | "publishing">("share");
const [ shareData, setShareData ] = React.useState<ShareData>();
Expand Down Expand Up @@ -95,7 +96,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
const handlePublishClick = async () => {
setShareState("publishing");
setLastShareWasAnonymous(isAnonymous);
let publishedShareData = await publishAsync(name, thumbnailUri, isAnonymous);
let publishedShareData = await publishAsync(name, description, thumbnailUri, isAnonymous);
setShareData(publishedShareData);
if (!publishedShareData?.error) setShareState("publish");
else setShareState("share")
Expand All @@ -104,7 +105,7 @@ export const ShareInfo = (props: ShareInfoProps) => {
const handlePublishInVscodeClick = async () => {
setShareState("publishing");
setLastShareWasAnonymous(isAnonymous);
let publishedShareData = await publishAsync(name, thumbnailUri, isAnonymous);
let publishedShareData = await publishAsync(name, description, thumbnailUri, isAnonymous);
setShareData(publishedShareData);
if (!publishedShareData?.error) {
setShareState("publish-vscode");
Expand Down Expand Up @@ -238,9 +239,9 @@ export const ShareInfo = (props: ShareInfoProps) => {
const handleMultiplayerShareConfirmClick = async () => {
setShareState("publishing");
setIsShowingMultiConfirmation(false);
setLastShareWasAnonymous(isAnonymous);
setLastShareWasAnonymous(isAnonymous);

const publishedShareData = await publishAsync(name, thumbnailUri, isAnonymous);
const publishedShareData = await publishAsync(name, description, thumbnailUri, isAnonymous);

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

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

const shareAttemptWasAnonymous = lastShareWasAnonymous === undefined ? isAnonymous : lastShareWasAnonymous;
Expand Down Expand Up @@ -378,6 +379,19 @@ export const ShareInfo = (props: ShareInfoProps) => {
onBlur={setName}
onEnterKey={setName}
preserveValueOnBlur={true} />
{pxt.appTarget.appTheme.showProjectDescription && <>
<div className="project-share-title project-share-label" id="share-description-title">
{lf("Project Description")}
</div>
<Textarea
ariaDescribedBy="share-description-title"
ariaLabel={lf("Type a description for your project")}
initialValue={projectDescription || ''}
onChange={setDescription}
id="projectDescriptionTextareaShare"
resize="vertical"
/>
</>}
{isLoggedIn && hasProjectBeenPersistentShared && <Checkbox
id="persistent-share-checkbox"
label={lf("Update existing share link for this project")}
Expand Down
11 changes: 7 additions & 4 deletions react-common/styles/controls/Textarea.less
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
pointer-events: none;
}

.common-textarea-wrapper {
&.resize-both .common-textarea { resize: both; }
&.resize-horizontal .common-textarea { resize: horizontal; }
&.resize-vertical .common-textarea { resize: vertical; }
}

.common-textarea {
width: 100%;
min-width: 0;
Expand All @@ -32,10 +38,7 @@
background: none transparent;
text-overflow: ellipsis;
resize: none;

&.resize-both { resize: both; }
&.resize-horizontal { resize: horizontal; }
&.resize-vertical { resize: vertical; }
min-height: 5rem;
}


Expand Down
8 changes: 8 additions & 0 deletions react-common/styles/share/share.less
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@
.common-editor-toggle-outer {
z-index: 1;
}

.common-textarea {
max-height: 12rem;
}

.common-textarea-wrapper {
margin-bottom: 1rem;
}
}
}

Expand Down
1 change: 1 addition & 0 deletions theme/pxt.less
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
@import 'asset-editor';
@import 'semantic-ui-overrides';
@import 'ai-error-explanation-text';
@import 'pxtjson';

@import 'light';
@import 'accessibility';
Expand Down
5 changes: 5 additions & 0 deletions theme/pxtjson.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.pxt-json-settings {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
11 changes: 6 additions & 5 deletions webapp/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4445,10 +4445,10 @@ export class ProjectView
return this.getShareUrl(script.shortid || script.id, false);
}

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

const hasIdentity = auth.hasIdentity() && this.isLoggedIn();
Expand Down Expand Up @@ -4595,13 +4595,14 @@ export class ProjectView
}
}

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

//Save the name in the target MainPackage as well
pkg.mainPkg.config.name = name;
pkg.mainPkg.config.description = description || pkg.mainPkg.config.description;

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