Skip to content

feat: customize getting started page #5707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 28, 2022
5 changes: 5 additions & 0 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
- [Does code-server have any security login validation?](#does-code-server-have-any-security-login-validation)
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
- [How do I change the port?](#how-do-i-change-the-port)
- [How do I hide the coder/coder promotion?](#how-do-i-hide-the-codercoder-promotion)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
Expand Down Expand Up @@ -418,3 +419,7 @@ There are two ways to change the port on which code-server runs:

1. with an environment variable e.g. `PORT=3000 code-server`
2. using the flag `--bind-addr` e.g. `code-server --bind-addr localhost:3000`

## How do I hide the coder/coder promotion?

You can pass the flag `--disable-getting-started-override` to `code-server`.
178 changes: 178 additions & 0 deletions patches/getting-started.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
Modify Help: Getting Started

This modifies some text on the Getting Started page and adds text about using
code-server on a team.

It is enabled by default but can be overriden using the cli flag
`--disable-getting-started-override`.

Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
@@ -62,7 +62,7 @@ import { GettingStartedIndexList } from
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
-import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
+import { IsEnabledCoderGettingStarted, WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
import { OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
import { Toggle } from 'vs/base/browser/ui/toggle/toggle';
@@ -753,11 +753,24 @@ export class GettingStartedPage extends
onShowOnStartupChanged();
}));

- const header = $('.header', {},
+ let header = $('.header', {},
$('h1.product-name.caption', {}, this.productService.nameLong),
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
);

+ if (this.contextService.contextMatchesRules(IsEnabledCoderGettingStarted)) {
+ header = $('.header', {},
+ $('h1.product-name.caption', {}, this.productService.nameLong),
+ $('p.subtitle.description.coder', {},
+ "Using code-server on a team?",
+ ),
+ $('p.subtitle.description.coder-coder', {},
+ "Check out: ",
+ $('a', { href: "https://github.com/coder/coder" }, "coder/coder")
+ ),
+ );
+ }
+

const leftColumn = $('.categories-column.categories-column-left', {},);
const rightColumn = $('.categories-column.categories-column-right', {},);
Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/media/gettingStarted.css
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/media/gettingStarted.css
+++ code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/media/gettingStarted.css
@@ -60,6 +60,15 @@
display: block;
}

+.monaco-workbench .part.editor > .content .gettingStartedContainer .coder {
+ margin-bottom: 0.2em;
+}
+
+.monaco-workbench .part.editor>.content .gettingStartedContainer .coder-coder {
+ font-size: 1em;
+ margin-top: 0.2em;
+}
+
.monaco-workbench.hc-black .part.editor>.content .gettingStartedContainer .subtitle,
.monaco-workbench.hc-light .part.editor>.content .gettingStartedContainer .subtitle {
font-weight: 200;
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -276,6 +276,11 @@ export interface IWorkbenchConstructionO
*/
readonly isEnabledFileDownloads?: boolean

+ /**
+ * Whether to use Coder's custom Getting Started text.
+ */
+ readonly isEnabledCoderGettingStarted?: boolean
+
//#endregion


Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -36,6 +36,11 @@ export interface IBrowserWorkbenchEnviro
* Enable downloading files via menu actions.
*/
readonly isEnabledFileDownloads?: boolean;
+
+ /**
+ * Enable Coder's custom getting started text.
+ */
+ readonly isEnabledCoderGettingStarted?: boolean;
}

export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
@@ -74,6 +79,13 @@ export class BrowserWorkbenchEnvironment
return this.options.isEnabledFileDownloads;
}

+ get isEnabledCoderGettingStarted(): boolean {
+ if (typeof this.options.isEnabledCoderGettingStarted === "undefined") {
+ throw new Error('isEnabledCoderGettingStarted was not provided to the browser');
+ }
+ return this.options.isEnabledCoderGettingStarted;
+ }
+
@memoize
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }

Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -16,6 +16,7 @@ export const serverOptions: OptionDescri
'auth': { type: 'string' },
'disable-file-downloads': { type: 'boolean' },
'locale': { type: 'string' },
+ 'disable-getting-started-override': { type: 'boolean' },

/* ----- server setup ----- */

@@ -98,6 +99,7 @@ export interface ServerParsedArgs {
'auth'?: string
'disable-file-downloads'?: boolean;
'locale'?: string
+ 'disable-getting-started-override'?: boolean;

/* ----- server setup ----- */

Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -308,6 +308,7 @@ export class WebClientServer {
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
userDataPath: this._environmentService.userDataPath,
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
+ isEnabledCoderGettingStarted: !this._environmentService.args['disable-getting-started-override'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/ev
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, IsEnabledCoderGettingStarted } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -204,6 +204,7 @@ export class WorkbenchContextKeysHandler

// code-server
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
+ IsEnabledCoderGettingStarted.bindTo(this.contextKeyService).set(this.environmentService.isEnabledCoderGettingStarted ?? true)

this.registerListeners();
}
Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
@@ -33,6 +33,7 @@ export const IsFullscreenContext = new R
export const HasWebFileSystemAccess = new RawContextKey<boolean>('hasWebFileSystemAccess', false, true); // Support for FileSystemAccess web APIs (https://wicg.github.io/file-system-access)

export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
+export const IsEnabledCoderGettingStarted = new RawContextKey<boolean>('isEnabledCoderGettingStarted', true, true);

//#endregion

1 change: 1 addition & 0 deletions patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ telemetry.diff
display-language.diff
cli-window-open.diff
exec-argv.diff
getting-started.diff
9 changes: 9 additions & 0 deletions src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface UserProvidedCodeArgs {
"disable-update-check"?: boolean
"disable-file-downloads"?: boolean
"disable-workspace-trust"?: boolean
"disable-getting-started-override"?: boolean
}

/**
Expand Down Expand Up @@ -170,6 +171,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
type: "boolean",
description: "Disable Workspace Trust feature. This switch only affects the current session.",
},
"disable-getting-started-override": {
type: "boolean",
description: "Disable the coder/coder override in the Help: Getting Started page.",
},
// --enable can be used to enable experimental features. These features
// provide no guarantees.
enable: { type: "string[]" },
Expand Down Expand Up @@ -563,6 +568,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args["disable-file-downloads"] = true
}

if (process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE?.match(/^(1|true)$/)) {
args["disable-getting-started-override"] = true
}

const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
if (process.env.HASHED_PASSWORD) {
args["hashed-password"] = process.env.HASHED_PASSWORD
Expand Down
28 changes: 28 additions & 0 deletions test/unit/node/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe("parser", () => {
delete process.env.LOG_LEVEL
delete process.env.PASSWORD
delete process.env.CS_DISABLE_FILE_DOWNLOADS
delete process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE
console.log = jest.fn()
})

Expand Down Expand Up @@ -97,6 +98,8 @@ describe("parser", () => {

"--disable-file-downloads",

"--disable-getting-started-override",

["--host", "0.0.0.0"],
"4",
"--",
Expand All @@ -114,6 +117,7 @@ describe("parser", () => {
value: path.resolve("path/to/cert"),
},
"disable-file-downloads": true,
"disable-getting-started-override": true,
enable: ["feature1", "feature2"],
help: true,
host: "0.0.0.0",
Expand Down Expand Up @@ -378,6 +382,30 @@ describe("parser", () => {
})
})

it("should use env var CS_DISABLE_GETTING_STARTED_OVERRIDE", async () => {
process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE = "1"
const args = parse([])
expect(args).toEqual({})

const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"disable-getting-started-override": true,
})
})

it("should use env var CS_DISABLE_GETTING_STARTED_OVERRIDE set to true", async () => {
process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE = "true"
const args = parse([])
expect(args).toEqual({})

const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"disable-getting-started-override": true,
})
})

it("should error if password passed in", () => {
expect(() => parse(["--password", "supersecret123"])).toThrowError(
"--password can only be set in the config file or passed in via $PASSWORD",
Expand Down