Selaa lähdekoodia

Improves home, welcome, getting started experience

Adds links footer to home view when welcome is hidden
Polishes welcome/settings page headers
Removes links from welcome page
Removes old welcome view
main
Eric Amodio 2 vuotta sitten
vanhempi
commit
a540814a22
26 muutettua tiedostoa jossa 376 lisäystä ja 281 poistoa
  1. +25
    -50
      package.json
  2. +1
    -1
      src/commands.ts
  3. +0
    -26
      src/commands/closeView.ts
  4. +22
    -0
      src/commands/getStarted.ts
  5. +1
    -9
      src/commands/showView.ts
  6. +2
    -2
      src/constants.ts
  7. +12
    -16
      src/extension.ts
  8. +1
    -1
      src/storage.ts
  9. +87
    -13
      src/webviews/apps/premium/home/home.html
  10. +39
    -1
      src/webviews/apps/premium/home/home.scss
  11. +19
    -9
      src/webviews/apps/premium/home/home.ts
  12. +2
    -0
      src/webviews/apps/rebase/rebase.ts
  13. +20
    -10
      src/webviews/apps/settings/settings.scss
  14. +12
    -34
      src/webviews/apps/settings/settings.ts
  15. +20
    -0
      src/webviews/apps/shared/appWithConfigBase.ts
  16. +32
    -0
      src/webviews/apps/shared/codicons.scss
  17. +3
    -63
      src/webviews/apps/welcome/welcome.html
  18. +16
    -15
      src/webviews/apps/welcome/welcome.scss
  19. +12
    -2
      src/webviews/premium/home/homeWebviewView.ts
  20. +2
    -0
      src/webviews/premium/home/protocol.ts
  21. +6
    -0
      src/webviews/protocol.ts
  22. +0
    -6
      src/webviews/settings/protocol.ts
  23. +1
    -19
      src/webviews/settings/settingsWebview.ts
  24. +2
    -1
      src/webviews/webviewBase.ts
  25. +11
    -1
      src/webviews/webviewViewBase.ts
  26. +28
    -2
      src/webviews/webviewWithConfigBase.ts

+ 25
- 50
package.json Näytä tiedosto

@ -71,6 +71,7 @@
"onCommand:gitlens.premium.startPreview",
"onCommand:gitlens.premium.purchase",
"onCommand:gitlens.premium.reset",
"onCommand:gitlens.getStarted",
"onCommand:gitlens.showSettingsPage",
"onCommand:gitlens.showSettingsPage#views",
"onCommand:gitlens.showSettingsPage#branches-view",
@ -89,6 +90,7 @@
"onCommand:gitlens.showCommitsView",
"onCommand:gitlens.showContributorsView",
"onCommand:gitlens.showFileHistoryView",
"onCommand:gitlens.showHomeView",
"onCommand:gitlens.showLineHistoryView",
"onCommand:gitlens.showRemotesView",
"onCommand:gitlens.showRepositoriesView",
@ -96,8 +98,6 @@
"onCommand:gitlens.showStashesView",
"onCommand:gitlens.showTagsView",
"onCommand:gitlens.showWorktreesView",
"onCommand:gitlens.showWelcomeView",
"onCommand:gitlens.closeWelcomeView",
"onCommand:gitlens.compareWith",
"onCommand:gitlens.compareHeadWith",
"onCommand:gitlens.compareWorkingWith",
@ -3625,6 +3625,11 @@
"category": "GitLens Premium"
},
{
"command": "gitlens.getStarted",
"title": "Get Started",
"category": "GitLens"
},
{
"command": "gitlens.showSettingsPage",
"title": "Open Settings",
"category": "GitLens",
@ -3728,6 +3733,11 @@
"category": "GitLens"
},
{
"command": "gitlens.showHomeView",
"title": "Show Home View",
"category": "GitLens"
},
{
"command": "gitlens.showLineHistoryView",
"title": "Show Line History View",
"category": "GitLens"
@ -3763,17 +3773,6 @@
"category": "GitLens"
},
{
"command": "gitlens.showWelcomeView",
"title": "Show Welcome View",
"category": "GitLens"
},
{
"command": "gitlens.closeWelcomeView",
"title": "Close",
"category": "GitLens",
"icon": "$(close)"
},
{
"command": "gitlens.compareWith",
"title": "Compare References...",
"category": "GitLens",
@ -5978,6 +5977,10 @@
"when": "gitlens:enabled"
},
{
"command": "gitlens.showHomeView",
"when": "gitlens:enabled"
},
{
"command": "gitlens.showLineHistoryView",
"when": "gitlens:enabled && !gitlens:hasVirtualFolders"
},
@ -6003,15 +6006,7 @@
},
{
"command": "gitlens.showWorktreesView",
"when": "gitlens:enabled"
},
{
"command": "gitlens.showWelcomeView",
"when": "gitlens:enabled"
},
{
"command": "gitlens.closeWelcomeView",
"when": "false"
"when": "gitlens:enabled && !gitlens:hasVirtualFolders"
},
{
"command": "gitlens.compareWith",
@ -7685,14 +7680,19 @@
],
"extension/context": [
{
"command": "gitlens.showWelcomePage",
"command": "gitlens.getStarted",
"when": "extension =~ /^eamodio.gitlens(-insiders)?$/ && extensionStatus == installed",
"group": "9_gitlens@1"
},
{
"command": "gitlens.showSettingsPage",
"command": "gitlens.showWelcomePage",
"when": "extension =~ /^eamodio.gitlens(-insiders)?$/ && extensionStatus == installed",
"group": "9_gitlens@2"
},
{
"command": "gitlens.showSettingsPage",
"when": "extension =~ /^eamodio.gitlens(-insiders)?$/ && extensionStatus == installed",
"group": "9_gitlens@3"
}
],
"git.commit": [
@ -7790,11 +7790,6 @@
],
"view/title": [
{
"command": "gitlens.closeWelcomeView",
"when": "view == gitlens.views.welcome",
"group": "navigation@1"
},
{
"command": "gitlens.views.switchToAnotherBranch",
"when": "!gitlens:readonly && !gitlens:untrusted && !gitlens:hasVirtualFolders && view =~ /^gitlens\\.views\\.branches/",
"group": "navigation@10"
@ -10530,18 +10525,6 @@
},
"viewsWelcome": [
{
"view": "gitlens.views.welcome",
"contents": "GitLens 11 is powerful, feature rich, and highly customizable to meet your needs. You can use the GitLens Welcome experience to get setup quickly.\n\n[Welcome (Quick Setup)](command:gitlens.showWelcomePage \"Opens the GitLens Welcome (Quick Setup)\")\n\nFor more options, run [GitLens: Open Settings](command:gitlens.showSettingsPage \"Opens the GitLens Interactive Settings\") from the Command Palette to open the interactive GitLens settings editor."
},
{
"view": "gitlens.views.welcome",
"contents": "[GitLens views](command:gitlens.showSettingsPage%23views) are shown on the Source Control side bar, by default. Run [GitLens: Set Views Layout](command:gitlens.setViewsLayout \"Changes the GitLens Views Layout\") from the Command Palette to switch to an alternate side bar layout, or drag & drop them."
},
{
"view": "gitlens.views.welcome",
"contents": "[Close](command:gitlens.closeWelcomeView \"Closes the Welcome view\")"
},
{
"view": "gitlens.views.searchAndCompare",
"contents": "Search for commits by [message](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22message%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [author](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22author%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [SHA](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22commit%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [file](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22file%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), or [changes](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22change%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D)\n\n[Search Commits...](command:gitlens.views.searchAndCompare.searchCommits)",
"when": "!gitlens:hasVirtualFolders"
@ -10597,15 +10580,7 @@
"type": "webview",
"id": "gitlens.views.home",
"name": "Home",
"-when": "!gitlens:disabled && gitlens:views:home:visible != false",
"contextualTitle": "GitLens",
"icon": "images/gitlens-activitybar.svg",
"visibility": "visible"
},
{
"id": "gitlens.views.welcome",
"name": "Welcome",
"when": "gitlens:views:welcome:visible != false",
"-when": "!gitlens:disabled",
"contextualTitle": "GitLens",
"icon": "images/gitlens-activitybar.svg",
"visibility": "visible"

+ 1
- 1
src/commands.ts Näytä tiedosto

@ -1,7 +1,6 @@
export * from './commands/addAuthors';
export * from './commands/browseRepoAtRevision';
export * from './commands/closeUnchangedFiles';
export * from './commands/closeView';
export * from './commands/compareWith';
export * from './commands/copyCurrentBranch';
export * from './commands/copyMessageToClipboard';
@ -17,6 +16,7 @@ export * from './commands/diffWithRevision';
export * from './commands/diffWithRevisionFrom';
export * from './commands/diffWithWorking';
export * from './commands/externalDiff';
export * from './commands/getStarted';
export * from './commands/gitCommands';
export * from './commands/inviteToLiveShare';
export * from './commands/logging';

+ 0
- 26
src/commands/closeView.ts Näytä tiedosto

@ -1,26 +0,0 @@
import { Commands, ContextKeys } from '../constants';
import type { Container } from '../container';
import { setContext } from '../context';
import { SyncedStorageKeys } from '../storage';
import { command } from '../system/command';
import { Command, CommandContext } from './base';
@command()
export class CloseViewCommand extends Command {
constructor(private readonly container: Container) {
super([Commands.CloseWelcomeView]);
}
protected override preExecute(context: CommandContext) {
return this.execute(context.command as Commands);
}
async execute(command: Commands) {
switch (command) {
case Commands.CloseWelcomeView:
await this.container.storage.store(SyncedStorageKeys.WelcomeViewVisible, false);
await setContext(ContextKeys.ViewsWelcomeVisible, false);
break;
}
}
}

+ 22
- 0
src/commands/getStarted.ts Näytä tiedosto

@ -0,0 +1,22 @@
import { Commands, CoreCommands } from '../constants';
import type { Container } from '../container';
import { command, executeCoreCommand } from '../system/command';
import { Command } from './base';
@command()
export class GetStartedCommand extends Command {
constructor(private readonly container: Container) {
super(Commands.GetStarted);
}
execute(step?: string) {
const id = this.container.context.extension.id;
// If the step param is the same as the extension id, then this was run from the extensions view gear menu
if (step === id) {
step = undefined;
}
// Takes the following params: walkthroughID: string | { category: string, step: string } | undefined, toSide: boolean | undefined
void executeCoreCommand(CoreCommands.OpenWalkthrough, `${id}#${step ?? 'gitlens.welcome'}`, true);
}
}

+ 1
- 9
src/commands/showView.ts Näytä tiedosto

@ -1,7 +1,5 @@
import { Commands, ContextKeys } from '../constants';
import { Commands } from '../constants';
import type { Container } from '../container';
import { setContext } from '../context';
import { SyncedStorageKeys } from '../storage';
import { command, executeCommand } from '../system/command';
import { Command, CommandContext } from './base';
@ -20,7 +18,6 @@ export class ShowViewCommand extends Command {
Commands.ShowStashesView,
Commands.ShowTagsView,
Commands.ShowWorktreesView,
Commands.ShowWelcomeView,
Commands.ShowHomeView,
]);
}
@ -53,11 +50,6 @@ export class ShowViewCommand extends Command {
return this.container.tagsView.show();
case Commands.ShowWorktreesView:
return this.container.worktreesView.show();
case Commands.ShowWelcomeView:
await setContext(ContextKeys.ViewsWelcomeVisible, true);
void this.container.storage.store(SyncedStorageKeys.WelcomeViewVisible, true);
void (await executeCommand('gitlens.views.welcome.focus'));
break;
case Commands.ShowHomeView:
void (await executeCommand('gitlens.views.home.focus'));
break;

+ 2
- 2
src/constants.ts Näytä tiedosto

@ -98,6 +98,7 @@ export const enum Commands {
ExternalDiff = 'gitlens.externalDiff',
ExternalDiffAll = 'gitlens.externalDiffAll',
FetchRepositories = 'gitlens.fetchRepositories',
GetStarted = 'gitlens.getStarted',
InviteToLiveShare = 'gitlens.inviteToLiveShare',
OpenBlamePriorToChange = 'gitlens.openBlamePriorToChange',
OpenBranchesOnRemote = 'gitlens.openBranchesOnRemote',
@ -182,7 +183,6 @@ export const enum Commands {
ShowTagsView = 'gitlens.showTagsView',
ShowWorktreesView = 'gitlens.showWorktreesView',
ShowWelcomePage = 'gitlens.showWelcomePage',
ShowWelcomeView = 'gitlens.showWelcomeView',
StashApply = 'gitlens.stashApply',
StashSave = 'gitlens.stashSave',
StashSaveFiles = 'gitlens.stashSaveFiles',
@ -238,7 +238,6 @@ export const enum ContextKeys {
ViewsLineHistoryEditorFollowing = 'gitlens:views:lineHistory:editorFollowing',
ViewsRepositoriesAutoRefresh = 'gitlens:views:repositories:autoRefresh',
ViewsSearchAndCompareKeepResults = 'gitlens:views:searchAndCompare:keepResults',
ViewsWelcomeVisible = 'gitlens:views:welcome:visible',
Vsls = 'gitlens:vsls',
Premium = 'gitlens:premium',
@ -262,6 +261,7 @@ export const enum CoreCommands {
Open = 'vscode.open',
OpenFolder = 'vscode.openFolder',
OpenInTerminal = 'openInTerminal',
OpenWalkthrough = 'workbench.action.openWalkthrough',
OpenWith = 'vscode.openWith',
NextEditor = 'workbench.action.nextEditor',
PreviewHtml = 'vscode.previewHtml',

+ 12
- 16
src/extension.ts Näytä tiedosto

@ -85,18 +85,12 @@ export async function activate(context: ExtensionContext): Promise
let exitMessage;
if (Logger.enabled(LogLevel.Debug)) {
exitMessage = `syncedVersion=${syncedVersion}, localVersion=${localVersion}, previousVersion=${previousVersion}, welcome=${context.globalState.get<boolean>(
SyncedStorageKeys.WelcomeViewVisible,
SyncedStorageKeys.HomeViewWelcomeVisible,
)}`;
}
if (previousVersion == null) {
void context.globalState.update(SyncedStorageKeys.WelcomeViewVisible, true);
void setContext(ContextKeys.ViewsWelcomeVisible, true);
} else {
void setContext(
ContextKeys.ViewsWelcomeVisible,
context.globalState.get<boolean>(SyncedStorageKeys.WelcomeViewVisible) ?? false,
);
void context.globalState.update(SyncedStorageKeys.HomeViewWelcomeVisible, true);
}
Configuration.configure(context);
@ -165,7 +159,7 @@ function setKeysForSync(context: ExtensionContext, ...keys: (SyncedStorageKeys |
return context.globalState?.setKeysForSync([
...keys,
SyncedStorageKeys.Version,
SyncedStorageKeys.WelcomeViewVisible,
SyncedStorageKeys.HomeViewWelcomeVisible,
]);
}
@ -204,6 +198,9 @@ function registerBuiltInActionRunners(container: Container): void {
async function showWelcomeOrWhatsNew(container: Container, version: string, previousVersion: string | undefined) {
if (previousVersion == null) {
Logger.log(`GitLens first-time install; window.focused=${window.state.focused}`);
void executeCommand(Commands.ShowHomeView);
if (container.config.showWelcomeOnInstall === false) return;
if (window.state.focused) {
@ -237,16 +234,15 @@ async function showWelcomeOrWhatsNew(container: Container, version: string, prev
const [major, minor] = version.split('.').map(v => parseInt(v, 10));
const [prevMajor, prevMinor] = previousVersion.split('.').map(v => parseInt(v, 10));
if (
(major === prevMajor && minor === prevMinor) ||
// Don't notify on downgrades
major < prevMajor ||
(major === prevMajor && minor < prevMinor)
) {
// Don't notify on downgrades
if (major === prevMajor || major < prevMajor || (major === prevMajor && minor < prevMinor)) {
return;
}
if (major !== prevMajor && container.config.showWhatsNewAfterUpgrades) {
void executeCommand(Commands.ShowHomeView);
if (container.config.showWhatsNewAfterUpgrades) {
if (window.state.focused) {
await container.storage.delete(StorageKeys.PendingWhatsNewOnFocus);
await Messages.showWhatsNewMessage(version);

+ 1
- 1
src/storage.ts Näytä tiedosto

@ -70,7 +70,7 @@ export const enum StorageKeys {
export const enum SyncedStorageKeys {
Version = 'gitlens:synced:version',
WelcomeViewVisible = 'gitlens:views:welcome:visible',
HomeViewWelcomeVisible = 'gitlens:views:welcome:visible',
Deprecated_DisallowConnectionPrefix = 'gitlens:disallow:connection:',
}

+ 87
- 13
src/webviews/apps/premium/home/home.html Näytä tiedosto

@ -11,7 +11,7 @@
</head>
<body class="preload">
<div class="container">
<div id="container" class="container">
<div id="slot1"></div>
<vscode-divider></vscode-divider>
<div id="slot2"></div>
@ -21,8 +21,8 @@
</body>
<template id="welcome">
<section>
<h3>Welcome to GitLens 12!</h3>
<section class="welcome">
<h3>Welcome to GitLens 12</h3>
<p>
GitLens <b>supercharges</b> Git inside VS Code and <b>unlocks</b> the untapped <b>knowledge</b> within
each repository. While GitLens is both very <b>powerful</b> and feature rich, it is <b>intuitive</b> and
@ -31,33 +31,107 @@
<p>
Jump over to the getting started experience to familiarize yourself with the features GitLens provides.
</p>
<vscode-button data-action="command:gitlens.getStarted">Get Started</vscode-button>
<vscode-button data-action="command:gitlens.getStarted">Get started walkthrough</vscode-button>
<p>Or, you can use the GitLens welcome experience to get setup quickly.</p>
<vscode-button data-action="command:gitlens.showWelcomePage">Welcome (Quick Setup)</vscode-button>
<ul>
<li>
To view all GitLens settings, run
<a href="command:workbench.action.quickOpen?%22>GitLens%3A%20Open%20Settings%22"
>GitLens: Open Settings</a
To <a href="command:gitlens.showSettingsPage">view all GitLens settings</a>, run
<i
><a href="command:workbench.action.quickOpen?%22>GitLens%3A%20Open%20Settings%22"
>GitLens: Open Settings</a
></i
>
from the Command Palette.
</li>
<li>
<a href="command:gitlens.showSettingsPage%23views">GitLens side bar views</a>
for commits, branches, etc. are displayed within the Source Control side bar by default.
<a href="command:workbench.action.quickOpen?%22>GitLens%3A%20Set%20Views%20Layout%22"
>Run GitLens: Set Views Layout</a
for commits, branches, etc. are shown within the
<a href="command:workbench.scm.focus">Source Control side bar</a> by default.
</li>
<li>
To <a href="command:gitlens.setViewsLayout">display them here</a> in the GitLens side bar, run
<i
><a href="command:workbench.action.quickOpen?%22>GitLens%3A%20Set%20Views%20Layout%22"
>GitLens: Set Views Layout</a
></i
>
from the Command Palette to display them here in the GitLens side bar, or drag & drop them
individually.
from the Command Palette, or drag & drop them individually.
</li>
</ul>
<vscode-button data-action="command:gitlens.home.hideWelcome" appearance="secondary"
<vscode-button data-action="command:gitlens.home.toggleWelcome" appearance="secondary"
>Dismiss welcome</vscode-button
>
</section>
</template>
<template id="links">
<section>
<div class="links">
<div class="links__group">
<h4>Get Started</h4>
<ul>
<li>
<a href="command:gitlens.getStarted" appearance="secondary">Walkthrough</a>
</li>
<li>
<a href="command:gitlens.showWelcomePage?%22quick-setup%22" appearance="secondary"
>Quick&nbsp;setup</a
>
</li>
<li>
<a href="command:gitlens.showSettingsPage" appearance="secondary"
>Interactive&nbsp;settings&nbsp;editor</a
>
</li>
<li>
<a href="command:gitlens.home.toggleWelcome">Restore&nbsp;welcome</a>
</li>
</ul>
</div>
<div class="links__group">
<h4>Help</h4>
<ul>
<li>
<i class="codicon codicon-book"></i>
<a href="https://github.com/eamodio/vscode-gitlens#readme">Documentation</a>
</li>
<li>
<i class="codicon codicon-comment-discussion"></i>
<a href="https://github.com/eamodio/vscode-gitlens/discussions">Questions</a>
</li>
<li>
<i class="codicon codicon-issues"></i>
<a href="https://github.com/eamodio/vscode-gitlens/issues">Issues</a>
</li>
<li>
<i class="codicon codicon-comment"></i>
<a href="https://gitkraken.slack.com">Slack</a>
</li>
<li>
<i class="codicon codicon-twitter"></i>
<a href="https://twitter.com/gitlens">Twitter</a>
</li>
</ul>
</div>
<div class="links__group">
<h4>Resources</h4>
<ul>
<li><a href="https://gitlens.amod.io">Website</a></li>
<li><a href="https://gitlens.amod.io/#whats-new">What's new</a></li>
<li>
<a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens"
>Marketplace</a
>
</li>
<li><a href="https://github.com/eamodio/vscode-gitlens">GitHub</a></li>
<li><a href="https://github.com/eamodio/vscode-gitlens/blob/main/LICENSE">License</a></li>
</ul>
</div>
</div>
</section>
</template>
<template id="state:free">
<section>
<h3>Try GitLens Premium Features</h3>

+ 39
- 1
src/webviews/apps/premium/home/home.scss Näytä tiedosto

@ -17,7 +17,12 @@ body {
color: var(--color-view-foreground);
display: grid;
font-size: 1.3em;
padding-bottom: 1.5rem;
grid-template-rows: auto repeat(2, min-content);
min-height: 100%;
}
.welcome {
grid-template-rows: repeat(3, min-content);
}
section {
@ -36,6 +41,12 @@ h3 {
white-space: nowrap;
}
h4 {
font-size: 1.5rem;
font-weight: 400;
margin: 0.5rem 0 1rem 0;
}
a {
text-decoration: none;
@ -56,6 +67,33 @@ p {
margin-bottom: 0;
}
.welcome {
ul {
list-style: none;
padding: 0;
margin: 1rem 3rem;
}
li {
margin: 1rem 0;
}
}
.links {
display: grid;
grid-template-columns: repeat(3, auto);
grid-gap: 2rem;
justify-content: space-between;
margin: 1rem;
ul {
list-style: none;
margin: 0.5rem 0 0 0;
padding: 0;
white-space: nowrap;
}
}
vscode-button {
align-self: center;
margin-top: 1.5rem;

+ 19
- 9
src/webviews/apps/premium/home/home.ts Näytä tiedosto

@ -36,6 +36,8 @@ export class HomeApp extends App {
switch (msg.method) {
case DidChangeSubscriptionNotificationType.method:
this.log(`${this.appName}.onMessageReceived: name=${msg.method}`);
onIpc(DidChangeSubscriptionNotificationType, msg, params => {
this.state = params;
this.updateState();
@ -56,46 +58,54 @@ export class HomeApp extends App {
}
private updateState() {
const { subscription } = this.state;
const { subscription, welcomeVisible } = this.state;
if (subscription.account?.verified === false) {
this.insertTemplate('state:verify-email', this.$slot1);
this.insertTemplate('welcome', this.$slot2);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
return;
}
const $container = document.getElementById('container') as HTMLDivElement;
$container.classList.toggle('welcome', welcomeVisible);
switch (subscription.state) {
case SubscriptionState.Free:
this.insertTemplate('welcome', this.$slot1);
this.insertTemplate('state:free', this.$slot2);
if (welcomeVisible) {
this.insertTemplate('welcome', this.$slot1);
this.insertTemplate('state:free', this.$slot2);
} else {
this.insertTemplate('state:free', this.$slot1);
this.insertTemplate('links', this.$slot2);
}
break;
case SubscriptionState.FreeInPreview: {
const remaining = getSubscriptionTimeRemaining(subscription, 'days') ?? 0;
this.insertTemplate('state:free-preview', this.$slot1, {
previewDays: `${remaining === 1 ? `${remaining} more day` : `${remaining} more days`}`,
});
this.insertTemplate('welcome', this.$slot2);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
}
case SubscriptionState.FreePreviewExpired:
this.insertTemplate('state:free-preview-expired', this.$slot1);
this.insertTemplate('welcome', this.$slot2);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
case SubscriptionState.FreePlusInTrial: {
const remaining = getSubscriptionTimeRemaining(subscription, 'days') ?? 0;
this.insertTemplate('state:plus-trial', this.$slot1, {
trialDays: `${remaining === 1 ? `${remaining} day` : `${remaining} days`}`,
});
this.insertTemplate('welcome', this.$slot2);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
}
case SubscriptionState.FreePlusTrialExpired:
this.insertTemplate('state:plus-trial-expired', this.$slot1);
this.insertTemplate('welcome', this.$slot2);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
case SubscriptionState.Paid:
this.insertTemplate('state:paid', this.$slot1);
this.insertTemplate('welcome', this.$slot2);
this.insertTemplate(welcomeVisible ? 'welcome' : 'links', this.$slot2);
break;
}
}

+ 2
- 0
src/webviews/apps/rebase/rebase.ts Näytä tiedosto

@ -275,6 +275,8 @@ class RebaseEditor extends App {
switch (msg.method) {
case DidChangeNotificationType.method:
this.log(`${this.appName}.onMessageReceived: name=${msg.method}`);
onIpc(DidChangeNotificationType, msg, params => {
this.setState({ ...this.state, ...params.state });
this.refresh(this.state);

+ 20
- 10
src/webviews/apps/settings/settings.scss Näytä tiedosto

@ -11,11 +11,21 @@ body {
header {
grid-area: header;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(265px, 1fr));
grid-gap: 1em 3em;
grid-template-columns: max-content minmax(396px, auto);
grid-gap: 1em 4em;
align-items: center;
justify-items: center;
margin: 0 3em;
margin: 0 2em;
// grid-template-columns: repeat(auto-fit, minmax(265px, 1fr));
// grid-gap: 1em 3em;
// align-items: center;
// justify-items: center;
// margin: 0 3em;
@media all and (max-width: 768px) {
grid-template-columns: auto;
justify-items: center;
grid-gap: 1rem;
}
}
.blurb {
@ -99,20 +109,16 @@ header {
.header__blurb {
color: var(--color-foreground--75);
flex: 2 1 55%;
font-size: 1.5rem;
font-weight: 200;
margin: 0;
min-width: 345px;
@media all and (max-width: 880px) {
margin: 0 2em;
}
text-align: justify;
}
.header__link {
color: var(--color-foreground);
outline: none;
margin: 0 1rem 0.75rem 2rem;
&:hover,
&:active,
@ -120,6 +126,10 @@ header {
color: var(--color-foreground);
outline: none;
}
@media all and (max-width: 768px) {
margin: 0 0 0.75rem 0;
}
}
.header__logo {

+ 12
- 34
src/webviews/apps/settings/settings.ts Näytä tiedosto

@ -1,11 +1,12 @@
/*global window document IntersectionObserver*/
import './settings.scss';
import { IpcMessage, onIpc } from '../../protocol';
import { DidJumpToNotificationType, State } from '../../settings/protocol';
import { State } from '../../settings/protocol';
import { AppWithConfig } from '../shared/appWithConfigBase';
import { DOM } from '../shared/dom';
// import { Snow } from '../shared/snow';
const topOffset = 83;
export class SettingsApp extends AppWithConfig<State> {
private _scopes: HTMLSelectElement | null = null;
private _observer: IntersectionObserver | undefined;
@ -36,7 +37,7 @@ export class SettingsApp extends AppWithConfig {
this._scopes = scopes;
}
let top = 83;
let top = topOffset;
const header = document.querySelector('.hero__area--sticky');
if (header != null) {
top = header.clientHeight;
@ -92,19 +93,14 @@ export class SettingsApp extends AppWithConfig {
return disposables;
}
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
switch (msg.method) {
case DidJumpToNotificationType.method:
onIpc(DidJumpToNotificationType, msg, params => {
this.scrollToAnchor(params.anchor);
});
break;
default:
super.onMessageReceived?.(e);
protected override scrollToAnchor(anchor: string, behavior: ScrollBehavior): void {
let offset = topOffset;
const header = document.querySelector('.hero__area--sticky');
if (header != null) {
offset = header.clientHeight;
}
super.scrollToAnchor(anchor, behavior, offset);
}
private onObserver(entries: IntersectionObserverEntry[], _observer: IntersectionObserver) {
@ -189,7 +185,7 @@ export class SettingsApp extends AppWithConfig {
if (href == null) return;
const anchor = href.substr(1);
this.scrollToAnchor(anchor);
this.scrollToAnchor(anchor, 'smooth');
e.stopPropagation();
e.preventDefault();
@ -207,24 +203,6 @@ export class SettingsApp extends AppWithConfig {
element.parentElement!.parentElement!.classList.toggle('expanded');
}
private scrollToAnchor(anchor: string) {
const el = document.getElementById(anchor);
if (el == null) return;
let height = 83;
const header = document.querySelector('.hero__area--sticky');
if (header != null) {
height = header.clientHeight;
}
const top = el.getBoundingClientRect().top - document.body.getBoundingClientRect().top - height;
window.scrollTo({
top: top,
behavior: 'smooth',
});
}
private toggleJumpLink(anchor: string, active: boolean) {
const el = document.querySelector(`a.sidebar__jump-link[href="#${anchor}"]`);
if (el != null) {

+ 20
- 0
src/webviews/apps/shared/appWithConfigBase.ts Näytä tiedosto

@ -3,6 +3,7 @@ import type { Config } from '../../../config';
import {
DidChangeConfigurationNotificationType,
DidGenerateConfigurationPreviewNotificationType,
DidOpenAnchorNotificationType,
GenerateConfigurationPreviewCommandType,
IpcMessage,
onIpc,
@ -66,7 +67,15 @@ export abstract class AppWithConfig extends Ap
protected override onMessageReceived(e: MessageEvent) {
const msg = e.data as IpcMessage;
this.log(`${this.appName}.onMessageReceived: name=${msg.method}`);
switch (msg.method) {
case DidOpenAnchorNotificationType.method: {
onIpc(DidOpenAnchorNotificationType, msg, params => {
this.scrollToAnchor(params.anchor, params.scrollBehavior);
});
break;
}
case DidChangeConfigurationNotificationType.method:
onIpc(DidChangeConfigurationNotificationType, msg, params => {
this.state.config = params.config;
@ -259,6 +268,17 @@ export abstract class AppWithConfig extends Ap
e.preventDefault();
}
protected scrollToAnchor(anchor: string, behavior: ScrollBehavior, offset?: number) {
const el = document.getElementById(anchor);
if (el == null) return;
const top = el.getBoundingClientRect().top - document.body.getBoundingClientRect().top - (offset ?? 0);
window.scrollTo({
top: top,
behavior: behavior ?? 'smooth',
});
}
private evaluateStateExpression(expression: string, changes: Record<string, string | boolean>): boolean {
let state = false;
for (const expr of expression.trim().split('&')) {

+ 32
- 0
src/webviews/apps/shared/codicons.scss Näytä tiedosto

@ -37,3 +37,35 @@
margin: 0 3px;
}
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
vertical-align: middle;
line-height: 2rem;
}
.codicon-book:before {
content: '\eaa4';
}
.codicon-comment:before {
content: '\ea6b';
}
.codicon-comment-discussion:before {
content: '\eac7';
}
.codicon-issues:before {
content: '\eb0c';
}
.codicon-twitter:before {
content: '\eb72';
}

+ 3
- 63
src/webviews/apps/welcome/welcome.html Näytä tiedosto

@ -20,16 +20,6 @@
/> -->
<div class="container">
<!-- <div class="banner">
<a
title="Learn more about GitKraken and GitLens joining forces!"
href="https://www.gitkraken.com/blog/gitkraken-acquires-gitlens-for-visual-studio-code"
target="_blank"
alt="Learn more about GitKraken and GitLens joining forces!"
>
<img src="#{root}/images/gk+gl-banner.png" alt="GitKraken and GitLens are joining forces!" />
</a>
</div> -->
<header>
<a class="header__link" title="Learn more about GitLens" href="https://gitlens.amod.io">
<div class="header__logo">
@ -48,22 +38,6 @@
</p>
</header>
<!-- <div class="hero__area">
<p>
<a class="bold" title="Learn more about GitLens" href="https://gitlens.amod.io">GitLens</a> is an
<a class="bold" title="Open GitLens on GitHub" href="https://github.com/eamodio/vscode-gitlens"
>open-source</a
>
extension for Visual Studio Code.
</p>
<p>
GitLens simply helps you <b>better understand code</b>. Quickly glimpse into whom, why, and when a
line or code block was changed. Jump back through history to <b>gain further insights</b> as to how
and why the code evolved. Effortlessly explore the history and evolution of a codebase. Dive right
in and see how GitLens can help!
</p>
</div> -->
<div class="content__area">
<section id="welcome" class="section--full">
<h2 class="section__title section__title--primary">
@ -76,17 +50,16 @@
</div>
<h2 id="quick-setup" class="section__title section__title--break">Quick Setup</h2>
<p class="blurb ml-0 mr-0">
<p class="blurb ml-2 mr-2">
GitLens is <b>powerful</b>, <b>feature rich</b>, and highly <b>customizable</b> to meet your
needs. Do you find CodeLens intrusive or the current line blame annotation distracting &mdash;
no problem, quickly turn them off or change how they behave using the options below.
</p>
<p class="section__hint mt-0 center">
<p class="blurb mt-0 mb-0 center">
<i class="icon icon__info"></i> For more options, use the interactive
<a class="command" title="Open GitLens Settings" href="command:gitlens.showSettingsPage"
>GitLens Settings</a
>GitLens settings editor</a
>
editor
</p>
</section>
@ -419,39 +392,6 @@
</div>
</section>
</div>
<div class="sidebar">
<div class="sidebar__group">
<h2>Help</h2>
<ul>
<li>
<a href="https://github.com/eamodio/vscode-gitlens#readme">Documentation</a>
</li>
<li>
<a href="https://github.com/eamodio/vscode-gitlens/issues">Questions &amp; Issues</a>
</li>
<li>
<a href="https://vscode-slack.amod.io">Slack</a>
<small> &nbsp;&nbsp;&mdash;&nbsp; #gitlens channel</small>
</li>
<li><a href="https://twitter.com/gitlens">Twitter</a></li>
</ul>
</div>
<div class="sidebar__group">
<h2>Resources</h2>
<ul>
<li><a href="https://gitlens.amod.io">Website</a></li>
<li><a href="https://gitlens.amod.io/#whats-new">What's New</a></li>
<li>
<a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens"
>Marketplace</a
>
</li>
<li><a href="https://github.com/eamodio/vscode-gitlens">GitHub</a></li>
<li><a href="https://github.com/eamodio/vscode-gitlens/blob/main/LICENSE">License</a></li>
</ul>
</div>
</div>
</div>
#{endOfBody}
</body>

+ 16
- 15
src/webviews/apps/welcome/welcome.scss Näytä tiedosto

@ -11,11 +11,16 @@ body {
header {
grid-area: header;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(265px, 1fr));
grid-gap: 1em 3em;
grid-template-columns: max-content minmax(396px, auto);
grid-gap: 1em 4em;
align-items: center;
justify-items: center;
margin: 0 3em;
margin: 0 2em;
@media all and (max-width: 768px) {
grid-template-columns: auto;
justify-items: center;
grid-gap: 1rem;
}
}
.blurb {
@ -42,14 +47,10 @@ header {
display: grid;
grid-template-areas: 'banner banner' 'header header' 'hero hero' 'content sidebar';
grid-template-columns: repeat(1, 1fr min-content);
grid-gap: 1em 0;
margin: 1em auto;
grid-gap: 1em 3em;
max-width: 1200px;
min-width: 450px;
@media all and (max-width: 768px) {
grid-gap: 1em 0;
}
}
.banner {
@ -113,20 +114,16 @@ header {
.header__blurb {
color: var(--color-foreground--75);
flex: 2 1 55%;
font-size: 1.5rem;
font-weight: 200;
margin: 0;
min-width: 345px;
@media all and (max-width: 880px) {
margin: 0 2em;
}
text-align: justify;
}
.header__link {
color: var(--color-foreground);
outline: none;
margin: 0 1rem 0.75rem 2rem;
&:hover,
&:active,
@ -134,6 +131,10 @@ header {
color: var(--color-foreground);
outline: none;
}
@media all and (max-width: 768px) {
margin: 0 0 0.75rem 0;
}
}
.header__logo {

+ 12
- 2
src/webviews/premium/home/homeWebviewView.ts Näytä tiedosto

@ -1,6 +1,7 @@
import { commands, Disposable, window } from 'vscode';
import type { Container } from '../../../container';
import type { SubscriptionChangeEvent } from '../../../premium/subscription/subscriptionService';
import { SyncedStorageKeys } from '../../../storage';
import type { Subscription } from '../../../subscription';
import { WebviewViewBase } from '../../webviewViewBase';
import { DidChangeSubscriptionNotificationType, State } from './protocol';
@ -42,8 +43,13 @@ export class HomeWebviewView extends WebviewViewBase {
protected override registerCommands(): Disposable[] {
return [
commands.registerCommand('gitlens.home.hideWelcome', () => {
commands.registerCommand('gitlens.home.toggleWelcome', async () => {
// TODO@eamodio implement hiding the welcome section and show a help/links section
const welcomeVisible = this.container.storage.get(SyncedStorageKeys.HomeViewWelcomeVisible, true);
await this.container.storage.store(SyncedStorageKeys.HomeViewWelcomeVisible, !welcomeVisible);
const subscription = await this.container.subscription.getSubscription();
void this.notifyDidChangeData(subscription);
}),
];
}
@ -52,6 +58,7 @@ export class HomeWebviewView extends WebviewViewBase {
const subscription = await this.container.subscription.getSubscription();
return {
subscription: subscription,
welcomeVisible: this.container.storage.get(SyncedStorageKeys.HomeViewWelcomeVisible, true),
};
}
@ -59,7 +66,10 @@ export class HomeWebviewView extends WebviewViewBase {
if (!this.isReady) return false;
return window.withProgress({ location: { viewId: this.id } }, () =>
this.notify(DidChangeSubscriptionNotificationType, { subscription: subscription }),
this.notify(DidChangeSubscriptionNotificationType, {
subscription: subscription,
welcomeVisible: this.container.storage.get(SyncedStorageKeys.HomeViewWelcomeVisible, true),
}),
);
}
}

+ 2
- 0
src/webviews/premium/home/protocol.ts Näytä tiedosto

@ -3,10 +3,12 @@ import { IpcNotificationType } from '../../protocol';
export interface State {
subscription: Subscription;
welcomeVisible: boolean;
}
export interface DidChangeSubscriptionParams {
subscription: Subscription;
welcomeVisible: boolean;
}
export const DidChangeSubscriptionNotificationType = new IpcNotificationType<DidChangeSubscriptionParams>(
'subscription/didChange',

+ 6
- 0
src/webviews/protocol.ts Näytä tiedosto

@ -78,3 +78,9 @@ export interface DidGenerateConfigurationPreviewParams {
}
export const DidGenerateConfigurationPreviewNotificationType =
new IpcNotificationType<DidGenerateConfigurationPreviewParams>('configuration/didPreview');
export interface DidOpenAnchorParams {
anchor: string;
scrollBehavior: 'auto' | 'smooth';
}
export const DidOpenAnchorNotificationType = new IpcNotificationType<DidOpenAnchorParams>('webview/didOpenAnchor');

+ 0
- 6
src/webviews/settings/protocol.ts Näytä tiedosto

@ -1,5 +1,4 @@
import type { Config } from '../../config';
import { IpcNotificationType } from '../protocol';
export interface State {
config: Config;
@ -7,8 +6,3 @@ export interface State {
scope: 'user' | 'workspace';
scopes: ['user' | 'workspace', string][];
}
export interface DidJumpToParams {
anchor: string;
}
export const DidJumpToNotificationType = new IpcNotificationType<DidJumpToParams>('settings/jumpTo');

+ 1
- 19
src/webviews/settings/settingsWebview.ts Näytä tiedosto

@ -3,13 +3,11 @@ import { configuration } from '../../configuration';
import { Commands } from '../../constants';
import type { Container } from '../../container';
import { WebviewWithConfigBase } from '../webviewWithConfigBase';
import { DidJumpToNotificationType, State } from './protocol';
import { State } from './protocol';
const anchorRegex = /.*?#(.*)/;
export class SettingsWebview extends WebviewWithConfigBase<State> {
private _pendingJumpToAnchor: string | undefined;
constructor(container: Container) {
super(
container,
@ -47,22 +45,6 @@ export class SettingsWebview extends WebviewWithConfigBase {
);
}
protected override onReady() {
if (this._pendingJumpToAnchor != null) {
void this.notify(DidJumpToNotificationType, {
anchor: this._pendingJumpToAnchor,
});
this._pendingJumpToAnchor = undefined;
}
}
protected override onShowCommand(anchor?: string) {
if (anchor) {
this._pendingJumpToAnchor = anchor;
}
super.onShowCommand();
}
protected override includeBootstrap(): State {
const scopes: ['user' | 'workspace', string][] = [['user', 'User']];
if (workspace.workspaceFolders?.length) {

+ 2
- 1
src/webviews/webviewBase.ts Näytä tiedosto

@ -151,7 +151,7 @@ export abstract class WebviewBase implements Disposable {
protected onMessageReceivedCore(e: IpcMessage) {
if (e == null) return;
Logger.debug(`Webview(${this.id}).onMessageReceived: method=${e.method}, data=${JSON.stringify(e)}`);
Logger.debug(`Webview(${this.id}).onMessageReceived: method=${e.method}`);
switch (e.method) {
case WebviewReadyCommandType.method:
@ -238,6 +238,7 @@ export abstract class WebviewBase implements Disposable {
private postMessage(message: IpcMessage) {
if (this._panel == null) return Promise.resolve(false);
Logger.debug(`Webview(${this.id}).postMessage: method=${message.method}`);
return this._panel.webview.postMessage(message);
}
}

+ 11
- 1
src/webviews/webviewViewBase.ts Näytä tiedosto

@ -129,6 +129,12 @@ export abstract class WebviewViewBase implements WebviewViewProvider, Dis
this.onViewVisibilityChanged();
}
protected async refresh(): Promise<void> {
if (this._view == null) return;
this._view.webview.html = await this.getHtml(this._view.webview);
}
private onViewDisposed() {
this._disposableView?.dispose();
this._disposableView = undefined;
@ -139,6 +145,10 @@ export abstract class WebviewViewBase implements WebviewViewProvider, Dis
const visible = this.visible;
Logger.debug(`WebviewView(${this.id}).onViewVisibilityChanged`, `visible=${visible}`);
this.onVisibilityChanged?.(visible);
if (this.container.debugging) {
void this.refresh();
}
}
private onWindowStateChanged(e: WindowState) {
@ -148,7 +158,7 @@ export abstract class WebviewViewBase implements WebviewViewProvider, Dis
private onMessageReceivedCore(e: IpcMessage) {
if (e == null) return;
Logger.debug(`WebviewView(${this.id}).onMessageReceived: method=${e.method}, data=${JSON.stringify(e)}`);
Logger.debug(`WebviewView(${this.id}).onMessageReceived: method=${e.method}`);
switch (e.method) {
case WebviewReadyCommandType.method:

+ 28
- 2
src/webviews/webviewWithConfigBase.ts Näytä tiedosto

@ -15,6 +15,7 @@ import { Logger } from '../logger';
import {
DidChangeConfigurationNotificationType,
DidGenerateConfigurationPreviewNotificationType,
DidOpenAnchorNotificationType,
GenerateConfigurationPreviewCommandType,
IpcMessage,
onIpc,
@ -23,6 +24,8 @@ import {
import { WebviewBase } from './webviewBase';
export abstract class WebviewWithConfigBase<State> extends WebviewBase<State> {
private _pendingJumpToAnchor: string | undefined;
constructor(
container: Container,
id: string,
@ -56,6 +59,29 @@ export abstract class WebviewWithConfigBase extends WebviewBase {
void this.notifyDidChangeConfiguration();
}
protected override onReady() {
if (this._pendingJumpToAnchor != null) {
const anchor = this._pendingJumpToAnchor;
this._pendingJumpToAnchor = undefined;
void this.notify(DidOpenAnchorNotificationType, { anchor: anchor, scrollBehavior: 'auto' });
}
}
protected override onShowCommand(anchor?: string) {
if (anchor) {
if (this.isReady && this.visible) {
queueMicrotask(
() => void this.notify(DidOpenAnchorNotificationType, { anchor: anchor, scrollBehavior: 'smooth' }),
);
return;
}
this._pendingJumpToAnchor = anchor;
}
super.onShowCommand();
}
protected override onViewStateChanged(e: WebviewPanelOnDidChangeViewStateEvent): void {
super.onViewStateChanged(e);
@ -70,7 +96,7 @@ export abstract class WebviewWithConfigBase extends WebviewBase {
switch (e.method) {
case UpdateConfigurationCommandType.method:
Logger.debug(`Webview(${this.id}).onMessageReceived: method=${e.method}, data=${JSON.stringify(e)}`);
Logger.debug(`Webview(${this.id}).onMessageReceived: method=${e.method}`);
onIpc(UpdateConfigurationCommandType, e, async params => {
const target =
@ -110,7 +136,7 @@ export abstract class WebviewWithConfigBase extends WebviewBase {
break;
case GenerateConfigurationPreviewCommandType.method:
Logger.debug(`Webview(${this.id}).onMessageReceived: method=${e.method}, data=${JSON.stringify(e)}`);
Logger.debug(`Webview(${this.id}).onMessageReceived: method=${e.method}`);
onIpc(GenerateConfigurationPreviewCommandType, e, async params => {
switch (params.type) {

Ladataan…
Peruuta
Tallenna