-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Mobile Sketch Preview Screen #1467
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
Changes from all commits
0d119aa
bdedc63
0877d39
5c80702
49a9fe7
e5bbb53
0633c3b
e11756d
8a067a8
123c2b0
d00506a
a11bc44
776c3d2
eb3bc59
0e66756
597cb9b
7604e27
ec8566f
ebb9525
75bd5a3
1eb1bff
c39211d
78ec304
9ca0995
7d24c07
8a0b09d
7805acc
a1d6abf
3143cc3
b4c1b86
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 |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import { prop, remSize } from '../../theme'; | ||
|
||
const background = prop('MobilePanel.default.background'); | ||
const textColor = prop('primaryTextColor'); | ||
|
||
const Footer = styled.div` | ||
position: fixed; | ||
width: 100%; | ||
background: ${background}; | ||
color: ${textColor}; | ||
padding: ${remSize(12)}; | ||
padding-left: ${remSize(32)}; | ||
z-index: 1; | ||
|
||
bottom: 0; | ||
`; | ||
|
||
export default Footer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import { prop, remSize } from '../../theme'; | ||
|
||
const background = prop('MobilePanel.default.background'); | ||
const textColor = prop('primaryTextColor'); | ||
|
||
const Header = styled.div` | ||
position: fixed; | ||
width: 100%; | ||
background: ${background}; | ||
color: ${textColor}; | ||
padding: ${remSize(12)}; | ||
padding-left: ${remSize(16)}; | ||
padding-right: ${remSize(16)}; | ||
z-index: 1; | ||
|
||
display: flex; | ||
flex: 1; | ||
flex-direction: row; | ||
justify-content: flex-start; | ||
align-items: center; | ||
|
||
// TODO: | ||
svg { | ||
height: 2rem; | ||
} | ||
`; | ||
|
||
export default Header; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import { remSize } from '../../theme'; | ||
|
||
export default styled.div` | ||
z-index: 0; | ||
margin-top: ${remSize(16)}; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import styled from 'styled-components'; | ||
import Button from '../../common/Button'; | ||
|
||
const ButtonWrapper = styled(Button)` | ||
width: 3rem; | ||
> svg { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
`; | ||
|
||
const IconButton = (props) => { | ||
const { icon, ...otherProps } = props; | ||
const Icon = icon; | ||
|
||
return (<ButtonWrapper | ||
iconBefore={<Icon />} | ||
kind={Button.kinds.inline} | ||
focusable="false" | ||
{...otherProps} | ||
/>); | ||
}; | ||
|
||
IconButton.propTypes = { | ||
icon: PropTypes.func.isRequired | ||
}; | ||
|
||
export default IconButton; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const Screen = ({ children }) => ( | ||
<div className="fullscreen-preview"> | ||
{children} | ||
</div> | ||
); | ||
Screen.propTypes = { | ||
children: PropTypes.node.isRequired | ||
}; | ||
|
||
export default Screen; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,23 @@ import { | |
import { hijackConsoleErrorsScript, startTag, getAllScriptOffsets } | ||
from '../../../utils/consoleUtils'; | ||
|
||
|
||
const shouldRenderSketch = (props, prevProps = undefined) => { | ||
const { isPlaying, previewIsRefreshing, fullView } = props; | ||
|
||
// if the user explicitly clicks on the play button | ||
if (isPlaying && previewIsRefreshing) return true; | ||
|
||
if (!prevProps) return false; | ||
|
||
return (props.isPlaying !== prevProps.isPlaying // if sketch starts or stops playing, want to rerender | ||
|| props.isAccessibleOutputPlaying !== prevProps.isAccessibleOutputPlaying // if user switches textoutput preferences | ||
|| props.textOutput !== prevProps.textOutput | ||
|| props.gridOutput !== prevProps.gridOutput | ||
|| props.soundOutput !== prevProps.soundOutput | ||
|| (fullView && props.files[0].id !== prevProps.files[0].id)); | ||
}; | ||
|
||
class PreviewFrame extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
|
@@ -30,46 +47,17 @@ class PreviewFrame extends React.Component { | |
|
||
componentDidMount() { | ||
window.addEventListener('message', this.handleConsoleEvent); | ||
|
||
const props = { | ||
...this.props, | ||
previewIsRefreshing: this.props.previewIsRefreshing, | ||
isAccessibleOutputPlaying: this.props.isAccessibleOutputPlaying | ||
}; | ||
if (shouldRenderSketch(props)) this.renderSketch(); | ||
} | ||
|
||
componentDidUpdate(prevProps) { | ||
// if sketch starts or stops playing, want to rerender | ||
if (this.props.isPlaying !== prevProps.isPlaying) { | ||
this.renderSketch(); | ||
return; | ||
} | ||
|
||
// if the user explicitly clicks on the play button | ||
if (this.props.isPlaying && this.props.previewIsRefreshing) { | ||
this.renderSketch(); | ||
return; | ||
} | ||
|
||
// if user switches textoutput preferences | ||
if (this.props.isAccessibleOutputPlaying !== prevProps.isAccessibleOutputPlaying) { | ||
this.renderSketch(); | ||
return; | ||
} | ||
|
||
if (this.props.textOutput !== prevProps.textOutput) { | ||
this.renderSketch(); | ||
return; | ||
} | ||
|
||
if (this.props.gridOutput !== prevProps.gridOutput) { | ||
this.renderSketch(); | ||
return; | ||
} | ||
|
||
if (this.props.soundOutput !== prevProps.soundOutput) { | ||
this.renderSketch(); | ||
return; | ||
} | ||
|
||
if (this.props.fullView && this.props.files[0].id !== prevProps.files[0].id) { | ||
this.renderSketch(); | ||
} | ||
|
||
if (shouldRenderSketch(this.props, prevProps)) this.renderSketch(); | ||
// small bug - if autorefresh is on, and the usr changes files | ||
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. Is this a bug that still exists? Should this comment be removed? 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 think the commend holds, since I merely moved code around. The logic is pretty much the same |
||
// in the sketch, preview will reload | ||
} | ||
|
@@ -395,7 +383,7 @@ PreviewFrame.propTypes = { | |
clearConsole: PropTypes.func.isRequired, | ||
cmController: PropTypes.shape({ | ||
getContent: PropTypes.func | ||
}) | ||
}), | ||
}; | ||
|
||
PreviewFrame.defaultProps = { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,93 +20,54 @@ import { getHTMLFile } from '../reducers/files'; | |
|
||
// Local Imports | ||
import Editor from '../components/Editor'; | ||
import { prop, remSize } from '../../../theme'; | ||
import { ExitIcon } from '../../../common/icons'; | ||
|
||
const background = prop('Button.default.background'); | ||
const textColor = prop('primaryTextColor'); | ||
|
||
|
||
const Header = styled.div` | ||
position: fixed; | ||
width: 100%; | ||
background: ${background}; | ||
color: ${textColor}; | ||
padding: ${remSize(12)}; | ||
padding-left: ${remSize(32)}; | ||
padding-right: ${remSize(32)}; | ||
z-index: 1; | ||
|
||
display: flex; | ||
flex: 1; | ||
flex-direction: row; | ||
justify-content: flex-start; | ||
align-items: center; | ||
`; | ||
|
||
const Footer = styled.div` | ||
position: fixed; | ||
width: 100%; | ||
background: ${background}; | ||
color: ${textColor}; | ||
padding: ${remSize(12)}; | ||
padding-left: ${remSize(32)}; | ||
z-index: 1; | ||
|
||
bottom: 0; | ||
`; | ||
|
||
const Content = styled.div` | ||
z-index: 0; | ||
margin-top: ${remSize(16)}; | ||
`; | ||
import { PreferencesIcon, PlayIcon, ExitIcon } from '../../../common/icons'; | ||
|
||
const Icon = styled.a` | ||
> svg { | ||
fill: ${textColor}; | ||
color: ${textColor}; | ||
margin-left: ${remSize(16)}; | ||
} | ||
`; | ||
import IconButton from '../../../components/mobile/IconButton'; | ||
import Header from '../../../components/mobile/Header'; | ||
import Screen from '../../../components/mobile/MobileScreen'; | ||
import Footer from '../../../components/mobile/Footer'; | ||
import IDEWrapper from '../../../components/mobile/IDEWrapper'; | ||
import { remSize } from '../../../theme'; | ||
|
||
const IconLinkWrapper = styled(Link)` | ||
width: 3rem; | ||
margin-right: 1.25rem; | ||
margin-left: none; | ||
const IconContainer = styled.div` | ||
margin-left: ${remSize(32)}; | ||
display: flex; | ||
`; | ||
|
||
|
||
const Screen = ({ children }) => ( | ||
<div className="fullscreen-preview"> | ||
{children} | ||
</div> | ||
); | ||
Screen.propTypes = { | ||
children: PropTypes.node.isRequired | ||
}; | ||
|
||
const isUserOwner = ({ project, user }) => (project.owner && project.owner.id === user.id); | ||
|
||
const IDEViewMobile = (props) => { | ||
const { | ||
preferences, ide, editorAccessibility, project, updateLintMessage, clearLintMessage, selectedFile, updateFileContent, files, closeEditorOptions, showEditorOptions, showKeyboardShortcutModal, setUnsavedChanges, startRefreshSketch, stopSketch, expandSidebar, collapseSidebar, clearConsole, console, showRuntimeErrorWarning, hideRuntimeErrorWarning | ||
preferences, ide, editorAccessibility, project, updateLintMessage, clearLintMessage, | ||
selectedFile, updateFileContent, files, | ||
closeEditorOptions, showEditorOptions, showKeyboardShortcutModal, setUnsavedChanges, | ||
startRefreshSketch, stopSketch, expandSidebar, collapseSidebar, clearConsole, console, | ||
showRuntimeErrorWarning, hideRuntimeErrorWarning, startSketch | ||
} = props; | ||
|
||
const [tmController, setTmController] = useState(null); | ||
const [tmController, setTmController] = useState(null); // eslint-disable-line | ||
const [overlay, setOverlay] = useState(null); // eslint-disable-line | ||
|
||
return ( | ||
<Screen> | ||
<Header> | ||
<IconLinkWrapper to="/" aria-label="Return to original editor"> | ||
<ExitIcon /> | ||
</IconLinkWrapper> | ||
<div> | ||
<IconButton to="/mobile" icon={ExitIcon} aria-label="Return to original editor" /> | ||
<div style={{ marginLeft: '1rem' }}> | ||
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. if possible i would prefer to not have inline styles! 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 next PR fixes this by improving the structure of the |
||
<h2>{project.name}</h2> | ||
<h3>{selectedFile.name}</h3> | ||
</div> | ||
|
||
<IconContainer> | ||
<IconButton | ||
onClick={() => setOverlay('preferences')} | ||
icon={PreferencesIcon} | ||
aria-label="Open preferences menu" | ||
/> | ||
<IconButton to="/mobile/preview" onClick={() => { startSketch(); }} icon={PlayIcon} aria-label="Run sketch" /> | ||
</IconContainer> | ||
</Header> | ||
|
||
<Content> | ||
<IDEWrapper> | ||
<Editor | ||
lintWarning={preferences.lintWarning} | ||
linewrap={preferences.linewrap} | ||
|
@@ -141,7 +102,7 @@ const IDEViewMobile = (props) => { | |
runtimeErrorWarningVisible={ide.runtimeErrorWarningVisible} | ||
provideController={setTmController} | ||
/> | ||
</Content> | ||
</IDEWrapper> | ||
<Footer><h2>Bottom Bar</h2></Footer> | ||
</Screen> | ||
); | ||
|
@@ -205,6 +166,8 @@ IDEViewMobile.propTypes = { | |
updatedAt: PropTypes.string | ||
}).isRequired, | ||
|
||
startSketch: PropTypes.func.isRequired, | ||
|
||
updateLintMessage: PropTypes.func.isRequired, | ||
|
||
clearLintMessage: PropTypes.func.isRequired, | ||
|
Uh oh!
There was an error while loading. Please reload this page.