Skip to content

Commit 13377aa

Browse files
committed
Add colours for files in browser
1 parent 3e08ea2 commit 13377aa

File tree

6 files changed

+141
-8
lines changed

6 files changed

+141
-8
lines changed

src/browserDecorations.ts

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Git, IGitExtension } from './tokens';
2+
import * as fileStyle from './style/BrowserFile';
3+
import { DirListing, FileBrowser } from '@jupyterlab/filebrowser';
4+
import { Contents } from '@jupyterlab/services';
5+
import { DocumentRegistry } from '@jupyterlab/docregistry';
6+
import { ITranslator } from '@jupyterlab/translation';
7+
8+
const statusStyles: Map<Git.StatusCode, string> = new Map([
9+
['M', fileStyle.modified],
10+
['A', fileStyle.added],
11+
['D', fileStyle.deleted],
12+
['R', fileStyle.modified],
13+
['C', fileStyle.modified],
14+
['U', fileStyle.modified],
15+
['?', fileStyle.untracked],
16+
['!', fileStyle.ignored]
17+
]);
18+
19+
class GitListingRenderer extends DirListing.Renderer {
20+
constructor(private gitExtension: IGitExtension) {
21+
super();
22+
}
23+
24+
updateItemNode(
25+
node: HTMLElement,
26+
model: Contents.IModel,
27+
fileType?: DocumentRegistry.IFileType,
28+
translator?: ITranslator
29+
) {
30+
super.updateItemNode(node, model, fileType, translator);
31+
const file = this.gitExtension.getFile(model.path);
32+
console.log(model.path, 'file status', file?.status);
33+
let status_code: Git.StatusCode = null;
34+
if (file) {
35+
status_code = file.status === 'staged' ? file.x : file.y;
36+
console.log(model.path, 'file x, y', file.x, file.y);
37+
console.log(model.path, 'file status code', status_code);
38+
}
39+
40+
for (const [otherStatus, className] of statusStyles.entries()) {
41+
if (status_code === otherStatus) {
42+
node.classList.add(className);
43+
} else {
44+
node.classList.remove(className);
45+
}
46+
}
47+
}
48+
}
49+
50+
export function substituteListingRenderer(
51+
extension: IGitExtension,
52+
fileBrowser: FileBrowser
53+
): void {
54+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
55+
// @ts-ignore
56+
const listing: DirListing = fileBrowser._listing;
57+
const renderer = new GitListingRenderer(extension);
58+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
59+
// @ts-ignore
60+
listing._renderer = renderer;
61+
}

src/components/FileItem.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ import {
1313
import { Git } from '../tokens';
1414
import { FilePath } from './FilePath';
1515

16-
// Git status codes https://git-scm.com/docs/git-status
17-
export const STATUS_CODES = {
16+
export const STATUS_CODES: Record<Git.StatusCode, string> = {
1817
M: 'Modified',
1918
A: 'Added',
2019
D: 'Deleted',
2120
R: 'Renamed',
2221
C: 'Copied',
2322
U: 'Updated',
2423
'?': 'Untracked',
25-
'!': 'Ignored'
24+
'!': 'Ignored',
25+
' ': 'Unchanged'
2626
};
2727

2828
/**
@@ -124,7 +124,7 @@ export interface IFileItemProps {
124124
}
125125

126126
export class FileItem extends React.PureComponent<IFileItemProps> {
127-
protected _getFileChangedLabel(change: keyof typeof STATUS_CODES): string {
127+
protected _getFileChangedLabel(change: Git.StatusCode): string {
128128
return STATUS_CODES[change];
129129
}
130130

@@ -157,7 +157,7 @@ export class FileItem extends React.PureComponent<IFileItemProps> {
157157
render(): JSX.Element {
158158
const { file } = this.props;
159159
const status_code = file.status === 'staged' ? file.x : file.y;
160-
const status = this._getFileChangedLabel(status_code as any);
160+
const status = this._getFileChangedLabel(status_code);
161161

162162
return (
163163
<div

src/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { GitWidget } from './widgets/GitWidget';
2525
import { addStatusBarWidget } from './widgets/StatusWidget';
2626

2727
export { Git, IGitExtension } from './tokens';
28+
import { substituteListingRenderer } from './browserDecorations';
2829

2930
/**
3031
* The default running sessions extension.
@@ -181,6 +182,8 @@ async function activate(
181182
app.commands,
182183
app.contextMenu
183184
);
185+
186+
substituteListingRenderer(gitExtension, factory.defaultBrowser);
184187
}
185188

186189
return gitExtension;

src/style/BrowserFile.ts

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { style } from 'typestyle';
2+
3+
export const modified = style({
4+
$nest: {
5+
'&:not(.jp-mod-selected)': {
6+
$nest: {
7+
'.jp-DirListing-itemText': {
8+
color: 'var(--md-blue-700)'
9+
}
10+
}
11+
}
12+
}
13+
});
14+
15+
export const untracked = style({
16+
$nest: {
17+
'&:not(.jp-mod-selected)': {
18+
$nest: {
19+
'.jp-DirListing-itemText': {
20+
color: 'var(--md-red-700)'
21+
}
22+
}
23+
}
24+
}
25+
});
26+
27+
export const added = style({
28+
$nest: {
29+
'&:not(.jp-mod-selected)': {
30+
$nest: {
31+
'.jp-DirListing-itemText': {
32+
color: 'var(--md-green-700)'
33+
}
34+
}
35+
}
36+
}
37+
});
38+
39+
export const ignored = style({
40+
$nest: {
41+
'&:not(.jp-mod-selected)': {
42+
$nest: {
43+
'.jp-DirListing-itemText': {
44+
color: 'var(--md-grey-700)'
45+
}
46+
}
47+
}
48+
}
49+
});
50+
51+
export const deleted = style({
52+
$nest: {
53+
'&:not(.jp-mod-selected)': {
54+
$nest: {
55+
'.jp-DirListing-itemText': {
56+
color: 'var(--md-grey-700)'
57+
}
58+
}
59+
},
60+
'.jp-DirListing-itemText': {
61+
textDecoration: 'line-through'
62+
}
63+
}
64+
});

src/tokens.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -604,8 +604,8 @@ export namespace Git {
604604
* has the status of each changed file
605605
*/
606606
export interface IStatusFileResult {
607-
x: string;
608-
y: string;
607+
x: StatusCode;
608+
y: StatusCode;
609609
to: string;
610610
from: string;
611611
is_binary: boolean | null;
@@ -750,6 +750,11 @@ export namespace Git {
750750
| 'partially-staged'
751751
| null;
752752

753+
/**
754+
* Git status codes https://git-scm.com/docs/git-status
755+
*/
756+
export type StatusCode = 'M' | 'A' | 'D' | 'R' | 'C' | 'U' | '?' | '!' | ' ';
757+
753758
export interface ITagResult {
754759
code: number;
755760
message?: string;

tests/test-components/FileItem.spec.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe('FileItem', () => {
77
const props: IFileItemProps = {
88
contextMenu: () => {},
99
file: {
10-
x: '',
10+
x: ' ',
1111
y: 'M',
1212
to: 'some/file/path/file-name',
1313
from: '',

0 commit comments

Comments
 (0)