From 362f65d13b969ec1d2a92b45b174c1c5ef85e98b Mon Sep 17 00:00:00 2001 From: bendera Date: Mon, 12 Oct 2020 22:33:33 +0200 Subject: [PATCH] #132 Add sticky header option --- package.json | 5 ++++ src/config.ts | 7 +++++ src/gitGraphView.ts | 4 ++- src/types.ts | 1 + tests/config.test.ts | 62 ++++++++++++++++++++++++++++++++++++++++++++ web/main.ts | 3 ++- web/styles/main.css | 17 ++++++++++-- 7 files changed, 95 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 241517b7..14935b9d 100644 --- a/package.json +++ b/package.json @@ -460,6 +460,11 @@ }, "description": "An object specifying the default visibility of the Date, Author & Commit columns. Example: {\"Date\": true, \"Author\": true, \"Commit\": true}" }, + "git-graph.stickyHeader": { + "type": "boolean", + "default": true, + "description": "Keeps the header visible when the view is scrolled" + }, "git-graph.dialog.addTag.pushToRemote": { "type": "boolean", "default": false, diff --git a/src/config.ts b/src/config.ts index f297c00f..f9650db8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -489,6 +489,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. */ diff --git a/src/gitGraphView.ts b/src/gitGraphView.ts index 87cb0c48..a958ee03 100644 --- a/src/gitGraphView.ts +++ b/src/gitGraphView.ts @@ -589,6 +589,7 @@ export class GitGraphView extends Disposable { customPullRequestProviders: config.customPullRequestProviders, dateFormat: config.dateFormat, defaultColumnVisibility: config.defaultColumnVisibility, + stickyHeader: config.stickyHeader, dialogDefaults: config.dialogDefaults, enhancedAccessibility: config.enhancedAccessibility, fetchAndPrune: config.fetchAndPrune, @@ -628,9 +629,10 @@ export class GitGraphView extends Disposable {

${UNABLE_TO_FIND_GIT_MSG}

`; } else if (numRepos > 0) { + const stickyClassAttr = initialState.config.stickyHeader ? ' class="sticky"' : ''; body = `
-
+
Repo: Branches: diff --git a/src/types.ts b/src/types.ts index 10d112e0..2d7aa499 100644 --- a/src/types.ts +++ b/src/types.ts @@ -235,6 +235,7 @@ export interface GitGraphViewConfig { readonly repoDropdownOrder: RepoDropdownOrder; readonly showRemoteBranches: boolean; readonly showTags: boolean; + readonly stickyHeader: boolean; } export interface GitGraphViewGlobalState { diff --git a/tests/config.test.ts b/tests/config.test.ts index 11d72c4f..b45df51c 100644 --- a/tests/config.test.ts +++ b/tests/config.test.ts @@ -3878,4 +3878,66 @@ describe('Config', () => { expect(value).toBe(false); }); }); + + describe('stickyHeader', () => { + it('Should return TRUE when the configuration value is TRUE', () => { + // Setup + workspaceConfiguration.get.mockReturnValueOnce(true); + + // Run + const value = config.stickyHeader; + + // Assert + expect(workspaceConfiguration.get).toBeCalledWith('stickyHeader', true); + expect(value).toBe(true); + }); + + it('Should return FALSE when the configuration value is FALSE', () => { + // Setup + workspaceConfiguration.get.mockReturnValueOnce(false); + + // Run + const value = config.stickyHeader; + + // Assert + expect(workspaceConfiguration.get).toBeCalledWith('stickyHeader', true); + expect(value).toBe(false); + }); + + it('Should return TRUE when the configuration value is truthy', () => { + // Setup + workspaceConfiguration.get.mockReturnValueOnce(5); + + // Run + const value = config.stickyHeader; + + // Assert + expect(workspaceConfiguration.get).toBeCalledWith('stickyHeader', true); + expect(value).toBe(true); + }); + + it('Should return FALSE when the configuration value is falsy', () => { + // Setup + workspaceConfiguration.get.mockReturnValueOnce(0); + + // Run + const value = config.stickyHeader; + + // Assert + expect(workspaceConfiguration.get).toBeCalledWith('stickyHeader', true); + expect(value).toBe(false); + }); + + it('Should return the default value (TRUE) when the configuration value is not set', () => { + // Setup + workspaceConfiguration.get.mockImplementationOnce((_, defaultValue) => defaultValue); + + // Run + const value = config.stickyHeader; + + // Assert + expect(workspaceConfiguration.get).toBeCalledWith('stickyHeader', true); + expect(value).toBe(true); + }); + }); }); diff --git a/web/main.ts b/web/main.ts index 326d6487..0c4c5d43 100644 --- a/web/main.ts +++ b/web/main.ts @@ -734,7 +734,8 @@ class GitGraphView { markdown: this.config.markdown }); - let html = 'GraphDescription' + + const stickyClassAttr = this.config.stickyHeader ? ' class="sticky"' : ''; + let html = 'GraphDescription' + (colVisibility.date ? 'Date' : '') + (colVisibility.author ? 'Author' : '') + (colVisibility.commit ? 'Commit' : '') + diff --git a/web/styles/main.css b/web/styles/main.css index b67ece67..02a760d2 100644 --- a/web/styles/main.css +++ b/web/styles/main.css @@ -210,7 +210,8 @@ body.selection-background-color-exists ::selection{ 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; } @@ -273,6 +274,12 @@ body.selection-background-color-exists ::selection{ .tableColHeader{ position:relative; } +#tableColHeaders.sticky .tableColHeader { + position: sticky; + top: 41px; + z-index: 3; + background-color: var(--vscode-editor-background); +} .resizeCol{ position:absolute; top:0; @@ -759,11 +766,12 @@ body.tagLabelsRightAligned .gitRef.tag{ #controls{ display:block; - position:relative; + position: relative; left:0; 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; @@ -773,6 +781,11 @@ body.tagLabelsRightAligned .gitRef.tag{ user-select:none; } +#controls.sticky { + position:sticky; + z-index: 4; +} + #repoControl, #branchControl, #showRemoteBranchesControl{ display:inline-block; white-space:nowrap;