Skip to content

Commit 1fd00aa

Browse files
authored
Merge pull request #785 from fcollonval/be-more-react
Propagate data through components tree...
2 parents 606e97b + a07b870 commit 1fd00aa

File tree

8 files changed

+205
-322
lines changed

8 files changed

+205
-322
lines changed

src/components/BranchMenu.tsx

+15-61
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ function renderFileName(filename: string): React.ReactElement {
8787
* Interface describing component properties.
8888
*/
8989
export interface IBranchMenuProps {
90+
/**
91+
* Current branch name.
92+
*/
93+
currentBranch: string;
94+
95+
/**
96+
* Current list of branches.
97+
*/
98+
branches: Git.IBranch[];
99+
90100
/**
91101
* Boolean indicating whether branching is disabled.
92102
*/
@@ -107,21 +117,11 @@ export interface IBranchMenuProps {
107117
* Interface describing component state.
108118
*/
109119
export interface IBranchMenuState {
110-
/**
111-
* Current branch name.
112-
*/
113-
current: string;
114-
115120
/**
116121
* Boolean indicating whether to show a dialog to create a new branch.
117122
*/
118123
branchDialog: boolean;
119124

120-
/**
121-
* Current list of branches.
122-
*/
123-
branches: Git.IBranch[];
124-
125125
/**
126126
* Menu filter.
127127
*/
@@ -144,30 +144,12 @@ export class BranchMenu extends React.Component<
144144
constructor(props: IBranchMenuProps) {
145145
super(props);
146146

147-
const repo = this.props.model.pathRepository;
148-
149147
this.state = {
150148
filter: '',
151-
branchDialog: false,
152-
current: repo ? this.props.model.currentBranch.name : '',
153-
branches: repo ? this.props.model.branches : []
149+
branchDialog: false
154150
};
155151
}
156152

157-
/**
158-
* Callback invoked immediately after mounting a component (i.e., inserting into a tree).
159-
*/
160-
componentDidMount(): void {
161-
this._addListeners();
162-
}
163-
164-
/**
165-
* Callback invoked when a component will no longer be mounted.
166-
*/
167-
componentWillUnmount(): void {
168-
this._removeListeners();
169-
}
170-
171153
/**
172154
* Renders the component.
173155
*
@@ -229,7 +211,7 @@ export class BranchMenu extends React.Component<
229211
private _renderBranchList(): React.ReactElement {
230212
// Perform a "simple" filter... (TODO: consider implementing fuzzy filtering)
231213
const filter = this.state.filter;
232-
const branches = this.state.branches.filter(
214+
const branches = this.props.branches.filter(
233215
branch => !filter || branch.name.includes(filter)
234216
);
235217
return (
@@ -259,7 +241,7 @@ export class BranchMenu extends React.Component<
259241
private _renderItem = (props: ListChildComponentProps): JSX.Element => {
260242
const { data, index, style } = props;
261243
const branch = data[index] as Git.IBranch;
262-
const isActive = branch.name === this.state.current;
244+
const isActive = branch.name === this.props.currentBranch;
263245
return (
264246
<ListItem
265247
button
@@ -285,6 +267,8 @@ export class BranchMenu extends React.Component<
285267
private _renderNewBranchDialog(): React.ReactElement {
286268
return (
287269
<NewBranchDialog
270+
currentBranch={this.props.currentBranch}
271+
branches={this.props.branches}
288272
logger={this.props.logger}
289273
open={this.state.branchDialog}
290274
model={this.props.model}
@@ -293,36 +277,6 @@ export class BranchMenu extends React.Component<
293277
);
294278
}
295279

296-
/**
297-
* Adds model listeners.
298-
*/
299-
private _addListeners(): void {
300-
// When the HEAD changes, decent probability that we've switched branches:
301-
this.props.model.headChanged.connect(this._syncState, this);
302-
303-
// When the status changes, we may have checked out a new branch (e.g., via the command-line and not via the extension) or changed repositories:
304-
this.props.model.statusChanged.connect(this._syncState, this);
305-
}
306-
307-
/**
308-
* Removes model listeners.
309-
*/
310-
private _removeListeners(): void {
311-
this.props.model.headChanged.disconnect(this._syncState, this);
312-
this.props.model.statusChanged.disconnect(this._syncState, this);
313-
}
314-
315-
/**
316-
* Syncs the component state with the underlying model.
317-
*/
318-
private _syncState(): void {
319-
const repo = this.props.model.pathRepository;
320-
this.setState({
321-
current: repo ? this.props.model.currentBranch.name : '',
322-
branches: repo ? this.props.model.branches : []
323-
});
324-
}
325-
326280
/**
327281
* Callback invoked upon a change to the menu filter.
328282
*

src/components/GitPanel.tsx

+8-5
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ export interface IGitPanelProps {
6161
*/
6262
export interface IGitPanelState {
6363
/**
64-
* Boolean indicating whether the user is currently in a Git repository.
64+
* Git path repository
6565
*/
66-
inGitRepository: boolean;
66+
repository: string | null;
6767

6868
/**
6969
* List of branches.
@@ -108,7 +108,7 @@ export class GitPanel extends React.Component<IGitPanelProps, IGitPanelState> {
108108
branches: [],
109109
currentBranch: '',
110110
files: [],
111-
inGitRepository: false,
111+
repository: null,
112112
pastCommits: [],
113113
tab: 0
114114
};
@@ -122,7 +122,7 @@ export class GitPanel extends React.Component<IGitPanelProps, IGitPanelState> {
122122

123123
model.repositoryChanged.connect((_, args) => {
124124
this.setState({
125-
inGitRepository: args.newValue !== null
125+
repository: args.newValue
126126
});
127127
this.refresh();
128128
}, this);
@@ -249,7 +249,7 @@ export class GitPanel extends React.Component<IGitPanelProps, IGitPanelState> {
249249
render(): React.ReactElement {
250250
return (
251251
<div className={panelWrapperClass}>
252-
{this.state.inGitRepository ? (
252+
{this.state.repository ? (
253253
<React.Fragment>
254254
{this._renderToolbar()}
255255
{this._renderMain()}
@@ -273,11 +273,14 @@ export class GitPanel extends React.Component<IGitPanelProps, IGitPanelState> {
273273
);
274274
return (
275275
<Toolbar
276+
currentBranch={this.state.currentBranch}
277+
branches={this.state.branches}
276278
branching={!disableBranching}
277279
commands={this.props.commands}
278280
logger={this.props.logger}
279281
model={this.props.model}
280282
refresh={this._onRefresh}
283+
repository={this.state.repository || ''}
281284
/>
282285
);
283286
}

src/components/NewBranchDialog.tsx

+20-66
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ const HEIGHT = 200; // HTML element height for the branches list
4949
* Interface describing component properties.
5050
*/
5151
export interface INewBranchDialogProps {
52+
/**
53+
* Current branch name.
54+
*/
55+
currentBranch: string;
56+
57+
/**
58+
* Current list of branches.
59+
*/
60+
branches: Git.IBranch[];
61+
5262
/**
5363
* Extension logger
5464
*/
@@ -89,16 +99,6 @@ export interface INewBranchDialogState {
8999
*/
90100
filter: string;
91101

92-
/**
93-
* Current branch name.
94-
*/
95-
current: string;
96-
97-
/**
98-
* Current list of branches.
99-
*/
100-
branches: Git.IBranch[];
101-
102102
/**
103103
* Error message.
104104
*/
@@ -120,33 +120,16 @@ export class NewBranchDialog extends React.Component<
120120
*/
121121
constructor(props: INewBranchDialogProps) {
122122
super(props);
123-
124-
const repo = this.props.model.pathRepository;
125123
this._branchList = React.createRef<VariableSizeList>();
126124

127125
this.state = {
128126
name: '',
129-
base: repo ? this.props.model.currentBranch.name : '',
127+
base: props.currentBranch || '',
130128
filter: '',
131-
current: repo ? this.props.model.currentBranch.name : '',
132-
branches: repo ? this.props.model.branches : [],
133129
error: ''
134130
};
135131
}
136132

137-
/**
138-
* Callback invoked immediately after mounting a component (i.e., inserting into a tree).
139-
*/
140-
componentDidMount(): void {
141-
this._addListeners();
142-
}
143-
144-
/**
145-
* Callback invoked when a component will no longer be mounted.
146-
*/
147-
componentWillUnmount(): void {
148-
this._removeListeners();
149-
}
150133
/**
151134
* Renders a dialog for creating a new branch.
152135
*
@@ -235,10 +218,10 @@ export class NewBranchDialog extends React.Component<
235218
* @returns array of React elements
236219
*/
237220
private _renderItems(): JSX.Element {
238-
const current = this.props.model.currentBranch.name;
221+
const current = this.props.currentBranch;
239222
// Perform a "simple" filter... (TODO: consider implementing fuzzy filtering)
240223
const filter = this.state.filter;
241-
const branches = this.state.branches
224+
const branches = this.props.branches
242225
.filter(branch => !filter || branch.name.includes(filter))
243226
.slice()
244227
.sort(comparator);
@@ -252,7 +235,7 @@ export class NewBranchDialog extends React.Component<
252235
itemKey={(index, data) => data[index].name}
253236
itemSize={index => {
254237
const branch = branches[index];
255-
return branch.name === this.state.current
238+
return branch.name === this.props.currentBranch
256239
? CURRENT_BRANCH_HEIGHT
257240
: ITEM_HEIGHT;
258241
}}
@@ -302,20 +285,22 @@ export class NewBranchDialog extends React.Component<
302285
const { data, index, style } = props;
303286
const branch = data[index] as Git.IBranch;
304287

305-
const isBase = branch.name === this.state.base;
306-
const isCurr = branch.name === this.state.current;
288+
const isCurrent = branch.name === this.props.currentBranch;
307289

308290
let isBold;
309291
let desc;
310-
if (isCurr) {
292+
if (isCurrent) {
311293
isBold = true;
312294
desc = BRANCH_DESC['current'];
313295
}
314296
return (
315297
<ListItem
316298
button
317299
title={`Create a new branch based on: ${branch.name}`}
318-
className={classes(listItemClass, isBase ? activeListItemClass : null)}
300+
className={classes(
301+
listItemClass,
302+
isCurrent ? activeListItemClass : null
303+
)}
319304
onClick={this._onBranchClickFactory(branch.name)}
320305
style={style}
321306
>
@@ -335,37 +320,6 @@ export class NewBranchDialog extends React.Component<
335320
);
336321
};
337322

338-
/**
339-
* Adds model listeners.
340-
*/
341-
private _addListeners(): void {
342-
// When the HEAD changes, decent probability that we've switched branches:
343-
this.props.model.headChanged.connect(this._syncState, this);
344-
345-
// When the status changes, we may have checked out a new branch (e.g., via the command-line and not via the extension) or changed repositories:
346-
this.props.model.statusChanged.connect(this._syncState, this);
347-
}
348-
349-
/**
350-
* Removes model listeners.
351-
*/
352-
private _removeListeners(): void {
353-
this.props.model.headChanged.disconnect(this._syncState, this);
354-
this.props.model.statusChanged.disconnect(this._syncState, this);
355-
}
356-
357-
/**
358-
* Syncs the component state with the underlying model.
359-
*/
360-
private _syncState(): void {
361-
const repo = this.props.model.pathRepository;
362-
this.setState({
363-
base: repo ? this.state.base : '',
364-
current: repo ? this.props.model.currentBranch.name : '',
365-
branches: repo ? this.props.model.branches : []
366-
});
367-
}
368-
369323
/**
370324
* Callback invoked upon closing the dialog.
371325
*

0 commit comments

Comments
 (0)