From 31b04afb9449f2c484391325a201b641938fb3e0 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Sat, 26 Aug 2023 22:53:42 +0200 Subject: [PATCH 1/7] Website: Implements source=latest-dev and source=latest --- website/src/website/components/Loader.tsx | 40 +++++++++++++++++++ .../components/monaco/MonacoLoader.tsx | 1 + .../pages/playground/PlaygroundModel.ts | 14 +++++++ .../pages/playground/PlaygroundPage.tsx | 11 +++++ .../pages/playground/getNpmVersionsSync.ts | 7 +++- 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 website/src/website/components/Loader.tsx diff --git a/website/src/website/components/Loader.tsx b/website/src/website/components/Loader.tsx new file mode 100644 index 0000000000..236aa75cc2 --- /dev/null +++ b/website/src/website/components/Loader.tsx @@ -0,0 +1,40 @@ +import * as React from "react"; +export class Loader extends React.Component< + { children: (value: T) => React.ReactChild; loader: () => Promise }, + { value: T | undefined; hasValue: boolean } +> { + constructor(props: any) { + super(props); + this.state = { value: undefined, hasValue: false }; + if (!this.state.value) { + this.props.loader().then((value) => { + this.setState({ + hasValue: true, + value, + }); + }); + } + } + + render() { + if (!this.state.hasValue) { + return null; + } + return this.props.children(this.state.value!); + } +} + +/** + * Decorates a component so that it only gets mounted when monaco is loaded. + */ +export function withLoader( + loader: () => Promise +): ( + Component: React.FunctionComponent | React.ComponentClass +) => any { + return (Component) => { + return (props: any) => ( + {() => } + ); + }; +} diff --git a/website/src/website/components/monaco/MonacoLoader.tsx b/website/src/website/components/monaco/MonacoLoader.tsx index 446654177f..61ea1c46c7 100644 --- a/website/src/website/components/monaco/MonacoLoader.tsx +++ b/website/src/website/components/monaco/MonacoLoader.tsx @@ -26,6 +26,7 @@ export class MonacoLoader extends React.Component< return this.props.children(this.state.monaco); } } + /** * Decorates a component so that it only gets mounted when monaco is loaded. */ diff --git a/website/src/website/pages/playground/PlaygroundModel.ts b/website/src/website/pages/playground/PlaygroundModel.ts index c21bfa313a..7096c30626 100644 --- a/website/src/website/pages/playground/PlaygroundModel.ts +++ b/website/src/website/pages/playground/PlaygroundModel.ts @@ -666,6 +666,20 @@ class Source { sourceStr: string | undefined, sourceLanguagesStr: string | undefined ): Source { + if (sourceStr === "latest-dev") { + // The versions are already loaded + const versions = getNpmVersionsSync(undefined); + const version = versions.find((v) => v.indexOf("-dev-") !== -1); + return new Source(version, undefined, sourceLanguagesStr); + } + if (sourceStr === "latest") { + return new Source( + monacoEditorVersion, + undefined, + sourceLanguagesStr + ); + } + if (sourceStr && sourceStr.startsWith("v")) { return new Source( sourceStr.substring(1), diff --git a/website/src/website/pages/playground/PlaygroundPage.tsx b/website/src/website/pages/playground/PlaygroundPage.tsx index 49a06f826b..fc6f6fbf96 100644 --- a/website/src/website/pages/playground/PlaygroundPage.tsx +++ b/website/src/website/pages/playground/PlaygroundPage.tsx @@ -3,7 +3,18 @@ import * as React from "react"; import { hotComponent } from "../../utils/hotComponent"; import { PlaygroundModel } from "./PlaygroundModel"; import { PlaygroundPageContent } from "./PlaygroundPageContent"; +import { withLoader } from "../../components/Loader"; +import { getNpmVersions } from "./getNpmVersionsSync"; +@withLoader(async () => { + if ( + new URLSearchParams(window.location.search).get("source") === + "latest-dev" + ) { + // So that the source class can resolve that value + await getNpmVersions(); + } +}) @hotComponent(module) @observer export class PlaygroundPage extends React.Component { diff --git a/website/src/website/pages/playground/getNpmVersionsSync.ts b/website/src/website/pages/playground/getNpmVersionsSync.ts index f1489039f0..7837b5f312 100644 --- a/website/src/website/pages/playground/getNpmVersionsSync.ts +++ b/website/src/website/pages/playground/getNpmVersionsSync.ts @@ -6,7 +6,7 @@ export function getNpmVersionsSync( currentVersion: string | undefined ): string[] { if (!npmVersionsObservable) { - npmVersionsObservable = new ObservablePromise(getNpmVersions()); + npmVersionsObservable = new ObservablePromise(loadNpmVersions()); } return ( npmVersionsObservable.value || (currentVersion ? [currentVersion] : []) @@ -16,6 +16,11 @@ export function getNpmVersionsSync( let npmVersionsPromise: Promise | undefined; export async function getNpmVersions(): Promise { + getNpmVersionsSync(undefined); + return npmVersionsPromise!; +} + +async function loadNpmVersions(): Promise { if (npmVersionsPromise === undefined) { npmVersionsPromise = _getNpmVersions(); } From 04ece428811cf1ce24546014c6a4915b2496295c Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Mon, 28 Aug 2023 20:48:44 +0200 Subject: [PATCH 2/7] Adds "use latest dev" button --- .../pages/playground/PlaygroundModel.ts | 32 +++++++++++++------ .../playground/PlaygroundPageContent.tsx | 9 ++++++ .../pages/playground/getNpmVersionsSync.ts | 2 ++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/website/src/website/pages/playground/PlaygroundModel.ts b/website/src/website/pages/playground/PlaygroundModel.ts index 7096c30626..db067c6614 100644 --- a/website/src/website/pages/playground/PlaygroundModel.ts +++ b/website/src/website/pages/playground/PlaygroundModel.ts @@ -404,6 +404,16 @@ class StateUrlSerializer implements IHistoryModel { this.historyId++; } + @action + useLatestDev(): void { + this._sourceOverride = undefined; + this.model.settings.setSettings({ + ...this.model.settings.settings, + ...Source.useLatestDev().toPartialSettings(), + }); + this.historyId++; + } + @action saveSourceOverride(): void { if (this._sourceOverride) { @@ -662,22 +672,26 @@ function findLastIndex( } class Source { + public static useLatestDev(sourceLanguagesStr?: string): Source { + // Assume the versions are already loaded + const versions = getNpmVersionsSync(undefined); + const version = versions.find((v) => v.indexOf("-dev-") !== -1); + return new Source(version, undefined, sourceLanguagesStr); + } + + public static useLatest(sourceLanguagesStr?: string): Source { + return new Source(monacoEditorVersion, undefined, sourceLanguagesStr); + } + public static parse( sourceStr: string | undefined, sourceLanguagesStr: string | undefined ): Source { if (sourceStr === "latest-dev") { - // The versions are already loaded - const versions = getNpmVersionsSync(undefined); - const version = versions.find((v) => v.indexOf("-dev-") !== -1); - return new Source(version, undefined, sourceLanguagesStr); + return Source.useLatestDev(sourceLanguagesStr); } if (sourceStr === "latest") { - return new Source( - monacoEditorVersion, - undefined, - sourceLanguagesStr - ); + return Source.useLatest(sourceLanguagesStr); } if (sourceStr && sourceStr.startsWith("v")) { diff --git a/website/src/website/pages/playground/PlaygroundPageContent.tsx b/website/src/website/pages/playground/PlaygroundPageContent.tsx index 66b5e3f71e..ac5129cf6e 100644 --- a/website/src/website/pages/playground/PlaygroundPageContent.tsx +++ b/website/src/website/pages/playground/PlaygroundPageContent.tsx @@ -192,6 +192,15 @@ export class PlaygroundPageContent extends React.Component< .version ?? "url"}{" "} override + + + + + ) : ( + <> + + + - - - ) : ( - <> - - - + + + } + > + + + + )} diff --git a/website/src/website/pages/playground/Preview.tsx b/website/src/website/pages/playground/Preview.tsx index 07ee853ca3..538b8d803f 100644 --- a/website/src/website/pages/playground/Preview.tsx +++ b/website/src/website/pages/playground/Preview.tsx @@ -1,27 +1,53 @@ import * as React from "react"; -import { IPreviewHandler, PlaygroundModel } from "./PlaygroundModel"; +import { PlaygroundModel } from "./PlaygroundModel"; import { observer } from "mobx-react"; -import { observable } from "mobx"; +import { autorun, observable, reaction } from "mobx"; import { IMessageFromRunner, IMessageToRunner, IPreviewState, } from "../../../shared"; +import { Button } from "react-bootstrap"; @observer -export class Preview - extends React.Component<{ model: PlaygroundModel }> - implements IPreviewHandler -{ +export class Preview extends React.Component<{ + model: PlaygroundModel; + getPreviewState: () => IPreviewState | undefined; +}> { private disposables: monaco.IDisposable[] = []; - @observable - private counter = 0; - private currentState: IPreviewState | undefined; + @observable private counter = 0; + @observable.ref private currentState: IPreviewState | undefined; private iframe: HTMLIFrameElement | null = null; render() { return (
+ {this.currentState ? null : ( +
+
+ Load{" "} +
+
+ )}