-
Notifications
You must be signed in to change notification settings - Fork 392
Fix logic for automatically opening diff views based on selection change #1311
Conversation
If there are stale pending pane items corresponding to a file that no longer exists in the changed files list, update them to reflect the new selection. If the selection in the changed file list has changed due to keyboard nav and there is a pending diff view in the active pane, update the diff view to reflect the new selection.
lib/views/staging-view.js
Outdated
} else { | ||
const panesWithStaleItemsToUpdate = this.getPanesWithStalePendingFilePatchItem(); | ||
if (panesWithStaleItemsToUpdate.length > 0) { | ||
// Staging event caused selection to change, so we need to update all old diff views to reflect new selection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not just when staging. also when deleting files and stashing
lib/views/staging-view.js
Outdated
} | ||
} | ||
} | ||
|
||
async showFilePatchItem(filePath, stagingStatus, {activate} = {activate: false}) { | ||
getPanesWithStalePendingFilePatchItem() { | ||
// "stale" meaning there is no longer a changed file associated with it due to contents being fully staged/unstaged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, not just when staging/unstaging
test/views/staging-view.test.js
Outdated
await view.selectNext(); | ||
assert.isFalse(showFilePatchItem.called); | ||
|
||
getPendingFilePatchItem.returns(true); | ||
getPanesWithStalePendingFilePatchItem.returns(['pending-file-patch-item']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have multiple array items to improve this and test the code that runs showFilePatchItem
for multiple panes
lib/views/staging-view.js
Outdated
const pendingItem = pane.getPendingItem(); | ||
if (!pendingItem) { return false; } | ||
const isDiffViewItem = pendingItem.getRealItem && pendingItem.getRealItem() instanceof FilePatchController; | ||
const isInActiveRepo = pendingItem.getWorkingDirectory() === this.props.workingDirectoryPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comment Diff views from repositories other than the active one do not count as stale. Ex: ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've found one thing that looks like a typo which should probably be changed. Other than that, I'd say the rest of this PR is ready to ✨
lib/views/staging-view.js
Outdated
this.quietlySelectItem(this.activeFilePatch.getFilePath(), this.activeFilePatch.getStagingStatus()); | ||
} else { | ||
const isRepoSame = oldProps.workingDirectoryPath === this.props.workingDirectoryPath; | ||
const selectionsPresent = previouslySelectedItems.size > 0 && currentlySelectedItems > 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨 It looks like currentlySelectedItems
is an Array. Did you mean currentlySelectedItems.length > 0
?
Also: the test suite is ✅ even though this is here. Does that mean we're missing a test case, or does it mean that the currentlySelectedItems
isn't actually needed?
const activate = pendingItem === this.props.workspace.getActivePaneItem(); | ||
await this.showFilePatchItem(selectedItem.filePath, this.selection.getActiveListKey(), {activate}); | ||
if (openNew) { | ||
// User explicitly asked to view diff, such as via click |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
I like explicitly separating the logic between "the user explicitly triggered this" and "we're inferring that this should happen."
const activePane = this.props.workspace.getCenter().getActivePane(); | ||
const activePendingItem = activePane.getPendingItem(); | ||
const activePaneHasPendingFilePatchItem = activePendingItem && activePendingItem.getRealItem && | ||
activePendingItem.getRealItem() instanceof FilePatchController; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instanceof
checks always make me feel vaguely uncomfortable. I think they raise my "OO code smell" instincts 😄
(No useful alternatives to suggest here, though; we don't have much choice when we're dealing with arbitrary PaneItems.)
const encodedFilePath = encodeURIComponent(filePath); | ||
const encodedWorkdir = encodeURIComponent(this.props.workingDirectoryPath); | ||
const filePatchItem = await this.props.workspace.open( | ||
`atom-github://file-patch/${encodedFilePath}?workdir=${encodedWorkdir}&stagingStatus=${stagingStatus}`, | ||
{pending: true, activatePane: activate, activateItem: activate}, | ||
{pending: true, activatePane: activate, activateItem: activate, pane}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it'll be good to control the Pane here.
... I still want to do that change in core to be able to specify "categories" of pending pane, so that there's only one pending pane of each category at once and we can keep ours independent from tree-view's.
test/views/staging-view.test.js
Outdated
await view.selectPrevious(); | ||
assert.isTrue(showFilePatchItem.calledTwice); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is .calledTwice
, shouldn't there be two assert.isTrue(showFilePatchItem.calledWith(...))
calls below it to assert that they're both correct? Or are the other calls too annoying to assert specifically? 🤔
Same for the next stanza there 👇
await view.selectPrevious(); | ||
await assert.async.isTrue(showFilePatchItem.calledWith(filePatches[0].filePath)); | ||
assert.isTrue(showFilePatchItem.calledThrice); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hehe. Times you get to use the word "thrice" in source code++
Nice ✨ |
Fixes #1287
Problem: We’re seeing surprised diff views popping up unexpectedly, such as in the following scenarios
Scenario 1: see steps in #1287
Scenario 2: have two repos open in project. have pending diff in pane 2 corresponding to repo 2. in pane 1 focus a file from repo 1, then focus a file from repo 2. note that new diff view opens.
Scenario 3: only have one repo. have pending diff in pane 2. focus pane 1. focus staging view (be sure not to click on a file). use arrow key to change selection (up or down). note that new diff view pops up in pane 1. The only time we want to open a brand new pending diff view in a pane is if the user explicitly expresses intent, such as by clicking the file (see 1 below).
These point to bugs in our logic for automatically opening diff views when the selection changes. We want to do this in two cases:
enter
multiple times. Or hit the “Stage File” button in a pending diff view in rapid sequence.So let’s get clear on the circumstances under which we do want a pending diff item to be opened.
In order to get this behavior right, we need to get more specific around when/what/how exactly we want to automatically show the next file.
If there are stale pending pane items corresponding to a file that no
longer exists in the changed files list, update them to reflect the new
selection.
When? The following criteria must be satisfied
What? What parts of the workspace should be affected?
How? Implementation details for updating pending items according to what is outlined above
TODO:
repro steps for bug: open diff view for repo 1 that is not the first one listed. make repo 2 active. click diff view for repo 1 and note that it changes to be first file listed.