Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit 5246a4a

Browse files
authored
Merge pull request #2399 from atom/lock-context
Context locking
2 parents 6d10136 + 36d001e commit 5246a4a

26 files changed

+853
-109
lines changed

img/unlock.svg

Lines changed: 61 additions & 0 deletions
Loading

lib/atom/octicon.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,32 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33
import cx from 'classnames';
44

5+
/* eslint-disable max-len */
6+
const SVG = {
7+
unlock: {
8+
viewBox: '0 0 24 16',
9+
element: (
10+
<path
11+
fillRule="evenodd"
12+
d="m 13.4,13 h -1 v -1 h 1 z m 6,-7 h 1 c 0.55,0 1,0.45 1,1 v 7 c 0,0.55 -0.45,1 -1,1 h -10 c -0.55,0 -1,-0.45 -1,-1 V 7 c 0,-0.55 0.45,-1 1,-1 h 1 V 4.085901 C 11.4,2.1862908 9.8780193,2.4095693 8.904902,2.4143325 8.0404588,2.4185637 6.3689542,2.1882296 6.3689542,4.085901 V 7.4918301 L 4.2521568,7.4509801 4.2930068,4.045051 C 4.3176792,1.987953 5.080245,-0.02206145 8.792353,-0.03403364 13.536238,-0.0493335 13.21,3.1688541 13.21,4.085901 V 6 h -0.01 4.41 m 2.79,1 h -9 v 7 h 9 z m -7,1 h -1 v 1 h 1 z m 0,2 h -1 v 1 h 1 z"
13+
/>
14+
),
15+
},
16+
};
17+
/* eslint-enable max-len */
18+
519
export default function Octicon({icon, ...others}) {
620
const classes = cx('icon', `icon-${icon}`, others.className);
21+
22+
const svgContent = SVG[icon];
23+
if (svgContent) {
24+
return (
25+
<svg {...others} viewBox={svgContent.viewBox} xmlns="http://www.w3.org/2000/svg" className={classes}>
26+
{svgContent.element}
27+
</svg>
28+
);
29+
}
30+
731
return <span {...others} className={classes} />;
832
}
933

lib/containers/github-tab-header-container.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ export default class GithubTabHeaderContainer extends React.Component {
1717

1818
// Workspace
1919
currentWorkDir: PropTypes.string,
20+
contextLocked: PropTypes.bool.isRequired,
21+
changeWorkingDirectory: PropTypes.func.isRequired,
22+
setContextLock: PropTypes.func.isRequired,
2023
getCurrentWorkDirs: PropTypes.func.isRequired,
2124

2225
// Event Handlers
23-
handleWorkDirSelect: PropTypes.func,
2426
onDidChangeWorkDirs: PropTypes.func,
2527
}
2628

@@ -59,12 +61,12 @@ export default class GithubTabHeaderContainer extends React.Component {
5961
environment={environment}
6062
variables={{}}
6163
query={query}
62-
render={result => this.renderWithResult(result, token)}
64+
render={result => this.renderWithResult(result)}
6365
/>
6466
);
6567
}
6668

67-
renderWithResult({error, props, retry}, token) {
69+
renderWithResult({error, props}) {
6870
if (error || props === null) {
6971
return this.renderNoResult();
7072
}
@@ -78,10 +80,12 @@ export default class GithubTabHeaderContainer extends React.Component {
7880

7981
// Workspace
8082
currentWorkDir={this.props.currentWorkDir}
83+
contextLocked={this.props.contextLocked}
8184
getCurrentWorkDirs={this.props.getCurrentWorkDirs}
85+
changeWorkingDirectory={this.props.changeWorkingDirectory}
86+
setContextLock={this.props.setContextLock}
8287

8388
// Event Handlers
84-
handleWorkDirSelect={this.props.handleWorkDirSelect}
8589
onDidChangeWorkDirs={this.props.onDidChangeWorkDirs}
8690
/>
8791
);
@@ -94,10 +98,12 @@ export default class GithubTabHeaderContainer extends React.Component {
9498

9599
// Workspace
96100
currentWorkDir={this.props.currentWorkDir}
101+
contextLocked={this.props.contextLocked}
102+
changeWorkingDirectory={this.props.changeWorkingDirectory}
103+
setContextLock={this.props.setContextLock}
97104
getCurrentWorkDirs={this.props.getCurrentWorkDirs}
98105

99106
// Event Handlers
100-
handleWorkDirSelect={this.props.handleWorkDirSelect}
101107
onDidChangeWorkDirs={this.props.onDidChangeWorkDirs}
102108
/>
103109
);

lib/controllers/git-tab-controller.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ export default class GitTabController extends React.Component {
5151
openFiles: PropTypes.func.isRequired,
5252
openInitializeDialog: PropTypes.func.isRequired,
5353
controllerRef: RefHolderPropType,
54+
contextLocked: PropTypes.bool.isRequired,
5455
changeWorkingDirectory: PropTypes.func.isRequired,
56+
setContextLock: PropTypes.func.isRequired,
5557
onDidChangeWorkDirs: PropTypes.func.isRequired,
5658
getCurrentWorkDirs: PropTypes.func.isRequired,
5759
};
@@ -122,7 +124,9 @@ export default class GitTabController extends React.Component {
122124
openFiles={this.props.openFiles}
123125
discardWorkDirChangesForPaths={this.props.discardWorkDirChangesForPaths}
124126
undoLastDiscard={this.props.undoLastDiscard}
127+
contextLocked={this.props.contextLocked}
125128
changeWorkingDirectory={this.props.changeWorkingDirectory}
129+
setContextLock={this.props.setContextLock}
126130
getCurrentWorkDirs={this.props.getCurrentWorkDirs}
127131
onDidChangeWorkDirs={this.props.onDidChangeWorkDirs}
128132

lib/controllers/git-tab-header-controller.js

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,28 @@ export default class GitTabHeaderController extends React.Component {
1111
// Workspace
1212
currentWorkDir: PropTypes.string,
1313
getCurrentWorkDirs: PropTypes.func.isRequired,
14+
changeWorkingDirectory: PropTypes.func.isRequired,
15+
contextLocked: PropTypes.bool.isRequired,
16+
setContextLock: PropTypes.func.isRequired,
1417

1518
// Event Handlers
16-
handleWorkDirSelect: PropTypes.func.isRequired,
1719
onDidChangeWorkDirs: PropTypes.func.isRequired,
1820
onDidUpdateRepo: PropTypes.func.isRequired,
1921
}
2022

2123
constructor(props) {
2224
super(props);
2325
this._isMounted = false;
24-
this.state = {currentWorkDirs: [], committer: nullAuthor};
26+
this.state = {
27+
currentWorkDirs: [],
28+
committer: nullAuthor,
29+
changingLock: null,
30+
changingWorkDir: null,
31+
};
2532
this.disposable = new CompositeDisposable();
2633
}
2734

28-
static getDerivedStateFromProps(props, state) {
35+
static getDerivedStateFromProps(props) {
2936
return {
3037
currentWorkDirs: props.getCurrentWorkDirs(),
3138
};
@@ -59,17 +66,49 @@ export default class GitTabHeaderController extends React.Component {
5966
committer={this.state.committer}
6067

6168
// Workspace
62-
workdir={this.props.currentWorkDir}
69+
workdir={this.getWorkDir()}
6370
workdirs={this.state.currentWorkDirs}
71+
contextLocked={this.getLocked()}
72+
changingWorkDir={this.state.changingWorkDir !== null}
73+
changingLock={this.state.changingLock !== null}
6474

6575
// Event Handlers
66-
handleWorkDirSelect={this.props.handleWorkDirSelect}
76+
handleWorkDirSelect={this.handleWorkDirSelect}
77+
handleLockToggle={this.handleLockToggle}
6778
/>
6879
);
6980
}
7081

82+
handleLockToggle = async () => {
83+
if (this.state.changingLock !== null) {
84+
return;
85+
}
86+
87+
const nextLock = !this.props.contextLocked;
88+
try {
89+
this.setState({changingLock: nextLock});
90+
await this.props.setContextLock(this.getWorkDir(), nextLock);
91+
} finally {
92+
await new Promise(resolve => this.setState({changingLock: null}, resolve));
93+
}
94+
}
95+
96+
handleWorkDirSelect = async e => {
97+
if (this.state.changingWorkDir !== null) {
98+
return;
99+
}
100+
101+
const nextWorkDir = e.target.value;
102+
try {
103+
this.setState({changingWorkDir: nextWorkDir});
104+
await this.props.changeWorkingDirectory(nextWorkDir);
105+
} finally {
106+
await new Promise(resolve => this.setState({changingWorkDir: null}, resolve));
107+
}
108+
}
109+
71110
resetWorkDirs = () => {
72-
this.setState((state, props) => ({
111+
this.setState(() => ({
73112
currentWorkDirs: [],
74113
}));
75114
}
@@ -81,6 +120,14 @@ export default class GitTabHeaderController extends React.Component {
81120
}
82121
}
83122

123+
getWorkDir() {
124+
return this.state.changingWorkDir !== null ? this.state.changingWorkDir : this.props.currentWorkDir;
125+
}
126+
127+
getLocked() {
128+
return this.state.changingLock !== null ? this.state.changingLock : this.props.contextLocked;
129+
}
130+
84131
componentWillUnmount() {
85132
this._isMounted = false;
86133
this.disposable.dispose();

lib/controllers/github-tab-controller.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export default class GitHubTabController extends React.Component {
2424
currentWorkDir: PropTypes.string,
2525

2626
changeWorkingDirectory: PropTypes.func.isRequired,
27+
setContextLock: PropTypes.func.isRequired,
28+
contextLocked: PropTypes.bool.isRequired,
2729
onDidChangeWorkDirs: PropTypes.func.isRequired,
2830
getCurrentWorkDirs: PropTypes.func.isRequired,
2931
openCreateDialog: PropTypes.func.isRequired,
@@ -54,6 +56,7 @@ export default class GitHubTabController extends React.Component {
5456
rootHolder={this.props.rootHolder}
5557

5658
workingDirectory={this.props.workingDirectory || this.props.currentWorkDir}
59+
contextLocked={this.props.contextLocked}
5760
repository={this.props.repository}
5861
branches={this.props.branches}
5962
currentBranch={currentBranch}
@@ -67,6 +70,7 @@ export default class GitHubTabController extends React.Component {
6770
handlePushBranch={this.handlePushBranch}
6871
handleRemoteSelect={this.handleRemoteSelect}
6972
changeWorkingDirectory={this.props.changeWorkingDirectory}
73+
setContextLock={this.props.setContextLock}
7074
getCurrentWorkDirs={this.props.getCurrentWorkDirs}
7175
onDidChangeWorkDirs={this.props.onDidChangeWorkDirs}
7276
openCreateDialog={this.props.openCreateDialog}

lib/controllers/github-tab-header-controller.js

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,26 @@ export default class GithubTabHeaderController extends React.Component {
99

1010
// Workspace
1111
currentWorkDir: PropTypes.string,
12+
contextLocked: PropTypes.bool.isRequired,
13+
changeWorkingDirectory: PropTypes.func.isRequired,
14+
setContextLock: PropTypes.func.isRequired,
1215
getCurrentWorkDirs: PropTypes.func.isRequired,
1316

1417
// Event Handlers
15-
handleWorkDirSelect: PropTypes.func.isRequired,
1618
onDidChangeWorkDirs: PropTypes.func.isRequired,
1719
}
1820

1921
constructor(props) {
2022
super(props);
21-
this.state = {currentWorkDirs: []};
23+
24+
this.state = {
25+
currentWorkDirs: [],
26+
changingLock: null,
27+
changingWorkDir: null,
28+
};
2229
}
2330

24-
static getDerivedStateFromProps(props, state) {
31+
static getDerivedStateFromProps(props) {
2532
return {
2633
currentWorkDirs: props.getCurrentWorkDirs(),
2734
};
@@ -46,21 +53,60 @@ export default class GithubTabHeaderController extends React.Component {
4653
user={this.props.user}
4754

4855
// Workspace
49-
workdir={this.props.currentWorkDir}
56+
workdir={this.getWorkDir()}
5057
workdirs={this.state.currentWorkDirs}
58+
contextLocked={this.getContextLocked()}
59+
changingWorkDir={this.state.changingWorkDir !== null}
60+
changingLock={this.state.changingLock !== null}
5161

52-
// Event Handlers
53-
handleWorkDirSelect={this.props.handleWorkDirSelect}
62+
handleWorkDirChange={this.handleWorkDirChange}
63+
handleLockToggle={this.handleLockToggle}
5464
/>
5565
);
5666
}
5767

5868
resetWorkDirs = () => {
59-
this.setState((state, props) => ({
69+
this.setState(() => ({
6070
currentWorkDirs: [],
6171
}));
6272
}
6373

74+
handleLockToggle = async () => {
75+
if (this.state.changingLock !== null) {
76+
return;
77+
}
78+
79+
const nextLock = !this.props.contextLocked;
80+
try {
81+
this.setState({changingLock: nextLock});
82+
await this.props.setContextLock(this.state.changingWorkDir || this.props.currentWorkDir, nextLock);
83+
} finally {
84+
await new Promise(resolve => this.setState({changingLock: null}, resolve));
85+
}
86+
}
87+
88+
handleWorkDirChange = async e => {
89+
if (this.state.changingWorkDir !== null) {
90+
return;
91+
}
92+
93+
const nextWorkDir = e.target.value;
94+
try {
95+
this.setState({changingWorkDir: nextWorkDir});
96+
await this.props.changeWorkingDirectory(nextWorkDir);
97+
} finally {
98+
await new Promise(resolve => this.setState({changingWorkDir: null}, resolve));
99+
}
100+
}
101+
102+
getWorkDir() {
103+
return this.state.changingWorkDir !== null ? this.state.changingWorkDir : this.props.currentWorkDir;
104+
}
105+
106+
getContextLocked() {
107+
return this.state.changingLock !== null ? this.state.changingLock : this.props.contextLocked;
108+
}
109+
64110
componentWillUnmount() {
65111
this.disposable.dispose();
66112
}

0 commit comments

Comments
 (0)