Skip to content
Draft
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ A summary of the Git Graph extension settings are:
* **Retain Context When Hidden**: Specifies if the Git Graph view Visual Studio Code context is kept when the panel is no longer visible (e.g. moved to background tab). Enabling this setting will make Git Graph load significantly faster when switching back to the Git Graph tab, however has a higher memory overhead.
* **Show Status Bar Item**: Show a Status Bar Item that opens the Git Graph View when clicked.
* **Source Code Provider Integration Location**: Specifies where the "View Git Graph" action appears on the title of SCM Providers.
* **Sticky Header**: Keeps the Graph View header (control bar and column headers) visible when the view is scrolled.
* **Tab Icon Colour Theme**: Specifies the colour theme of the icon displayed on the Git Graph tab.

This extension consumes the following settings:
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,11 @@
"default": "Inline",
"description": "Specifies where the \"View Git Graph\" action appears on the title of SCM Providers."
},
"git-graph.stickyHeader": {
"type": "boolean",
"default": true,
"description": "Keeps the Graph View header (control bar and column headers) visible when the view is scrolled."
},
"git-graph.tabIconColourTheme": {
"type": "string",
"enum": [
Expand Down
7 changes: 7 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,13 @@ class Config {
return !!this.config.get('showStatusBarItem', true);
}

/**
* Get the value of the `git-graph.stickyHeader` Extension Setting.
*/
get stickyHeader() {
return !!this.config.get('stickyHeader', true);
}

/**
* Get the value of the `git-graph.tabIconColourTheme` Extension Setting.
*/
Expand Down
8 changes: 5 additions & 3 deletions src/gitGraphView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,8 @@ export class GitGraphView extends Disposable {
repoDropdownOrder: config.repoDropdownOrder,
showRemoteBranches: config.showRemoteBranches,
showStashes: config.showStashes,
showTags: config.showTags
showTags: config.showTags,
stickyHeader: config.stickyHeader
},
lastActiveRepo: this.extensionState.getLastActiveRepo(),
loadViewTo: this.loadViewTo,
Expand All @@ -715,9 +716,10 @@ export class GitGraphView extends Disposable {
<p class="unableToLoadMessage">${UNABLE_TO_FIND_GIT_MSG}</p>
</body>`;
} else if (numRepos > 0) {
const stickyClassAttr = initialState.config.stickyHeader ? ' class="sticky"' : '';
body = `<body>
<div id="view" tabindex="-1">
<div id="controls">
<div id="controls"${stickyClassAttr}>
<span id="repoControl"><span class="unselectable">Repo: </span><div id="repoDropdown" class="dropdown"></div></span>
<span id="branchControl"><span class="unselectable">Branches: </span><div id="branchDropdown" class="dropdown"></div></span>
<label id="showRemoteBranchesControl"><input type="checkbox" id="showRemoteBranchesCheckbox" tabindex="-1"><span class="customCheckbox"></span>Show Remote Branches</label>
Expand All @@ -732,8 +734,8 @@ export class GitGraphView extends Disposable {
<div id="commitTable"></div>
</div>
<div id="footer"></div>
<div id="scrollShadow"></div>
</div>
<div id="scrollShadow"></div>
<script nonce="${nonce}">var initialState = ${JSON.stringify(initialState)}, globalState = ${JSON.stringify(globalState)}, workspaceState = ${JSON.stringify(workspaceState)};</script>
<script nonce="${nonce}" src="${this.getMediaUri('out.min.js')}"></script>
</body>`;
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export interface GitGraphViewConfig {
readonly showRemoteBranches: boolean;
readonly showStashes: boolean;
readonly showTags: boolean;
readonly stickyHeader: boolean;
}

export interface GitGraphViewGlobalState {
Expand Down
2 changes: 2 additions & 0 deletions tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2887,6 +2887,8 @@ describe('Config', () => {

describe('showStatusBarItem', testBooleanExtensionSetting('showStatusBarItem', 'showStatusBarItem', true));

describe('stickyHeader', testBooleanExtensionSetting('stickyHeader', 'stickyHeader', true));

describe('tabIconColourTheme', () => {
it('Should return TabIconColourTheme.Colour when the configuration value is "colour"', () => {
// Setup
Expand Down
17 changes: 17 additions & 0 deletions tests/gitGraphView.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3668,6 +3668,9 @@ describe('GitGraphView', () => {
// Assert
const mockedWebviewPanel = vscode.getMockedWebviewPanel(0);
expect(mockedWebviewPanel.panel.webview.html).toContain('<div id="view" tabindex="-1">');
expect(mockedWebviewPanel.panel.webview.html).toContain('<div id="controls" class="sticky">');
expect(mockedWebviewPanel.panel.webview.html).toContain('"stickyHeader":true');
expect(mockedWebviewPanel.panel.webview.html).toContain('<div id="scrollShadow"></div>\n\t\t\t</div>');
expect(mockedWebviewPanel.panel.webview.html).toContain('<script nonce="1a2b3c4d5e6f1a2b3c4d5e6f1a2b3c4d">');
expect(mockedWebviewPanel.panel.webview.html).toContain('<script nonce="1a2b3c4d5e6f1a2b3c4d5e6f1a2b3c4d" src="vscode-webview-resource://file///path/to/extension/media/out.min.js"></script>');
expect(spyOnIsAvatarStorageAvailable).not.toHaveBeenCalled();
Expand All @@ -3688,6 +3691,20 @@ describe('GitGraphView', () => {
expect(mockedWebviewPanel.panel.webview.html).toContain('<script nonce="1a2b3c4d5e6f1a2b3c4d5e6f1a2b3c4d" src="vscode-webview-resource://file///path/to/extension/media/out.min.js"></script>');
expect(spyOnIsAvatarStorageAvailable).toHaveBeenCalledWith();
});

it('Should omit the sticky class when stickyHeader is disabled', () => {
// Setup
vscode.mockExtensionSettingReturnValue('stickyHeader', false);

// Run
GitGraphView.createOrShow('/path/to/extension', dataSource, extensionState, avatarManager, repoManager, logger, null);

// Assert
const mockedWebviewPanel = vscode.getMockedWebviewPanel(0);
expect(mockedWebviewPanel.panel.webview.html).toContain('<div id="controls">');
expect(mockedWebviewPanel.panel.webview.html).not.toContain('<div id="controls" class="sticky">');
expect(mockedWebviewPanel.panel.webview.html).toContain('"stickyHeader":false');
});
});
});

Expand Down
2 changes: 1 addition & 1 deletion web/contextMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class ContextMenu {
? 2 - menuBounds.height // context menu fits above
: -2 - (menuBounds.height - (frameBounds.height - (event.pageY - frameBounds.top))); // Overlap the context menu vertically with the cursor
menu.style.left = (frameElem.scrollLeft + Math.max(event.pageX - frameBounds.left + relativeX, 2)) + 'px';
menu.style.top = (frameElem.scrollTop + Math.max(event.pageY - frameBounds.top + relativeY, 2)) + 'px';
menu.style.top = Math.max(event.clientY - frameBounds.top + relativeY, 2) + 'px';
menu.style.opacity = '1';
this.elem = menu;
this.onClose = onClose;
Expand Down
30 changes: 29 additions & 1 deletion web/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class GitGraphView {
private readonly viewElem: HTMLElement;
private readonly controlsElem: HTMLElement;
private readonly tableElem: HTMLElement;
private tableColHeadersElem: HTMLElement | null;
private readonly footerElem: HTMLElement;
private readonly showRemoteBranchesElem: HTMLInputElement;
private readonly refreshBtnElem: HTMLElement;
Expand All @@ -72,6 +73,7 @@ class GitGraphView {

this.controlsElem = document.getElementById('controls')!;
this.tableElem = document.getElementById('commitTable')!;
this.tableColHeadersElem = document.getElementById('tableColHeaders');
this.footerElem = document.getElementById('footer')!;
this.scrollShadowElem = <HTMLInputElement>document.getElementById('scrollShadow')!;

Expand Down Expand Up @@ -818,7 +820,8 @@ class GitGraphView {
markdown: this.config.markdown
});

let html = '<tr id="tableColHeaders"><th id="tableHeaderGraphCol" class="tableColHeader" data-col="0">Graph</th><th class="tableColHeader" data-col="1">Description</th>' +
const stickyClassAttr = this.config.stickyHeader ? ' class="sticky"' : '';
let html = '<tr id="tableColHeaders"' + stickyClassAttr + '><th id="tableHeaderGraphCol" class="tableColHeader" data-col="0">Graph</th><th class="tableColHeader" data-col="1">Description</th>' +
(colVisibility.date ? '<th class="tableColHeader dateCol" data-col="2">Date</th>' : '') +
(colVisibility.author ? '<th class="tableColHeader authorCol" data-col="3">Author</th>' : '') +
(colVisibility.commit ? '<th class="tableColHeader" data-col="4">Commit</th>' : '') +
Expand Down Expand Up @@ -920,6 +923,11 @@ class GitGraphView {
}
}
}

if (this.config.stickyHeader) {
this.tableColHeadersElem = document.getElementById('tableColHeaders');
this.alignTableHeaderToControls();
}
}

private renderUncommittedChanges() {
Expand Down Expand Up @@ -1941,6 +1949,22 @@ class GitGraphView {

/* Observers */

private alignTableHeaderToControls() {
if (!this.tableColHeadersElem) {
return;
}

const controlsHeight = this.controlsElem.offsetHeight;
const controlsWidth = this.controlsElem.offsetWidth;
const tableColHeadersHeight = this.tableColHeadersElem.offsetHeight;
const bottomBorderWidth = 1;
const shadowYPos = controlsHeight + tableColHeadersHeight + bottomBorderWidth;

this.tableColHeadersElem.style.top = `${controlsHeight}px`;
this.scrollShadowElem.style.top = `${shadowYPos}px`;
this.scrollShadowElem.style.width = `${controlsWidth}px`;
}

private observeWindowSizeChanges() {
let windowWidth = window.outerWidth, windowHeight = window.outerHeight;
window.addEventListener('resize', () => {
Expand All @@ -1950,6 +1974,10 @@ class GitGraphView {
windowWidth = window.outerWidth;
windowHeight = window.outerHeight;
}

if (this.config.stickyHeader) {
this.alignTableHeaderToControls();
}
});
}

Expand Down
4 changes: 2 additions & 2 deletions web/styles/contextMenu.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
.contextMenu{
display:block;
position:absolute;
position:fixed;
background-color:var(--vscode-menu-background);
box-shadow:0 1px 4px 1px var(--vscode-widget-shadow);
color:var(--vscode-menu-foreground);
list-style-type:none;
margin:0;
padding:4px 0;
z-index:10;
z-index:13;
-webkit-user-select:none;
user-select:none;
}
Expand Down
22 changes: 18 additions & 4 deletions web/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ code{
top:0;
left:0;
right:0;
height:0;
box-shadow:0 -6px 6px 6px var(--vscode-scrollbar-shadow);
z-index:20;
height:6px;
box-shadow:inset 0 6px 6px -6px var(--vscode-scrollbar-shadow);
z-index:11;
pointer-events:none;
}


Expand Down Expand Up @@ -214,7 +215,8 @@ code{
padding:0 4px;
}
#commitTable th{
border-bottom:1px solid rgba(128,128,128,0.5);
border-bottom:1px solid transparent;
box-shadow:0 1px 0 rgba(128,128,128,0.5);
line-height:18px;
padding:6px 12px;
}
Expand Down Expand Up @@ -277,6 +279,12 @@ code{
.tableColHeader{
position:relative;
}
#tableColHeaders.sticky .tableColHeader{
position:sticky;
top:inherit;
z-index:11;
background-color:var(--vscode-editor-background);
}
.resizeCol{
position:absolute;
top:0;
Expand Down Expand Up @@ -781,6 +789,7 @@ body.tagLabelsRightAligned .gitRef.tag{
right:0;
top:0;
padding:4px 132px 4px 0;
background-color:var(--vscode-editor-background);
border-bottom:1px solid rgba(128,128,128,0.5);
line-height:32px;
text-align:center;
Expand All @@ -790,6 +799,11 @@ body.tagLabelsRightAligned .gitRef.tag{
user-select:none;
}

#controls.sticky{
position:sticky;
z-index:12;
}

#repoControl, #branchControl, #showRemoteBranchesControl{
display:inline-block;
white-space:nowrap;
Expand Down
8 changes: 6 additions & 2 deletions web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"compilerOptions": {
"lib": [
"es6",
"dom"
"dom",
"es2016.array.include"
],
"module": "none",
"moduleResolution": "node",
Expand All @@ -13,6 +14,9 @@
"outDir": "../media",
"removeComments": true,
"strict": true,
"target": "es5"
"target": "es5",
"types": [
"node"
]
}
}