This repository was archived by the owner on Dec 15, 2022. It is now read-only.
Repository navigation
Rework PaneItem management #1414
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
dfd2c12
Move <PaneItem> to a new lib/atom/ directory
smashwilson b911ef0
URI pattern matching
smashwilson 4678cc9
Okay I went a little overboard on URI matching
smashwilson 4281d28
Avoid passing other arguments to asPart
smashwilson f4a2713
Manage open pane items
smashwilson 0cd460b
Pass matched parameters to the render prop
smashwilson 84abd5c
Remember the full matched URI
smashwilson 6027264
URI-decode matched parameters
smashwilson 7b53bed
Accept a URI in createItem()
smashwilson fd4b26b
Move URI pattern and construction to statics
smashwilson 7c69a21
Reorganize RootController's render method
smashwilson 133d7d6
Use the new PaneItem for FilePatchControllers
smashwilson f17cc9f
Hydrate stubs already present in the workspace at launch
smashwilson d8f8b47
Turns out openers are only kind of asynchronous
smashwilson 244d18d
Lowercase
smashwilson f8311df
Remove old FilePatch opener
smashwilson 4102a94
Render item portals within Fragments with keys
smashwilson 6da403f
Use FilePatchController to build URI
smashwilson 5ad31b0
FilePatchControllers are not managed that way
smashwilson 50a7672
workdir is URI-encoded
smashwilson f3b666d
That should be a non-default import
smashwilson d2019f5
Convert IssueishPaneItem to use the PaneItem component
smashwilson 24720e4
Convert GitTimingsView
smashwilson 6e62a03
These tests are subsumed by the PaneItem
smashwilson 249b8ea
Merge branch 'master' into aw/pane-item-pain
smashwilson 341a2c2
Document the PaneItem and URIPattern
smashwilson 70b3085
Merge branch 'master' into aw/pane-item-pain
smashwilson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| import React, {Fragment} from 'react'; | ||
| import ReactDOM from 'react-dom'; | ||
| import PropTypes from 'prop-types'; | ||
| import {CompositeDisposable} from 'event-kit'; | ||
|
|
||
| import URIPattern, {nonURIMatch} from './uri-pattern'; | ||
| import RefHolder from '../models/ref-holder'; | ||
| import {createItem} from '../helpers'; | ||
|
|
||
| /** | ||
| * PaneItem registers an opener with the current Atom workspace as long as this component is mounted. The opener will | ||
| * trigger on URIs that match a specified pattern and render a subtree returned by a render prop. | ||
| * | ||
| * The render prop can receive three arguments: | ||
| * | ||
| * * itemHolder: A RefHolder. If used as the target for a ref, the referenced component will be used as the "item" of | ||
| * the pane item - its `getTitle()`, `getIconName()`, and other methods will be used by the pane. | ||
| * * params: An object containing the named parameters captured by the URI pattern. | ||
| * * uri: The exact, matched URI used to launch this item. | ||
| * | ||
| * render() { | ||
| * return ( | ||
| * <PaneItem workspace={this.props.workspace} uriPattern='atom-github://host/{id}'> | ||
| * {({itemHolder, params}) => ( | ||
| * <ItemComponent ref={itemHolder.setter} id={params.id} /> | ||
| * )} | ||
| * </PaneItem> | ||
| * ); | ||
| * } | ||
| */ | ||
| export default class PaneItem extends React.Component { | ||
| static propTypes = { | ||
| workspace: PropTypes.object.isRequired, | ||
| children: PropTypes.func.isRequired, | ||
| uriPattern: PropTypes.string.isRequired, | ||
| } | ||
|
|
||
| constructor(props) { | ||
| super(props); | ||
|
|
||
| const uriPattern = new URIPattern(this.props.uriPattern); | ||
| const currentlyOpen = this.props.workspace.getPaneItems() | ||
| .map(item => { | ||
| const element = item.getElement ? item.getElement() : null; | ||
| const match = item.getURI ? uriPattern.matches(item.getURI()) : nonURIMatch; | ||
| const stub = item.setRealItem ? item : null; | ||
| return {element, match, stub}; | ||
| }) | ||
| .filter(each => each.element && each.match.ok()) | ||
| .map(each => new OpenItem(each.match, each.element, each.stub)); | ||
|
|
||
| this.subs = new CompositeDisposable(); | ||
| this.state = {uriPattern, currentlyOpen}; | ||
| } | ||
|
|
||
| static getDerivedStateFromProps(nextProps, prevState) { | ||
| if (prevState.uriPattern.getOriginal() === nextProps.uriPattern) { | ||
| return null; | ||
| } | ||
|
|
||
| return { | ||
| uriPattern: new URIPattern(nextProps.uriPattern), | ||
| }; | ||
| } | ||
|
|
||
| componentDidMount() { | ||
| this.subs.add(this.props.workspace.addOpener(this.opener)); | ||
|
|
||
| for (const openItem of this.state.currentlyOpen) { | ||
| openItem.hydrateStub(); | ||
| } | ||
| } | ||
|
|
||
| render() { | ||
| return this.state.currentlyOpen.map(item => { | ||
| return ( | ||
| <Fragment key={item.getURI()}> | ||
| {item.renderPortal(this.props.children)} | ||
| </Fragment> | ||
| ); | ||
| }); | ||
| } | ||
|
|
||
| componentWillUnmount() { | ||
| this.subs.dispose(); | ||
| } | ||
|
|
||
| opener = uri => { | ||
| const m = this.state.uriPattern.matches(uri); | ||
| if (!m.ok()) { | ||
| return undefined; | ||
| } | ||
|
|
||
| const openItem = new OpenItem(m); | ||
|
|
||
| return new Promise(resolve => { | ||
| this.setState(prevState => ({ | ||
| currentlyOpen: [...prevState.currentlyOpen, openItem], | ||
| }), () => { | ||
| 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), | ||
| })); | ||
| } | ||
| }), | ||
| ); | ||
|
|
||
| resolve(paneItem); | ||
| }); | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * A subtree rendered through a portal onto a detached DOM node for use as the root as a PaneItem. | ||
| */ | ||
| class OpenItem { | ||
| constructor(match, element = null, stub = null) { | ||
| this.domNode = element || document.createElement('div'); | ||
| this.stubItem = stub; | ||
| this.match = match; | ||
| this.itemHolder = new RefHolder(); | ||
| } | ||
|
|
||
| getURI() { | ||
| return this.match.getURI(); | ||
| } | ||
|
|
||
| create() { | ||
| const h = this.itemHolder.isEmpty() ? null : this.itemHolder; | ||
| return createItem(this.domNode, h, this.match.getURI()); | ||
| } | ||
|
|
||
| hydrateStub() { | ||
| if (this.stubItem) { | ||
| this.stubItem.setRealItem(this.create()); | ||
| this.stubItem = null; | ||
| } | ||
| } | ||
|
|
||
| renderPortal(renderProp) { | ||
| return ReactDOM.createPortal( | ||
| renderProp({ | ||
| itemHolder: this.itemHolder, | ||
| params: this.match.getParams(), | ||
| uri: this.match.getURI(), | ||
| }), | ||
| this.domNode, | ||
| ); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
👍👍