Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find and replace integration #1922

Merged
merged 4 commits into from Jan 29, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -5,7 +5,7 @@ import {QueryRenderer, graphql} from 'react-relay';

import {autobind, PAGE_SIZE} from '../helpers';
import RelayNetworkLayerManager from '../relay-network-layer-manager';
import {GithubLoginModelPropType, ItemTypePropType, EndpointPropType} from '../prop-types';
import {GithubLoginModelPropType, ItemTypePropType, EndpointPropType, RefHolderPropType} from '../prop-types';
import {UNAUTHENTICATED, INSUFFICIENT} from '../shared/keytar-strategy';
import GithubLoginView from '../views/github-login-view';
import LoadingView from '../views/loading-view';
@@ -42,6 +42,7 @@ export default class IssueishDetailContainer extends React.Component {

// Item context
itemType: ItemTypePropType.isRequired,
refEditor: RefHolderPropType.isRequired,
}

constructor(props) {
@@ -211,6 +212,7 @@ export default class IssueishDetailContainer extends React.Component {

itemType={this.props.itemType}
destroy={this.props.destroy}
refEditor={this.props.refEditor}
/>
);
}
@@ -2,7 +2,9 @@ import React from 'react';
import {graphql, createFragmentContainer} from 'react-relay';
import PropTypes from 'prop-types';

import {BranchSetPropType, RemoteSetPropType, ItemTypePropType, EndpointPropType} from '../prop-types';
import {
BranchSetPropType, RemoteSetPropType, ItemTypePropType, EndpointPropType, RefHolderPropType,
} from '../prop-types';
import {GitError} from '../git-shell-out-strategy';
import EnableableOperation from '../models/enableable-operation';
import PullRequestDetailView, {checkoutStates} from '../views/pr-detail-view';
@@ -56,6 +58,7 @@ export class BareIssueishDetailController extends React.Component {

// Item context
itemType: ItemTypePropType.isRequired,
refEditor: RefHolderPropType.isRequired,
}

constructor(props) {
@@ -144,6 +147,7 @@ export class BareIssueishDetailController extends React.Component {

itemType={this.props.itemType}
destroy={this.props.destroy}
refEditor={this.props.refEditor}
/>
);
} else {
@@ -5,6 +5,7 @@ import {Emitter} from 'event-kit';
import {WorkdirContextPoolPropType} from '../prop-types';
import {autobind} from '../helpers';
import ChangedFileContainer from '../containers/changed-file-container';
import RefHolder from '../models/ref-holder';

export default class ChangedFileItem extends React.Component {
static propTypes = {
@@ -41,6 +42,11 @@ export default class ChangedFileItem extends React.Component {
this.emitter = new Emitter();
this.isDestroyed = false;
this.hasTerminatedPendingState = false;

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
});
}

getTitle() {
@@ -81,11 +87,17 @@ export default class ChangedFileItem extends React.Component {
itemType={this.constructor}
repository={repository}
destroy={this.destroy}
refEditor={this.refEditor}
{...this.props}
/>
);
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

serialize() {
return {
deserializer: 'FilePatchControllerStub',
@@ -27,6 +27,11 @@ export default class CommitDetailItem extends React.Component {
this.hasTerminatedPendingState = false;
this.shouldFocus = true;
this.refInitialFocus = new RefHolder();

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
});
}

terminatePendingState() {
@@ -61,6 +66,7 @@ export default class CommitDetailItem extends React.Component {
repository={repository}
{...this.props}
destroy={this.destroy}
refEditor={this.refEditor}
refInitialFocus={this.refInitialFocus}
/>
);
@@ -74,6 +80,11 @@ export default class CommitDetailItem extends React.Component {
return 'git-commit';
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

getWorkingDirectory() {
return this.props.workingDirectory;
}
@@ -29,6 +29,11 @@ export default class CommitPreviewItem extends React.Component {
this.isDestroyed = false;
this.hasTerminatedPendingState = false;
this.refInitialFocus = new RefHolder();

this.refEditor = new RefHolder();

This comment has been minimized.

Copy link
@annthurium

annthurium Jan 28, 2019

Contributor

I see what you mean about cleaning up our items so they aren't so repetitive.

this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
});
}

terminatePendingState() {
@@ -63,6 +68,7 @@ export default class CommitPreviewItem extends React.Component {
repository={repository}
{...this.props}
destroy={this.destroy}
refEditor={this.refEditor}
refInitialFocus={this.refInitialFocus}
/>
);
@@ -76,6 +82,11 @@ export default class CommitPreviewItem extends React.Component {
return 'tasklist';
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}

getWorkingDirectory() {
return this.props.workingDirectory;
}
@@ -8,6 +8,7 @@ import {addEvent} from '../reporter-proxy';
import Repository from '../models/repository';
import {getEndpoint} from '../models/endpoint';
import IssueishDetailContainer from '../containers/issueish-detail-container';
import RefHolder from '../models/ref-holder';

export default class IssueishDetailItem extends Component {
static propTypes = {
@@ -66,6 +67,11 @@ export default class IssueishDetailItem extends Component {
if (repository.isAbsent()) {
this.switchToIssueish(this.props.owner, this.props.repo, this.props.issueishNumber);
}

this.refEditor = new RefHolder();
this.refEditor.observe(editor => {
this.emitter.emit('did-change-embedded-text-editor', editor);
});
}

render() {
@@ -89,6 +95,7 @@ export default class IssueishDetailItem extends Component {

destroy={this.destroy}
itemType={this.constructor}
refEditor={this.refEditor}
/>
);
}
@@ -176,4 +183,9 @@ export default class IssueishDetailItem extends Component {
getTitle() {
return this.title;
}

observeEmbeddedTextEditor(cb) {
this.refEditor.map(editor => cb(editor));
return this.emitter.on('did-change-embedded-text-editor', cb);
}
}
@@ -61,6 +61,7 @@ export default class MultiFilePatchView extends React.Component {
toggleSymlinkChange: PropTypes.func,
undoLastDiscard: PropTypes.func,
discardRows: PropTypes.func,
refEditor: RefHolderPropType,
refInitialFocus: RefHolderPropType,
itemType: ItemTypePropType.isRequired,
}
@@ -88,6 +89,9 @@ export default class MultiFilePatchView extends React.Component {
this.subs.add(
this.refEditor.observe(editor => {
this.refEditorElement.setter(editor.getElement());
if (this.props.refEditor) {
this.props.refEditor.setter(editor);
}
}),
this.refEditorElement.observe(element => {
this.props.refInitialFocus && this.props.refInitialFocus.setter(element);
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import cx from 'classnames';
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';

import {EnableableOperationPropType, ItemTypePropType, EndpointPropType} from '../prop-types';
import {EnableableOperationPropType, ItemTypePropType, EndpointPropType, RefHolderPropType} from '../prop-types';
import {addEvent} from '../reporter-proxy';
import PeriodicRefresher from '../periodic-refresher';
import Octicon from '../atom/octicon';
@@ -99,6 +99,7 @@ export class BarePullRequestDetailView extends React.Component {

// Item context
itemType: ItemTypePropType.isRequired,
refEditor: RefHolderPropType.isRequired,
}

state = {
@@ -207,6 +208,7 @@ export class BarePullRequestDetailView extends React.Component {
config={this.props.config}

itemType={this.props.itemType}
refEditor={this.props.refEditor}
destroy={this.props.destroy}

shouldRefetch={this.state.refreshing}
@@ -173,4 +173,38 @@ describe('ChangedFileItem', function() {
assert.strictEqual(item.getWorkingDirectory(), '/dir');
assert.isTrue(item.isFilePatchItem());
});

describe('observeEmbeddedTextEditor() to interoperate with find-and-replace', function() {
let sub, editor;

beforeEach(function() {
editor = Symbol('editor');
});

afterEach(function() {
sub && sub.dispose();
});

it('calls its callback immediately if an editor is present', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);

wrapper.update().find('ChangedFileContainer').prop('refEditor').setter(editor);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);
assert.isTrue(cb.calledWith(editor));
});

it('calls its callback later if the editor changes', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('ChangedFileContainer').prop('refEditor').setter(editor);
assert.isTrue(cb.calledWith(editor));
});
});
});
@@ -187,4 +187,38 @@ describe('CommitDetailItem', function() {
assert.isFalse(focusSpy.called);
});
});

describe('observeEmbeddedTextEditor() to interoperate with find-and-replace', function() {
let sub, editor;

beforeEach(function() {
editor = Symbol('editor');
});

afterEach(function() {
sub && sub.dispose();
});

it('calls its callback immediately if an editor is present', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);

wrapper.update().find('CommitDetailContainer').prop('refEditor').setter(editor);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);
assert.isTrue(cb.calledWith(editor));
});

it('calls its callback later if the editor changes', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('CommitDetailContainer').prop('refEditor').setter(editor);
assert.isTrue(cb.calledWith(editor));
});
});
});
@@ -173,4 +173,38 @@ describe('CommitPreviewItem', function() {
item.focus();
});
});

describe('observeEmbeddedTextEditor() to interoperate with find-and-replace', function() {
let sub, editor;

beforeEach(function() {
editor = Symbol('editor');
});

afterEach(function() {
sub && sub.dispose();
});

it('calls its callback immediately if an editor is present', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);

wrapper.update().find('CommitPreviewContainer').prop('refEditor').setter(editor);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);
assert.isTrue(cb.calledWith(editor));
});

it('calls its callback later if the editor changes', async function() {
const wrapper = mount(buildPaneApp());
const item = await open(wrapper);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('CommitPreviewContainer').prop('refEditor').setter(editor);
assert.isTrue(cb.calledWith(editor));
});
});
});
@@ -227,4 +227,39 @@ describe('IssueishDetailItem', function() {
item.terminatePendingState();
assert.strictEqual(handler.callCount, 1);
});

describe('observeEmbeddedTextEditor() to interoperate with find-and-replace', function() {
let sub, uri, editor;

beforeEach(function() {
editor = Symbol('editor');
uri = IssueishDetailItem.buildURI('one.com', 'me', 'code', 400, __dirname);
});

afterEach(function() {
sub && sub.dispose();
});

it('calls its callback immediately if an editor is present', async function() {
const wrapper = mount(buildApp());
const item = await atomEnv.workspace.open(uri);

wrapper.update().find('IssueishDetailContainer').prop('refEditor').setter(editor);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);
assert.isTrue(cb.calledWith(editor));
});

it('calls its callback later if the editor changes', async function() {
const wrapper = mount(buildApp());
const item = await atomEnv.workspace.open(uri);

const cb = sinon.spy();
sub = item.observeEmbeddedTextEditor(cb);

wrapper.update().find('IssueishDetailContainer').prop('refEditor').setter(editor);
assert.isTrue(cb.calledWith(editor));
});
});
});
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.