-
Notifications
You must be signed in to change notification settings - Fork 140
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
Focus on expanded editor #1086
base: master
Are you sure you want to change the base?
Focus on expanded editor #1086
Changes from 33 commits
8bb5b1e
57acd97
49adda4
a75a68e
95be55b
17d376f
8c82569
1b9ea4d
dcf0d5b
71e7453
f139ff0
f35b419
a7727fd
8e5d1aa
b7e917d
5b570dd
016ed36
9708c5e
0bf16b6
cbc1847
c86dc08
08aaf85
11e6aaf
98bc1ac
7cc3bdf
d14d894
2fe7483
6e92d65
22760ab
af3efd5
4b310e9
cdfd758
20bfc52
1129545
a3d519b
848ef59
30369fe
4f05a4b
23315cb
c447995
ab67c9c
f1fdd7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,7 +106,8 @@ function buildGistFromProject(project) { | |
language: 'Markdown', | ||
}; | ||
} | ||
if (project.enabledLibraries.length || project.hiddenUIComponents.length) { | ||
if (project.enabledLibraries.length || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the change to |
||
!isEmpty(project.hiddenUIComponents)) { | ||
files['popcode.json'] = { | ||
content: createPopcodeJson(project), | ||
language: 'JSON', | ||
|
@@ -137,7 +138,7 @@ function createPopcodeJson(project) { | |
if (project.enabledLibraries.length) { | ||
json.enabledLibraries = project.enabledLibraries; | ||
} | ||
if (project.hiddenUIComponents.length) { | ||
if (!isEmpty(project.hiddenUIComponents)) { | ||
json.hiddenUIComponents = project.hiddenUIComponents; | ||
} | ||
return JSON.stringify(json); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,13 +58,15 @@ class Editor extends React.Component { | |
} | ||
|
||
componentWillUnmount() { | ||
const {onComponentHidden, language} = this.props; | ||
const {row, column} = this._editor.getCursorPosition(); | ||
onComponentHidden(language, row, column); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if there is a better place for this action to be called, I would have ideally liked to call it from |
||
this._editor.destroy(); | ||
window.removeEventListener('resize', this._handleWindowResize); | ||
} | ||
|
||
_focusRequestedLine(requestedFocusedLine) { | ||
if (get(requestedFocusedLine, 'component') !== | ||
`editor.${this.props.language}`) { | ||
if (get(requestedFocusedLine, 'componentKey') !== this.props.language) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it doesn't feel 100% right here to use language as the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it seems like the structure of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (The same observation would of course apply here as well.) |
||
return; | ||
} | ||
|
||
|
@@ -141,6 +143,7 @@ Editor.propTypes = { | |
requestedFocusedLine: PropTypes.object, | ||
source: PropTypes.string.isRequired, | ||
textSizeIsLarge: PropTypes.bool.isRequired, | ||
onComponentHidden: PropTypes.func.isRequired, | ||
onInput: PropTypes.func.isRequired, | ||
onRequestedLineFocused: PropTypes.func.isRequired, | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,9 @@ import {t} from 'i18next'; | |
import {DraggableCore} from 'react-draggable'; | ||
import bindAll from 'lodash/bindAll'; | ||
import isEmpty from 'lodash/isEmpty'; | ||
import includes from 'lodash/includes'; | ||
import partial from 'lodash/partial'; | ||
import partition from 'lodash/partition'; | ||
import find from 'lodash/find'; | ||
import {getNodeHeights} from '../util/resize'; | ||
|
||
import EditorContainer from './EditorContainer'; | ||
|
@@ -50,6 +50,7 @@ export default class EditorsColumn extends React.Component { | |
currentProject, | ||
editorsFlex, | ||
errors, | ||
onComponentHidden, | ||
onComponentHide, | ||
onEditorInput, | ||
onRef, | ||
|
@@ -61,10 +62,7 @@ export default class EditorsColumn extends React.Component { | |
const children = []; | ||
const [hiddenLanguages, visibleLanguages] = partition( | ||
['html', 'css', 'javascript'], | ||
language => includes( | ||
currentProject.hiddenUIComponents, | ||
`editor.${language}`, | ||
), | ||
language => find(currentProject.hiddenUIComponents, {language}), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @outoftime My only hesitation with renaming the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel you, but I think the decoupling of the property from the specific use case here is valuable enough to make it worth it. And I think passing the search spec |
||
); | ||
visibleLanguages.forEach((language, index) => { | ||
children.push( | ||
|
@@ -73,7 +71,7 @@ export default class EditorsColumn extends React.Component { | |
language={language} | ||
source={currentProject.sources[language]} | ||
style={{flex: editorsFlex[index]}} | ||
onHide={partial(onComponentHide, `editor.${language}`)} | ||
onHide={partial(onComponentHide, language)} | ||
onRef={partial(this._storeEditorRef, index)} | ||
> | ||
<Editor | ||
|
@@ -84,6 +82,7 @@ export default class EditorsColumn extends React.Component { | |
requestedFocusedLine={ui.editors.requestedFocusedLine} | ||
source={currentProject.sources[language]} | ||
textSizeIsLarge={ui.editors.textSizeIsLarge} | ||
onComponentHidden={onComponentHidden} | ||
onInput={partial(onEditorInput, language)} | ||
onRequestedLineFocused={onRequestedLineFocused} | ||
/> | ||
|
@@ -111,7 +110,7 @@ export default class EditorsColumn extends React.Component { | |
key={language} | ||
onClick={partial( | ||
this.props.onComponentUnhide, | ||
`editor.${language}`, | ||
language, | ||
)} | ||
> | ||
<div className="label editors__label editors__label_collapsed"> | ||
|
@@ -147,6 +146,7 @@ EditorsColumn.propTypes = { | |
ui: PropTypes.shape({ | ||
editors: PropTypes.object.isRequired, | ||
}).isRequired, | ||
onComponentHidden: PropTypes.func.isRequired, | ||
onComponentHide: PropTypes.func.isRequired, | ||
onComponentUnhide: PropTypes.func.isRequired, | ||
onDividerDrag: PropTypes.func.isRequired, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,20 +17,20 @@ import {dehydrateProject, rehydrateProject} from '../clients/localStorage'; | |
|
||
import { | ||
updateProjectSource, | ||
hideComponent, | ||
unhideComponent, | ||
editorFocusedRequestedLine, | ||
dragRowDivider, | ||
dragColumnDivider, | ||
startDragColumnDivider, | ||
stopDragColumnDivider, | ||
toggleComponent, | ||
applicationLoaded, | ||
|
||
storeHiddenComponentLine, | ||
focusLine, | ||
} from '../actions'; | ||
|
||
import {isPristineProject} from '../util/projectUtils'; | ||
import {getCurrentProject, isEditingInstructions} from '../selectors'; | ||
import {HiddenUIComponent} from '../records'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m not a huge fan of having a React component explicitly depend on a Redux record class—it’s not something we’ve done elsewhere and increases coupling between the UI implementation and the application state implementation. Instead how about we just pass the |
||
|
||
import TopBar from '../containers/TopBar'; | ||
import Instructions from '../containers/Instructions'; | ||
|
@@ -61,6 +61,7 @@ class Workspace extends React.Component { | |
this, | ||
'_handleUnload', | ||
'_handleClickInstructionsBar', | ||
'_handleComponentHidden', | ||
'_handleComponentUnhide', | ||
'_handleComponentHide', | ||
'_handleDividerDrag', | ||
|
@@ -114,24 +115,29 @@ class Workspace extends React.Component { | |
} | ||
} | ||
|
||
_handleComponentHide(componentName) { | ||
_handleComponentHidden(componentKey, line, column) { | ||
const {projectKey} = this.props.currentProject; | ||
this.props.dispatch( | ||
hideComponent( | ||
this.props.currentProject.projectKey, | ||
componentName, | ||
), | ||
storeHiddenComponentLine(projectKey, componentKey, line, column), | ||
); | ||
} | ||
|
||
_handleComponentUnhide(componentName) { | ||
_handleComponentHide(language) { | ||
this.props.dispatch( | ||
unhideComponent( | ||
toggleComponent( | ||
this.props.currentProject.projectKey, | ||
componentName, | ||
language, | ||
new HiddenUIComponent({componentType: 'editor', language}), | ||
), | ||
); | ||
} | ||
|
||
_handleComponentUnhide(componentKey) { | ||
const {dispatch, currentProject} = this.props; | ||
const {line, column} = currentProject.hiddenUIComponents[componentKey]; | ||
dispatch(focusLine(componentKey, line, column)); | ||
} | ||
|
||
_handleEditorInput(language, source) { | ||
this.props.dispatch( | ||
updateProjectSource( | ||
|
@@ -266,6 +272,7 @@ class Workspace extends React.Component { | |
errors={errors} | ||
style={{flex: rowsFlex[0]}} | ||
ui={ui} | ||
onComponentHidden={this._handleComponentHidden} | ||
onComponentHide={this._handleComponentHide} | ||
onComponentUnhide={this._handleComponentUnhide} | ||
onDividerDrag={this._handleEditorsDividerDrag} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import {Record} from 'immutable'; | ||
|
||
export default Record({ | ||
componentType: '', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would probably just make this default to |
||
language: null, | ||
line: null, | ||
column: null, | ||
}, 'HiddenUIComponent'); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,25 @@ | ||
import {Record, Set} from 'immutable'; | ||
import {Record, Set, Map} from 'immutable'; | ||
import isArray from 'lodash/isArray'; | ||
import isPlainObject from 'lodash/isPlainObject'; | ||
|
||
import HTML_TEMPLATE from '../../templates/new.html'; | ||
import HiddenUIComponent from './HiddenUIComponent'; | ||
|
||
function hiddenUIArrayToObject(hiddenUIComponents) { | ||
let obj = {}; | ||
if (isPlainObject(hiddenUIComponents)) { | ||
obj = hiddenUIComponents; | ||
} else if (isArray(hiddenUIComponents)) { | ||
let component; | ||
for (component of hiddenUIComponents) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about |
||
const [componentType, language] = component.split('.'); | ||
const componentKey = language || componentType; | ||
obj[componentKey] = new HiddenUIComponent({componentType, language}); | ||
} | ||
} | ||
obj.console = new HiddenUIComponent({componentType: 'console'}); | ||
return obj; | ||
} | ||
|
||
const Sources = Record({ | ||
html: HTML_TEMPLATE, | ||
|
@@ -12,23 +31,25 @@ export default class Project extends Record({ | |
projectKey: null, | ||
sources: new Sources(), | ||
enabledLibraries: new Set(), | ||
hiddenUIComponents: new Set(['console']), | ||
hiddenUIComponents: new Map({ | ||
console: new HiddenUIComponent({componentType: 'console'}), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the more I look at this the more I think that the In order to do what we want to do here, I would suggest making this a |
||
}), | ||
updatedAt: null, | ||
instructions: '', | ||
}) { | ||
static fromJS({ | ||
projectKey = null, | ||
sources = {}, | ||
enabledLibraries = [], | ||
hiddenUIComponents = [], | ||
hiddenUIComponents = {}, | ||
updatedAt = null, | ||
instructions = '', | ||
}) { | ||
return new Project({ | ||
projectKey, | ||
sources: new Sources(sources), | ||
enabledLibraries: new Set(enabledLibraries), | ||
hiddenUIComponents: new Set(hiddenUIComponents), | ||
hiddenUIComponents: new Map(hiddenUIArrayToObject(hiddenUIComponents)), | ||
updatedAt, | ||
instructions, | ||
}); | ||
|
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 think the
hiddenUIComponent
parameter here is a vestige of an earlier approach?