Skip to content

Commit 5d161a2

Browse files
committed
Improve context menu for references
1 parent 4e03d70 commit 5d161a2

12 files changed

Lines changed: 152 additions & 8 deletions

src/renderer/components/app.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { PatchViewerOptions } from './patch-viewer';
1313
import { PreferencesDialog } from './preferences-dialog';
1414
import { Field, Settings } from '../../shared/settings';
1515
import { ThemeManager } from '../../shared/theme-manager';
16+
import { InputDialog } from './input-dialog';
1617

1718
export interface AppState {
1819
repos: RepoState[];
@@ -46,6 +47,7 @@ export class App extends React.PureComponent<{}, AppState> {
4647
this.openInitRepoDialog = this.openInitRepoDialog.bind(this);
4748
this.openOpenRepoDialog = this.openOpenRepoDialog.bind(this);
4849
this.openCreateBranchDialog = this.openCreateBranchDialog.bind(this);
50+
this.openInputDialog = this.openInputDialog.bind(this);
4951
this.showNotification = this.showNotification.bind(this);
5052
this.closeModalWindow = this.closeModalWindow.bind(this);
5153
}
@@ -132,14 +134,16 @@ export class App extends React.PureComponent<{}, AppState> {
132134
// Modal components
133135

134136
openCloneRepoDialog() {
135-
const element = <CloneRepoDialog onCloneRepo={this.cloneRepo} onClose={this.closeModalWindow} />
137+
const element = <CloneRepoDialog onCloneRepo={this.cloneRepo}
138+
onClose={this.closeModalWindow} />
136139
this.setState({
137140
modalWindow: element
138141
});
139142
}
140143

141144
openInitRepoDialog() {
142-
const element = <InitRepoDialog onInitRepo={this.initRepo} onClose={this.closeModalWindow} />
145+
const element = <InitRepoDialog onInitRepo={this.initRepo}
146+
onClose={this.closeModalWindow} />
143147
this.setState({
144148
modalWindow: element
145149
});
@@ -166,7 +170,20 @@ export class App extends React.PureComponent<{}, AppState> {
166170
}
167171

168172
openCreateBranchDialog(commit: Git.Commit) {
169-
const element = <CreateBranchDialog repo={this.getCurrentRepo()} commit={commit} onClose={this.closeModalWindow} />;
173+
const element = <CreateBranchDialog repo={this.getCurrentRepo()}
174+
commit={commit}
175+
onClose={this.closeModalWindow} />;
176+
this.setState({
177+
modalWindow: element
178+
});
179+
}
180+
181+
openInputDialog(label: string, button: string, onSubmit: (value: string) => void, defaultValue?: string) {
182+
const element = <InputDialog label={label}
183+
button={button}
184+
defaultValue={defaultValue}
185+
onSubmit={onSubmit}
186+
onClose={this.closeModalWindow} />
170187
this.setState({
171188
modalWindow: element
172189
});
@@ -190,6 +207,7 @@ export class App extends React.PureComponent<{}, AppState> {
190207
patchViewerOptions={this.state.patchViewerOptions}
191208
onRepoClose={() => this.closeRepo(i)}
192209
onCreateBranch={this.openCreateBranchDialog}
210+
onOpenInputDialog={this.openInputDialog}
193211
key={repo.path} />);
194212
return (
195213
<div id='app'>

src/renderer/components/commit-item.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { remote, clipboard } from 'electron';
22
import * as React from 'react';
33
import * as Git from 'nodegit';
44
import { ReferenceBadge } from './reference-badge';
5+
import { InputDialogHandler } from './input-dialog';
56
import { RepoState, Stash } from '../helpers/repo-state';
67
import { createStashContextMenu } from '../helpers/stash-context-menu';
78

@@ -15,6 +16,7 @@ export interface CommitItemProps {
1516
stash?: Stash;
1617
onCommitSelect: (commit: Git.Commit) => void;
1718
onCreateBranch: (commit: Git.Commit) => void;
19+
onOpenInputDialog: InputDialogHandler;
1820
}
1921

2022
export class CommitItem extends React.PureComponent<CommitItemProps, {}> {
@@ -75,6 +77,7 @@ export class CommitItem extends React.PureComponent<CommitItemProps, {}> {
7577
color={this.props.color}
7678
selected={name === this.props.head}
7779
repo={this.props.repo}
80+
onOpenInputDialog={this.props.onOpenInputDialog}
7881
key={name} />
7982
));
8083
return (

src/renderer/components/commit-list.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react';
22
import * as Git from 'nodegit';
33
import { CommitItem } from './commit-item';
44
import { IndexItem } from './index-item';
5+
import { InputDialogHandler } from './input-dialog';
56
import { RepoState } from '../helpers/repo-state';
67
import { getBranchColor } from '../helpers/commit-graph';
78

@@ -13,6 +14,7 @@ export interface CommitListProps {
1314
onCommitSelect: (commit: Git.Commit) => void;
1415
onIndexSelect: () => void;
1516
onCreateBranch: (commit: Git.Commit) => void;
17+
onOpenInputDialog: InputDialogHandler;
1618
onScroll: (height: number, start: number, end: number) => void;
1719
onResize: (offset: number, start: number, end: number) => void;
1820
onStateUpdate: (start: number, end: number) => void;
@@ -140,6 +142,7 @@ export class CommitList extends React.PureComponent<CommitListProps, CommitListS
140142
selected={this.props.selectedCommit !== null && this.props.selectedCommit.sha() === commit.sha()}
141143
onCommitSelect={this.props.onCommitSelect}
142144
onCreateBranch={this.props.onCreateBranch}
145+
onOpenInputDialog={this.props.onOpenInputDialog}
143146
color={color}
144147
stash={this.props.repo.stashes.get(commitSha)}
145148
key={commit.sha()} />

src/renderer/components/graph-viewer.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { GraphCanvas } from './graph-canvas';
44
import { CommitList } from './commit-list';
55
import { Splitter } from './splitter';
66
import { ReferenceExplorer } from './reference-explorer'
7+
import { InputDialogHandler } from './input-dialog';
78
import { RepoState } from "../helpers/repo-state";
89

910
export interface GraphViewerProps {
@@ -12,6 +13,7 @@ export interface GraphViewerProps {
1213
onCommitSelect: (commit: Git.Commit) => void;
1314
onIndexSelect: () => void;
1415
onCreateBranch: (commit: Git.Commit) => void;
16+
onOpenInputDialog: InputDialogHandler;
1517
}
1618

1719
export class GraphViewer extends React.PureComponent<GraphViewerProps, {}> {
@@ -82,6 +84,7 @@ export class GraphViewer extends React.PureComponent<GraphViewerProps, {}> {
8284
<ReferenceExplorer repo={this.props.repo}
8385
onCommitSelect={this.props.onCommitSelect}
8486
onIndexSelect={this.props.onIndexSelect}
87+
onOpenInputDialog={this.props.onOpenInputDialog}
8588
ref={this.referenceExplorer} />
8689
<Splitter onDrag={this.handleLeftPanelResize} />
8790
<div className='graph-container'>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as React from 'react';
2+
import { makeModal } from './make-modal';
3+
4+
export type InputDialogHandler = (label: string, button: string, onSubmit: (value: string) => void, defaultValue?: string) => void;
5+
6+
export class InputFormProps {
7+
defaultValue?: string;
8+
label: string;
9+
button: string;
10+
onSubmit: (value: string) => void;
11+
onClose: () => void;
12+
}
13+
14+
export class InputFormState {
15+
value: string;
16+
}
17+
18+
class InputForm extends React.PureComponent<InputFormProps, InputFormState> {
19+
constructor(props: InputFormProps) {
20+
super(props);
21+
this.state = {
22+
value: this.props.defaultValue || '',
23+
}
24+
this.handleValueChange = this.handleValueChange.bind(this);
25+
this.handleSubmit = this.handleSubmit.bind(this);
26+
}
27+
28+
handleValueChange(event: React.ChangeEvent<HTMLInputElement>) {
29+
this.setState({value: event.target.value});
30+
}
31+
32+
async handleSubmit(event: React.FormEvent<HTMLFormElement>) {
33+
event.preventDefault();
34+
if (this.state.value) {
35+
this.props.onSubmit(this.state.value);
36+
this.props.onClose();
37+
}
38+
}
39+
40+
render() {
41+
return (
42+
<form className='modal-form' onSubmit={this.handleSubmit}>
43+
<div className='field-container'>
44+
<label htmlFor='value'>{this.props.label}:</label>
45+
<input type='text'
46+
id='value'
47+
value={this.state.value}
48+
autoFocus={true}
49+
onChange={this.handleValueChange} />
50+
</div>
51+
<div className='button-container'>
52+
<button className='green-button'
53+
type='submit'
54+
disabled={!this.state.value}>
55+
{this.props.button}
56+
</button>
57+
</div>
58+
</form>
59+
);
60+
}
61+
}
62+
63+
export const InputDialog = makeModal(InputForm);

src/renderer/components/reference-badge.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import * as React from 'react';
22
import { RepoState, removeReferencePrefix } from "../helpers/repo-state";
33
import { createReferenceContextMenu } from '../helpers/reference-context-menu';
4+
import { InputDialogHandler } from './input-dialog';
45

56
export class ReferenceBadgeProps {
67
name: string;
78
color: string;
89
selected: boolean;
910
repo: RepoState;
11+
onOpenInputDialog: InputDialogHandler;
1012
}
1113

1214
export class ReferenceBadge extends React.PureComponent<ReferenceBadgeProps, {}> {
@@ -19,7 +21,7 @@ export class ReferenceBadge extends React.PureComponent<ReferenceBadgeProps, {}>
1921
handleContextMenu(event: React.MouseEvent<HTMLSpanElement>) {
2022
event.preventDefault();
2123
event.stopPropagation();
22-
const menu = createReferenceContextMenu(this.props.repo, this.props.name, this.props.selected);
24+
const menu = createReferenceContextMenu(this.props.repo, this.props.name, this.props.selected, this.props.onOpenInputDialog);
2325
menu.popup({});
2426
}
2527

@@ -35,7 +37,9 @@ export class ReferenceBadge extends React.PureComponent<ReferenceBadgeProps, {}>
3537
classNames.push('selected');
3638
}
3739
return (
38-
<span className={classNames.join(' ')} style={style} onContextMenu={this.handleContextMenu} onDoubleClick={this.handleDoubleClick}>
40+
<span className={classNames.join(' ')} style={style}
41+
onContextMenu={this.handleContextMenu}
42+
onDoubleClick={this.handleDoubleClick}>
3943
{removeReferencePrefix(this.props.name)}
4044
</span>
4145
);

src/renderer/components/reference-explorer.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import { RepoState } from '../helpers/repo-state';
44
import { ReferenceItem } from './reference-item';
55
import { ReferenceList } from './reference-list';
66
import { StashList } from './stash-list';
7+
import { InputDialogHandler } from './input-dialog';
78

89
export interface ReferenceExplorerProps {
910
repo: RepoState;
1011
onCommitSelect: (commit: Git.Commit) => void;
1112
onIndexSelect: () => void;
13+
onOpenInputDialog: InputDialogHandler;
1214
}
1315

1416
export interface ReferenceExplorerState {
@@ -34,12 +36,14 @@ export class ReferenceExplorer extends React.PureComponent<ReferenceExplorerProp
3436
<ReferenceItem repo={this.props.repo}
3537
name='Index'
3638
selected={false}
39+
onOpenInputDialog={this.props.onOpenInputDialog}
3740
onClick={this.props.onIndexSelect} />
3841
<h3>Branches</h3>
3942
<ReferenceList repo={this.props.repo}
4043
names={[...this.props.repo.references.keys()]}
4144
commits={[...this.props.repo.references.values()]}
4245
head={this.props.repo.head}
46+
onOpenInputDialog={this.props.onOpenInputDialog}
4347
onClick={this.props.onCommitSelect} />
4448
<h3>Stashes</h3>
4549
<StashList repo={this.props.repo}

src/renderer/components/reference-item.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import * as React from 'react';
22
import { removeReferencePrefix, RepoState } from '../helpers/repo-state';
33
import { createReferenceContextMenu } from '../helpers/reference-context-menu';
4+
import { InputDialogHandler } from './input-dialog';
45

56
export interface ReferenceItemProps {
67
repo: RepoState;
78
name: string;
89
selected: boolean;
10+
onOpenInputDialog: InputDialogHandler;
911
onClick: () => void;
1012
}
1113

@@ -18,7 +20,7 @@ export class ReferenceItem extends React.PureComponent<ReferenceItemProps, {}> {
1820

1921
handleContextMenu(event: React.MouseEvent<HTMLSpanElement>) {
2022
event.preventDefault();
21-
const menu = createReferenceContextMenu(this.props.repo, this.props.name, this.props.selected);
23+
const menu = createReferenceContextMenu(this.props.repo, this.props.name, this.props.selected, this.props.onOpenInputDialog);
2224
menu.popup({});
2325
}
2426

src/renderer/components/reference-list.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import * as React from 'react';
22
import * as Git from 'nodegit';
33
import { ReferenceItem } from './reference-item';
4+
import { InputDialogHandler } from './input-dialog';
45
import { RepoState } from '../helpers/repo-state';
56

67
export interface ReferenceListProps {
78
repo: RepoState;
89
head: string | null;
910
names: string[];
1011
commits: Git.Commit[];
12+
onOpenInputDialog: InputDialogHandler;
1113
onClick: (commit: Git.Commit) => void;
1214
}
1315

@@ -17,6 +19,7 @@ export class ReferenceList extends React.PureComponent<ReferenceListProps, {}> {
1719
<ReferenceItem repo={this.props.repo}
1820
name={name}
1921
selected={this.props.head === name}
22+
onOpenInputDialog={this.props.onOpenInputDialog}
2023
onClick={() => this.props.onClick(this.props.commits[i])}
2124
key={name} />
2225
));

src/renderer/components/repo-dashboard.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { IndexViewer } from './index-viewer';
99
import { PatchViewer, PatchViewerOptions } from './patch-viewer';
1010
import { Splitter } from './splitter';
1111
import { Toolbar } from './toolbar';
12+
import { InputDialogHandler } from './input-dialog';
1213
import { RepoState, PatchType } from '../helpers/repo-state';
1314

1415
export interface RepoDashboardProps {
@@ -17,6 +18,7 @@ export interface RepoDashboardProps {
1718
patchViewerOptions: PatchViewerOptions;
1819
onRepoClose: () => void;
1920
onCreateBranch: (commit: Git.Commit) => void;
21+
onOpenInputDialog: InputDialogHandler;
2022
}
2123

2224
export interface RepoDashboardState {
@@ -207,6 +209,7 @@ export class RepoDashboard extends React.PureComponent<RepoDashboardProps, RepoD
207209
onCommitSelect={this.handleCommitSelect}
208210
onIndexSelect={this.handleIndexSelect}
209211
onCreateBranch={this.props.onCreateBranch}
212+
onOpenInputDialog={this.props.onOpenInputDialog}
210213
ref={this.graphViewer} />
211214
}
212215
let rightViewer;

0 commit comments

Comments
 (0)