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

Move "Undo Discard" button behind context menu #1702

Merged
merged 21 commits into from
Oct 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0d73036
Move undo discard button to header
kuychaco Sep 24, 2018
b82e732
Hide "Undo discard" text for narrow width. Add tooltip
kuychaco Sep 24, 2018
0f1b6f5
Ask to confirm undo discard if head has moved since discard
kuychaco Nov 15, 2017
0b834a0
Revert "Ask to confirm undo discard if head has moved since discard"
kuychaco Sep 25, 2018
dee888e
Revert "Hide "Undo discard" text for narrow width. Add tooltip"
kuychaco Sep 25, 2018
ddb7c46
Revert "Move undo discard button to header"
kuychaco Sep 25, 2018
71abb97
:fire: "Undo Discard" btn and move to actions menu in header
kuychaco Sep 24, 2018
9baccc1
Extract `getSelectedItemFilePaths` method
kuychaco Sep 25, 2018
36f51ed
`Discard Selected Files` -> `Discard Changes in Selected File`, plura…
kuychaco Sep 25, 2018
7505f9b
Use <button> element for showActionsMenu icon
simurai Sep 26, 2018
46c8240
Disable discard/undo context menu items when appropriate
kuychaco Oct 3, 2018
dca63d6
Drop context menu items on StagingView headers
kuychaco Oct 3, 2018
08900af
Make Stage/Unstage All buttons always visible. Disable when no changes
kuychaco Oct 3, 2018
8336eee
Add "Discard All Changes" to kebab menu
kuychaco Oct 3, 2018
22ec1fe
Instrument discard/undo discard actions in StagingView
kuychaco Oct 3, 2018
636ccf0
Instrument discard/undo discard actions in FilePatchController
kuychaco Oct 3, 2018
8cba2f8
Add StagingView tests for event recording for discarding/undoing disc…
kuychaco Oct 3, 2018
3fabe7c
Add FilePatchController event recording tests for discard/undo discard
kuychaco Oct 3, 2018
7f03c66
Micro-optimization getting selected item count
kuychaco Oct 4, 2018
32b0ada
Add eventSource metadata to `undo-last-discard` event reporting
kuychaco Oct 5, 2018
f759c78
Add eventSource metadata to `discard-unstaged-changes` event recording
kuychaco Oct 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions lib/controllers/file-patch-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Switchboard from '../switchboard';
import FilePatchView from '../views/file-patch-view';
import ModelObserver from '../models/model-observer';
import {autobind} from '../helpers';
import {addEvent} from '../reporter-proxy';

export default class FilePatchController extends React.Component {
static propTypes = {
Expand Down Expand Up @@ -529,11 +530,22 @@ export default class FilePatchController extends React.Component {
return textEditor;
}

discardLines(lines) {
discardLines(lines, {eventSource} = {}) {
addEvent('discard-unstaged-changes', {
package: 'github',
component: 'FilePatchController',
lineCount: lines.length,
eventSource,
});
return this.props.discardLines(this.state.filePatch, lines, this.repositoryObserver.getActiveModel());
}

undoLastDiscard() {
undoLastDiscard({eventSource} = {}) {
addEvent('undo-last-discard', {
package: 'github',
component: 'FilePatchController',
eventSource,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yess metrics

return this.props.undoLastDiscard(this.props.filePath, this.repositoryObserver.getActiveModel());
}

Expand Down
40 changes: 32 additions & 8 deletions lib/views/file-patch-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,10 @@ export default class FilePatchView extends React.Component {
command="github:view-corresponding-diff"
callback={() => this.props.isPartiallyStaged && this.props.didDiveIntoCorrespondingFilePatch()}
/>
<Command command="github:discard-selected-lines" callback={this.discardSelection} />
<Command command="github:discard-selected-lines" callback={this.discardSelectionFromCommand} />
<Command
command="core:undo"
callback={() => this.props.hasUndoHistory && this.props.undoLastDiscard()}
callback={this.undoLastDiscardFromCoreUndo}
/>
{this.props.executableModeChange &&
<Command
Expand All @@ -282,14 +282,38 @@ export default class FilePatchView extends React.Component {
<Commands registry={this.props.commandRegistry} target="atom-workspace">
<Command
command="github:undo-last-discard-in-diff-view"
callback={() => this.props.hasUndoHistory && this.props.undoLastDiscard()}
callback={this.undoLastDiscardFromCommand}
/>
<Command command="github:focus-diff-view" callback={this.focus} />
</Commands>
</div>
);
}

undoLastDiscardFromCommand = () => {
if (this.props.hasUndoHistory) {
this.props.undoLastDiscard({eventSource: {command: 'github:undo-last-discard-in-diff-view'}});
}
}

undoLastDiscardFromCoreUndo = () => {
if (this.props.hasUndoHistory) {
this.props.undoLastDiscard({eventSource: {command: 'core:undo'}});
}
}

undoLastDiscardFromButton = () => {
this.props.undoLastDiscard({eventSource: 'button'});
}

undoLastDiscardFromButton = () => {
this.props.undoLastDiscard({eventSource: 'button'});
}

discardSelectionFromCommand = () => {
this.discardSelection({eventSource: {command: 'github:discard-selected-lines'}});
}

renderButtonGroup() {
const unstaged = this.props.stagingStatus === 'unstaged';

Expand All @@ -298,7 +322,7 @@ export default class FilePatchView extends React.Component {
{this.props.hasUndoHistory && unstaged ? (
<button
className="btn icon icon-history"
onClick={this.props.undoLastDiscard}>
onClick={this.undoLastDiscardFromButton}>
Undo Discard
</button>
) : null}
Expand Down Expand Up @@ -659,10 +683,10 @@ export default class FilePatchView extends React.Component {

didClickDiscardButtonForHunk(hunk) {
if (this.state.selection.getSelectedHunks().has(hunk)) {
this.discardSelection();
this.discardSelection({eventSource: 'button'});
} else {
this.setState(prevState => ({selection: prevState.selection.selectHunk(hunk)}), () => {
this.discardSelection();
this.discardSelection({eventSource: 'button'});
});
}
}
Expand Down Expand Up @@ -710,9 +734,9 @@ export default class FilePatchView extends React.Component {
this.props.attemptSymlinkStageOperation();
}

discardSelection() {
discardSelection({eventSource} = {}) {
const selectedLines = this.state.selection.getSelectedLines();
return selectedLines.size ? this.props.discardLines(selectedLines) : null;
return selectedLines.size ? this.props.discardLines(selectedLines, {eventSource}) : null;
}

goToDiffLine(lineNumber) {
Expand Down
138 changes: 110 additions & 28 deletions lib/views/staging-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import RefHolder from '../models/ref-holder';
import FilePatchController from '../controllers/file-patch-controller';
import Commands, {Command} from '../atom/commands';
import {autobind} from '../helpers';
import {addEvent} from '../reporter-proxy';

const debounce = (fn, wait) => {
let timeout;
Expand Down Expand Up @@ -82,9 +83,8 @@ export default class StagingView extends React.Component {
'dblclickOnItem', 'contextMenuOnItem', 'mousedownOnItem', 'mousemoveOnItem', 'mouseup', 'registerItemElement',
'renderBody', 'openFile', 'discardChanges', 'activateNextList', 'activatePreviousList', 'activateLastList',
'stageAll', 'unstageAll', 'stageAllMergeConflicts', 'discardAll', 'confirmSelectedItems', 'selectAll',
'selectFirst', 'selectLast', 'diveIntoSelection', 'showDiffView', 'showBulkResolveMenu',
'selectFirst', 'selectLast', 'diveIntoSelection', 'showDiffView', 'showBulkResolveMenu', 'showActionsMenu',
'resolveCurrentAsOurs', 'resolveCurrentAsTheirs', 'quietlySelectItem', 'didChangeSelectedItems',
'undoLastDiscard',
);

this.subs = new CompositeDisposable(
Expand Down Expand Up @@ -194,9 +194,12 @@ export default class StagingView extends React.Component {
<header className="github-StagingView-header">
<span className="icon icon-list-unordered" />
<span className="github-StagingView-title">Unstaged Changes</span>
{this.props.unstagedChanges.length ? this.renderStageAllButton() : null}
{this.renderActionsMenu()}
<button
className="github-StagingView-headerButton icon icon-move-down"
disabled={this.props.unstagedChanges.length === 0}
onClick={this.stageAll}>Stage All</button>
</header>
{this.props.hasUndoHistory ? this.renderUndoButton() : null}
<div className="github-StagingView-list github-FilePatchListView github-StagingView-unstaged">
{
this.state.unstagedChanges.map(filePatch => (
Expand All @@ -222,7 +225,9 @@ export default class StagingView extends React.Component {
<span className="github-StagingView-title">
Staged Changes
</span>
{ this.props.stagedChanges.length ? this.renderUnstageAllButton() : null }
<button className="github-StagingView-headerButton icon icon-move-up"
disabled={this.props.stagedChanges.length === 0}
onClick={this.unstageAll}>Unstage All</button>
</header>
<div className="github-StagingView-list github-FilePatchListView github-StagingView-staged">
{
Expand Down Expand Up @@ -267,38 +272,62 @@ export default class StagingView extends React.Component {
<Command command="github:open-file" callback={this.openFile} />
<Command command="github:resolve-file-as-ours" callback={this.resolveCurrentAsOurs} />
<Command command="github:resolve-file-as-theirs" callback={this.resolveCurrentAsTheirs} />
<Command command="github:discard-changes-in-selected-files" callback={this.discardChanges} />
<Command command="core:undo" callback={this.undoLastDiscard} />
<Command command="github:discard-changes-in-selected-files" callback={this.discardChangesFromCommand} />
<Command command="core:undo" callback={this.undoLastDiscardFromCoreUndo} />
</Commands>
<Commands registry={this.props.commandRegistry} target="atom-workspace">
<Command command="github:stage-all-changes" callback={this.stageAll} />
<Command command="github:unstage-all-changes" callback={this.unstageAll} />
<Command command="github:discard-all-changes" callback={this.discardAll} />
<Command command="github:undo-last-discard-in-git-tab" callback={this.undoLastDiscard} />
<Command command="github:discard-all-changes" callback={this.discardAllFromCommand} />
<Command command="github:undo-last-discard-in-git-tab"
callback={this.undoLastDiscardFromCommand}
/>
</Commands>
</Fragment>
);
}

renderStageAllButton() {
return (
<button
className="github-StagingView-headerButton icon icon-move-down"
onClick={this.stageAll}>Stage All</button>
);
undoLastDiscardFromCoreUndo = () => {
this.undoLastDiscard({eventSource: {command: 'core:undo'}});
}

renderUnstageAllButton() {
return (
<button className="github-StagingView-headerButton icon icon-move-up"
onClick={this.unstageAll}>Unstage All</button>
);
undoLastDiscardFromCommand = () => {
this.undoLastDiscard({eventSource: {command: 'github:undo-last-discard-in-git-tab'}});
}

undoLastDiscardFromButton = () => {
this.undoLastDiscard({eventSource: 'button'});
}

undoLastDiscardFromHeaderMenu = () => {
this.undoLastDiscard({eventSource: 'header-menu'});
}

discardChangesFromCommand = () => {
this.discardChanges({eventSource: {command: 'github:discard-changes-in-selected-files'}});
}

discardAllFromCommand = () => {
this.discardAll({eventSource: {command: 'github:discard-all-changes'}});
}

renderActionsMenu() {
if (this.props.unstagedChanges.length || this.props.hasUndoHistory) {
return (
<button
className="github-StagingView-headerButton github-StagingView-headerButton--iconOnly icon icon-ellipses"
onClick={this.showActionsMenu}
/>
);
} else {
return null;
}
}

renderUndoButton() {
return (
<button className="github-StagingView-headerButton github-StagingView-headerButton--fullWidth icon icon-history"
onClick={this.undoLastDiscard}>Undo Discard</button>
onClick={this.undoLastDiscardFromButton}>Undo Discard</button>
);
}

Expand Down Expand Up @@ -377,20 +406,31 @@ export default class StagingView extends React.Component {
this.subs.dispose();
}

getSelectedItemFilePaths() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for refactoring this out.

return Array.from(this.state.selection.getSelectedItems(), item => item.filePath);
}

getSelectedConflictPaths() {
if (this.state.selection.getActiveListKey() !== 'conflicts') {
return [];
}
return Array.from(this.state.selection.getSelectedItems(), item => item.filePath);
return this.getSelectedItemFilePaths();
}

openFile() {
const filePaths = Array.from(this.state.selection.getSelectedItems(), item => item.filePath);
const filePaths = this.getSelectedItemFilePaths();
return this.props.openFiles(filePaths);
}

discardChanges() {
const filePaths = Array.from(this.state.selection.getSelectedItems(), item => item.filePath);
discardChanges({eventSource} = {}) {
const filePaths = this.getSelectedItemFilePaths();
addEvent('discard-unstaged-changes', {
package: 'github',
component: 'StagingView',
fileCount: filePaths.length,
type: 'selected',
eventSource,
});
return this.props.discardWorkDirChangesForPaths(filePaths);
}

Expand Down Expand Up @@ -457,14 +497,21 @@ export default class StagingView extends React.Component {
return this.props.attemptFileStageOperation(filePaths, 'unstaged');
}

discardAll() {
discardAll({eventSource} = {}) {
if (this.props.unstagedChanges.length === 0) { return null; }
const filePaths = this.props.unstagedChanges.map(filePatch => filePatch.filePath);
addEvent('discard-unstaged-changes', {
package: 'github',
component: 'StagingView',
fileCount: filePaths.length,
type: 'all',
eventSource,
});
return this.props.discardWorkDirChangesForPaths(filePaths);
}

confirmSelectedItems = async () => {
const itemPaths = Array.from(this.state.selection.getSelectedItems(), item => item.filePath);
const itemPaths = this.getSelectedItemFilePaths();
await this.props.attemptFileStageOperation(itemPaths, this.state.selection.getActiveListKey());
await new Promise(resolve => {
this.setState(prevState => ({selection: prevState.selection.coalesce()}), resolve);
Expand Down Expand Up @@ -586,6 +633,35 @@ export default class StagingView extends React.Component {
menu.popup(remote.getCurrentWindow());
}

showActionsMenu(event) {
event.preventDefault();

const menu = new Menu();

const selectedItemCount = this.state.selection.getSelectedItems().size;
const pluralization = selectedItemCount > 1 ? 's' : '';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we ever i18n our package, all our hard coded pluralization is going to be fun to convert....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yuuuup 😕


menu.append(new MenuItem({
label: 'Discard All Changes',
click: () => this.discardAll({eventSource: 'header-menu'}),
enabled: this.props.unstagedChanges.length > 0,
}));

menu.append(new MenuItem({
label: 'Discard Changes in Selected File' + pluralization,
click: () => this.discardChanges({eventSource: 'header-menu'}),
enabled: !!(this.props.unstagedChanges.length && selectedItemCount),
}));

menu.append(new MenuItem({
label: 'Undo Last Discard',
click: () => this.undoLastDiscard({eventSource: 'header-menu'}),
enabled: this.props.hasUndoHistory,
}));

menu.popup(remote.getCurrentWindow());
}

resolveCurrentAsOurs() {
this.props.resolveAsOurs(this.getSelectedConflictPaths());
}
Expand Down Expand Up @@ -792,11 +868,17 @@ export default class StagingView extends React.Component {
}
}

undoLastDiscard() {
undoLastDiscard({eventSource} = {}) {
if (!this.props.hasUndoHistory) {
return;
}

addEvent('undo-last-discard', {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above - would recommend refactoring this so that you're logging menu views as a ui interaction.

package: 'github',
component: 'StagingView',
eventSource,
});

this.props.undoLastDiscard();
}

Expand Down
19 changes: 0 additions & 19 deletions menus/git.cson
Original file line number Diff line number Diff line change
Expand Up @@ -77,25 +77,6 @@
'command': 'github:open-link-in-browser'
}
]
'.github-UnstagedChanges .github-StagingView-header': [
{
'label': 'Stage All Changes'
'command': 'github:stage-all-changes'
}
{
'type': 'separator'
}
{
'label': 'Discard All Changes'
'command': 'github:discard-all-changes'
}
]
'.github-StagedChanges .github-StagingView-header': [
{
'label': 'Unstage All Changes'
'command': 'github:unstage-all-changes'
}
]
'.github-CommitView': [
{
'type': 'separator'
Expand Down
4 changes: 4 additions & 0 deletions styles/staging-view.less
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
border-left: none;
border-bottom: 1px solid @panel-heading-border-color;
}

&--iconOnly:before {
width: auto;
}
}


Expand Down
Loading