Browse Source

Reduces startup impact

Changes context to be Uri based rather than editor
main
Eric Amodio 2 years ago
parent
commit
fb30059821
3 changed files with 80 additions and 68 deletions
  1. +60
    -41
      src/premium/webviews/timeline/timelineWebviewView.ts
  2. +16
    -15
      src/webviews/apps/premium/timeline/timeline.scss
  3. +4
    -12
      src/webviews/webviewViewBase.ts

+ 60
- 41
src/premium/webviews/timeline/timelineWebviewView.ts View File

@ -1,5 +1,5 @@
'use strict';
import { commands, Disposable, TextEditor, window } from 'vscode';
import { commands, Disposable, TextEditor, Uri, window } from 'vscode';
import { ShowQuickCommitCommandArgs } from '../../../commands';
import { Commands } from '../../../constants';
import { Container } from '../../../container';
@ -23,7 +23,7 @@ import {
} from './protocol';
interface Context {
editor: TextEditor | undefined;
uri: Uri | undefined;
period: Period | undefined;
etagRepository: number | undefined;
etagSubscription: number | undefined;
@ -42,23 +42,34 @@ export class TimelineWebviewView extends WebviewViewBase {
super(container, 'gitlens.views.timeline', 'timeline.html', 'Visual File History');
this._context = {
editor: undefined,
uri: undefined,
period: defaultPeriod,
etagRepository: 0,
etagSubscription: 0,
};
}
protected override onInitializing(): Disposable[] | undefined {
this._context = {
uri: undefined,
period: defaultPeriod,
etagRepository: 0,
etagSubscription: this.container.subscription.etag,
};
this.disposables.push(
return [
this.container.subscription.onDidChange(this.onSubscriptionChanged, this),
window.onDidChangeActiveTextEditor(this.onActiveEditorChanged, this),
this.container.git.onDidChangeRepository(this.onRepositoryChanged, this),
);
];
}
protected override async includeBootstrap(): Promise<State> {
this._bootstraping = true;
this.updatePendingEditor(window.activeTextEditor);
this._context = { ...this._context, ...this._pendingContext };
this._pendingContext = undefined;
return this.getState(this._context);
}
@ -66,29 +77,6 @@ export class TimelineWebviewView extends WebviewViewBase {
return [commands.registerCommand(`${this.id}.refresh`, () => this.refresh(), this)];
}
@debug({ args: false })
private onActiveEditorChanged(editor: TextEditor | undefined) {
if (!this.updatePendingEditor(editor)) return;
this.updateState();
}
private onRepositoryChanged(e: RepositoryChangeEvent) {
if (!e.changed(RepositoryChange.Heads, RepositoryChange.Index, RepositoryChangeComparisonMode.Any)) {
return;
}
if (this.updatePendingContext({ etagRepository: e.repository.etag })) {
this.updateState();
}
}
private onSubscriptionChanged(e: SubscriptionChangeEvent) {
if (this.updatePendingContext({ etagSubscription: e.etag })) {
this.updateState();
}
}
protected override onVisibilityChanged(visible: boolean) {
if (!visible) return;
@ -104,9 +92,9 @@ export class TimelineWebviewView extends WebviewViewBase {
switch (e.method) {
case OpenDataPointCommandType.method:
onIpc(OpenDataPointCommandType, e, params => {
if (params.data == null || !params.data.selected || this._context.editor == null) return;
if (params.data == null || !params.data.selected || this._context.uri == null) return;
const repository = this.container.git.getRepository(this._context.editor.document.uri);
const repository = this.container.git.getRepository(this._context.uri);
if (repository == null) return;
const commandArgs: ShowQuickCommitCommandArgs = {
@ -146,13 +134,38 @@ export class TimelineWebviewView extends WebviewViewBase {
}
@debug({ args: false })
private onActiveEditorChanged(editor: TextEditor | undefined) {
if (!this.updatePendingEditor(editor)) return;
this.updateState();
}
@debug({ args: false })
private onRepositoryChanged(e: RepositoryChangeEvent) {
if (!e.changed(RepositoryChange.Heads, RepositoryChange.Index, RepositoryChangeComparisonMode.Any)) {
return;
}
if (this.updatePendingContext({ etagRepository: e.repository.etag })) {
this.updateState();
}
}
@debug({ args: false })
private onSubscriptionChanged(e: SubscriptionChangeEvent) {
if (this.updatePendingContext({ etagSubscription: e.etag })) {
this.updateState();
}
}
@debug({ args: false })
private async getState(current: Context): Promise<State> {
const access = await this.container.git.access(PremiumFeatures.Timeline);
const period = current.period ?? defaultPeriod;
const dateFormat = this.container.config.defaultDateFormat ?? 'MMMM Do, YYYY h:mma';
if (current.editor == null || !access.allowed) {
if (current.uri == null || !access.allowed) {
return {
period: period,
title: 'There are no editors open that can provide file history information',
@ -161,7 +174,7 @@ export class TimelineWebviewView extends WebviewViewBase {
};
}
const gitUri = await GitUri.fromUri(current.editor.document.uri);
const gitUri = await GitUri.fromUri(current.uri);
const repoPath = gitUri.repoPath!;
const title = gitUri.relativePath;
@ -181,7 +194,7 @@ export class TimelineWebviewView extends WebviewViewBase {
dataset: [],
period: period,
title: 'No commits found for the specified time period',
uri: current.editor.document.uri.toString(),
uri: current.uri.toString(),
dateFormat: dateFormat,
access: access,
};
@ -210,7 +223,7 @@ export class TimelineWebviewView extends WebviewViewBase {
dataset: dataset,
period: period,
title: title,
uri: current.editor.document.uri.toString(),
uri: current.uri.toString(),
dateFormat: dateFormat,
access: access,
};
@ -234,14 +247,20 @@ export class TimelineWebviewView extends WebviewViewBase {
private updatePendingContext(context: Partial<Context>): boolean {
let changed = false;
for (const [key, value] of Object.entries(context)) {
if ((this._context as unknown as Record<string, unknown>)[key] !== value) {
if (this._pendingContext == null) {
this._pendingContext = {};
}
const current = (this._context as unknown as Record<string, unknown>)[key];
if (
current === value ||
((current instanceof Uri || value instanceof Uri) && (current as any)?.toString() === value?.toString())
) {
continue;
}
(this._pendingContext as Record<string, unknown>)[key] = value;
changed = true;
if (this._pendingContext == null) {
this._pendingContext = {};
}
(this._pendingContext as Record<string, unknown>)[key] = value;
changed = true;
}
return changed;
@ -259,7 +278,7 @@ export class TimelineWebviewView extends WebviewViewBase {
etag = 0;
}
return this.updatePendingContext({ editor: editor, etagRepository: etag });
return this.updatePendingContext({ uri: editor?.document.uri, etagRepository: etag });
}
private _notifyDidChangeStateDebounced: Deferrable<() => void> | undefined = undefined;

+ 16
- 15
src/webviews/apps/premium/timeline/timeline.scss View File

@ -75,20 +75,7 @@ p {
margin-bottom: 0;
}
.select-container {
display: flex;
align-items: center;
justify-content: flex-end;
// margin: 1em;
flex: 100% 0 1;
label {
margin: 0 1em;
font-size: var(--font-size);
}
}
vscode-button {
vscode-button:not([appearance='icon']) {
align-self: center;
margin-top: 1.5rem;
max-width: 300px;
@ -101,7 +88,7 @@ span.button-subaction {
}
@media (min-width: 640px) {
vscode-button {
vscode-button:not([appearance='icon']) {
align-self: flex-start;
}
span.button-subaction {
@ -140,6 +127,20 @@ span.button-subaction {
.toolbox {
grid-area: toolbox;
display: flex;
}
}
.select-container {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 100% 0 1;
// margin: 1em;
label {
margin: 0 1em;
font-size: var(--font-size);
}
}

+ 4
- 12
src/webviews/webviewViewBase.ts View File

@ -36,14 +36,6 @@ function nextIpcId() {
return `host:${ipcSequence}`;
}
const emptyCommands: Disposable[] = [
{
dispose: function () {
/* noop */
},
},
];
export abstract class WebviewViewBase<State> implements WebviewViewProvider, Disposable {
protected readonly disposables: Disposable[] = [];
protected isReady: boolean = false;
@ -100,14 +92,13 @@ export abstract class WebviewViewBase implements WebviewViewProvider, Dis
}
}
protected onInitializing?(): Disposable[] | undefined;
protected onReady?(): void;
protected onMessageReceived?(e: IpcMessage): void;
protected onVisibilityChanged?(visible: boolean): void;
protected onWindowFocusChanged?(focused: boolean): void;
protected registerCommands(): Disposable[] {
return emptyCommands;
}
protected registerCommands?(): Disposable[];
protected includeBootstrap?(): State | Promise<State>;
protected includeHead?(): string | Promise<string>;
@ -133,7 +124,8 @@ export abstract class WebviewViewBase implements WebviewViewProvider, Dis
this._view.onDidChangeVisibility(this.onViewVisibilityChanged, this),
this._view.webview.onDidReceiveMessage(this.onMessageReceivedCore, this),
window.onDidChangeWindowState(this.onWindowStateChanged, this),
...this.registerCommands(),
...(this.onInitializing?.() ?? []),
...(this.registerCommands?.() ?? []),
);
webviewView.webview.html = await this.getHtml(webviewView.webview);

Loading…
Cancel
Save