Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
13d7e00
Port the FilePatch and MergeConflict list item views to React
smashwilson Apr 27, 2018
f582509
StagingView :rocket: React
smashwilson Apr 27, 2018
ae3089b
StagingView tests are all green
smashwilson Apr 27, 2018
282e768
:fire: EtchWrapper
smashwilson Apr 27, 2018
c6bcdd3
Blam
smashwilson Apr 27, 2018
6e1ac3c
Now with less logging
smashwilson Apr 30, 2018
85140e1
mergeConflicts prop is an array of MergeConflictItemPropType
smashwilson Apr 30, 2018
8c4dc6c
Pass an absent Repository to the app
smashwilson Apr 30, 2018
56ca1ae
Resolve the nextUpdatePromise regardless of actual changes
smashwilson Apr 30, 2018
6ce355e
Awaiting those Promises was redundant to the assert.asyncs
smashwilson Apr 30, 2018
f355dd2
Ah we do have to await that promise
smashwilson Apr 30, 2018
97ced87
Merge branch 'master' into aw/the-final-react
smashwilson Apr 30, 2018
f86a3c9
:fire: unused ListView
smashwilson Apr 30, 2018
fd8a24a
:fire: unused DebuggerView
smashwilson Apr 30, 2018
e978fd2
:hocho: comment referencing etch
smashwilson Apr 30, 2018
02b5ab3
Remove etch dependency
smashwilson Apr 30, 2018
a1b9521
:fire: .only()
smashwilson Apr 30, 2018
f611a8c
Turns out that style attribute wasn't being applied before
smashwilson Apr 30, 2018
09bf65c
Persist synthetic events that we need to access asynchronously
smashwilson Apr 30, 2018
b21c7e4
workingDirectoryPath is null for absent repositories
smashwilson Apr 30, 2018
e397682
Avoid binding a truthy argument to selectPrevious and selectNext
smashwilson Apr 30, 2018
47a09bf
Remove an unused variable
smashwilson Apr 30, 2018
1e031d3
Manually trigger debouncedDidChangeSelectedItem on click
smashwilson Apr 30, 2018
6ecf866
Stub a persist() method on fake events
smashwilson Apr 30, 2018
4a264b6
Only trigger didChangeSelectedItem in mouseUp for mouse selections
smashwilson Apr 30, 2018
1b2506e
Register closeListeners for hydrated stub items
smashwilson Apr 30, 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
4 changes: 0 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ Feel free to [open an issue](https://github.com/atom/github/issues) if you want

## Technical Contribution Tips

### React and Etch

Early in the project's life, we used [Etch](https://github.com/atom/etch) to manage DOM updates via a virtual-DOM mechanism very similar to React. Eventually we migrated to using [React](https://facebook.github.io/react/) itself. During the transition, we implemented a React component called `EtchWrapper` to allow us to render Etch components from within React; however, all new UI work should be done using React, and we are working to migrate all existing UI components to fully use React.

### Updating the GraphQL Schema

This project uses [Relay](https://github.com/facebook/relay) for its GitHub integration. There's a source-level transform that depends on having a local copy of the GraphQL schema available. If you need to update the local schema to the latest version, run
Expand Down
26 changes: 15 additions & 11 deletions lib/atom/pane-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ export default class PaneItem extends React.Component {
}

componentDidMount() {
this.subs.add(this.props.workspace.addOpener(this.opener));

for (const openItem of this.state.currentlyOpen) {
this.subs.add(this.closeListener(openItem.stubItem, openItem));

openItem.hydrateStub();
}

this.subs.add(this.props.workspace.addOpener(this.opener));
}

render() {
Expand Down Expand Up @@ -99,20 +101,22 @@ export default class PaneItem extends React.Component {
}), () => {
const paneItem = openItem.create();

this.subs.add(
this.props.workspace.onDidDestroyPaneItem(({item}) => {
if (item === paneItem) {
this.setState(prevState => ({
currentlyOpen: prevState.currentlyOpen.filter(each => each !== openItem),
}));
}
}),
);
this.subs.add(this.closeListener(paneItem, openItem));

resolve(paneItem);
});
});
}

closeListener(paneItem, openItem) {
return this.props.workspace.onDidDestroyPaneItem(({item}) => {
if (item === paneItem) {
this.setState(prevState => ({
currentlyOpen: prevState.currentlyOpen.filter(each => each !== openItem),
}));
}
});
}
}

/**
Expand Down
1 change: 0 additions & 1 deletion lib/controllers/file-patch-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ export default class FilePatchController extends React.Component {
</div>
);
} else {
// NOTE: Outer div is required for etch to render elements correctly
const hasUndoHistory = repository ? this.hasUndoHistory() : false;
return (
<div className="github-PaneView pane-item">
Expand Down
2 changes: 1 addition & 1 deletion lib/controllers/git-tab-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export default class GitTabController extends React.Component {

this.stagingOperationInProgress = true;

const fileListUpdatePromise = this.refView.refStagingView.getWrappedComponent().getNextListUpdatePromise();
const fileListUpdatePromise = this.refView.refStagingView.getNextListUpdatePromise();
let stageOperationPromise;
if (stageStatus === 'staged') {
stageOperationPromise = this.unstageFiles(filePaths);
Expand Down
4 changes: 0 additions & 4 deletions lib/controllers/root-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,6 @@ class TabTracker {
getControllerComponent() {
const controller = this.getController();

if (controller.getWrappedComponentInstance) {
return controller.getWrappedComponentInstance();
}

if (controller.getWrappedComponent) {
return controller.getWrappedComponent();
}
Expand Down
5 changes: 1 addition & 4 deletions lib/models/composite-list-selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@ export default class CompositeListSelection {
updated = next !== updated ? next : updated.activatePreviousSelection();
}

if (isDifferent) {
updated.resolveNextUpdatePromise();
}

updated.resolveNextUpdatePromise();
return updated;
}

Expand Down
22 changes: 22 additions & 0 deletions lib/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,25 @@ export const RefHolderPropType = PropTypes.shape({
setter: PropTypes.func.isRequired,
observe: PropTypes.func.isRequired,
});

export const FilePatchItemPropType = PropTypes.shape({
filePath: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
});

const statusNames = [
'added',
'deleted',
'modified',
'typechange',
'equivalent',
];

export const MergeConflictItemPropType = PropTypes.shape({
filePath: PropTypes.string.isRequired,
status: PropTypes.shape({
file: PropTypes.oneOf(statusNames).isRequired,
ours: PropTypes.oneOf(statusNames).isRequired,
theirs: PropTypes.oneOf(statusNames).isRequired,
}).isRequired,
});
42 changes: 0 additions & 42 deletions lib/views/debugger-view.js

This file was deleted.

128 changes: 0 additions & 128 deletions lib/views/etch-wrapper.js

This file was deleted.

40 changes: 27 additions & 13 deletions lib/views/file-patch-list-item-view.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,46 @@
/** @jsx etch.dom */
/* eslint react/no-unknown-property: "off" */
import React from 'react';
import PropTypes from 'prop-types';
import {CompositeDisposable} from 'event-kit';

import etch from 'etch';
import {FilePatchItemPropType} from '../prop-types';
import {classNameForStatus} from '../helpers';
import RefHolder from '../models/ref-holder';

export default class FilePatchListItemView {
constructor(props) {
this.props = props;
etch.initialize(this);
this.props.registerItemElement(this.props.filePatch, this.element);
export default class FilePatchListItemView extends React.Component {
static propTypes = {
filePatch: FilePatchItemPropType.isRequired,
selected: PropTypes.bool.isRequired,
registerItemElement: PropTypes.func,
}

static defaultProps = {
registerItemElement: () => {},
}

update(props) {
this.props = props;
this.props.registerItemElement(this.props.filePatch, this.element);
return etch.update(this);
constructor(props) {
super(props);

this.refItem = new RefHolder();
this.subs = new CompositeDisposable(
this.refItem.observe(item => this.props.registerItemElement(this.props.filePatch, item)),
);
}

render() {
const {filePatch, selected, ...others} = this.props;
delete others.registerItemElement;
const status = classNameForStatus[filePatch.status];
const className = selected ? 'is-selected' : '';

return (
<div {...others} className={`github-FilePatchListView-item is-${status} ${className}`}>
<div ref={this.refItem.setter} {...others} className={`github-FilePatchListView-item is-${status} ${className}`}>
<span className={`github-FilePatchListView-icon icon icon-diff-${status} status-${status}`} />
<span className="github-FilePatchListView-path">{filePatch.filePath}</span>
</div>
);
}

componentWillUnmount() {
this.subs.dispose();
}
}
Loading