Fix save on pressing play with new project -- show save button first time around (as isPlaying get reset when URL is change on save)

This commit is contained in:
Ruben van de Ven 2020-10-09 19:06:19 +02:00
parent c1810ed47f
commit f181bc6cb7
5 changed files with 76 additions and 47 deletions

View file

@ -127,6 +127,7 @@ function getSynchedProject(currentState, responseProject) {
}
export function saveProject(selectedFile = null, autosave = false, mobile = false) {
console.trace('saving inproject.js');
return (dispatch, getState) => {
const state = getState();
if (state.project.isSaving) {

View file

@ -59,7 +59,9 @@ class PreviewFrame extends React.Component {
}
componentDidUpdate(prevProps) {
// console.log(this.props, prevProps);
if (prevProps.isPlaying === true && this.props.isPlaying === false) {
console.trace('update', this.props, prevProps);
}
if (shouldRenderSketch(this.props, prevProps)) this.renderSketch();
// small bug - if autorefresh is on, and the usr changes files
// in the sketch, preview will reload
@ -339,72 +341,81 @@ class PreviewFrame extends React.Component {
// console.log('changed and requiring reload:', changedFiles, filesRequiringReload, filesToHotSwap);
let saving;
if (changedFiles.length > 0) {
console.log('is saving...', this.props);
if (changedFiles.length > 0 || this.props.project.updatedAt === '') {
saving = this.props.saveProject();
} else {
// can be done pretier: a promise that always resolves
saving = new Promise((resolve, err) => resolve());
}
console.log('saving:', saving);
if (saving === null) {
// console.log('Error saving... not authenticated?');
console.log('Error saving... not authenticated?');
this.props.stopSketch(); // prevent crazy loop of renderSketch() through componentDidUpdate()
} else {
saving.catch(() => {
// console.log('Error when saving... not authenticated? Redirect!');
console.log('Error when saving... not authenticated? Redirect!');
this.props.stopSketch(); // prevent crazy loop of renderSketch() through componentDidUpdate()
// this.props.clearConsole(); // introduces bug: causes nested compnonentDidUpdate()
});
saving.then(() => {
console.log('play!', this.props.isPlaying);
if (this.props.isPlaying) {
this.props.clearConsole();
doc.removeAttribute('srcdoc');
const source = `${window.location.origin}/${this.props.project.owner.username}/sketches/${this.props.project.id}/index.html`;
// console.log('FILES', this.props.files, doc.src, source, lastUpdate);
if (doc.src === source) {
// const newFiles = this.props.files.filter(file => new Date(file.updatedAt) > lastUpdate);
if (this.props.unsavedChanges) {
// console.log('unsaved changes');
}
// console.log('doc', doc);
// we need a hard reload
if (filesRequiringReload.length > 0) {
doc.src = source; // for now...
} else {
// if (doc.contentWindow.document.querySelector('script[src="/assets/hotswap.js"]') == null) {
// const headEl = doc.contentWindow.document.querySelector('head');
// const srcEl = doc.contentWindow.document.createElement('script');
// srcEl.src = '/assets/hotswap.js';
// headEl.appendChild(srcEl);
// }
console.log('Hot swap (..append):', filesToHotSwap);
const headEl = doc.contentWindow.document.querySelector('head');
const updatevar = Date.now();
filesToHotSwap.forEach((file) => {
// doc.contentWindow.postMessage({ 'action': 'code', 'contents': file.content }, '*');
const srcEl = doc.contentWindow.document.createElement('script');
srcEl.src = `${file.name}?changed=${updatevar}`;
srcEl.onload = 'setupAssets();'; // (re)load assets
headEl.appendChild(srcEl);
});
}
// if ( this.props.htmlFile.content === doc.contentWindow)
// TODO: don't set, but update only (will be hard... :-P)
if (typeof this.props.project.owner === 'undefined') {
console.error('no owner for project?', this.props.project);
} else {
doc.src = source;
}
// lastUpdate = new Date();
if (this.props.endSketchRefresh) {
this.props.endSketchRefresh();
const source = `${window.location.origin}/${this.props.project.owner.username}/sketches/${this.props.project.id}/index.html`;
// console.log('FILES', this.props.files, doc.src, source, lastUpdate);
if (doc.src === source) {
// const newFiles = this.props.files.filter(file => new Date(file.updatedAt) > lastUpdate);
if (this.props.unsavedChanges) {
// console.log('unsaved changes');
}
// console.log('doc', doc);
// we need a hard reload
if (filesRequiringReload.length > 0) {
doc.src = source; // for now...
} else {
// if (doc.contentWindow.document.querySelector('script[src="/assets/hotswap.js"]') == null) {
// const headEl = doc.contentWindow.document.querySelector('head');
// const srcEl = doc.contentWindow.document.createElement('script');
// srcEl.src = '/assets/hotswap.js';
// headEl.appendChild(srcEl);
// }
console.log('Hot swap (..append):', filesToHotSwap);
const headEl = doc.contentWindow.document.querySelector('head');
const updatevar = Date.now();
filesToHotSwap.forEach((file) => {
// doc.contentWindow.postMessage({ 'action': 'code', 'contents': file.content }, '*');
const srcEl = doc.contentWindow.document.createElement('script');
srcEl.src = `${file.name}?changed=${updatevar}`;
srcEl.onload = 'setupAssets();'; // (re)load assets
headEl.appendChild(srcEl);
});
}
// if ( this.props.htmlFile.content === doc.contentWindow)
// TODO: don't set, but update only (will be hard... :-P)
} else {
doc.src = source;
}
}
} else {
doc.removeAttribute('src');
doc.srcdoc = '';
srcDoc.set(doc, ' ');
}
// prevent looping
if (this.props.endSketchRefresh) {
this.props.endSketchRefresh();
}
});
}
}
@ -463,7 +474,7 @@ PreviewFrame.propTypes = {
}),
updatedAt: PropTypes.string,
}).isRequired,
clearConsole: PropTypes.func.isRequired,
// clearConsole: PropTypes.func,
unsavedChanges: PropTypes.bool,
cmController: PropTypes.shape({
getContent: PropTypes.func
@ -473,7 +484,7 @@ PreviewFrame.propTypes = {
PreviewFrame.defaultProps = {
fullView: false,
unsavedChanges: false,
cmController: {}
cmController: {},
};
export default PreviewFrame;

View file

@ -60,7 +60,9 @@ class Toolbar extends React.Component {
render() {
const playButtonClass = classNames({
'toolbar__play-button': true,
'toolbar__play-button--selected': this.props.isPlaying
'toolbar__play-button--selected': this.props.isPlaying,
'toolbar__play-button--saved': this.props.isSaved,
'toolbar__play-button--unsaved': !this.props.isSaved
});
const stopButtonClass = classNames({
'toolbar__stop-button': true,
@ -176,6 +178,7 @@ class Toolbar extends React.Component {
Toolbar.propTypes = {
isPlaying: PropTypes.bool.isRequired,
isSaved: PropTypes.bool.isRequired,
preferencesIsVisible: PropTypes.bool.isRequired,
stopSketch: PropTypes.func.isRequired,
setProjectName: PropTypes.func.isRequired,
@ -215,6 +218,7 @@ function mapStateToProps(state) {
infiniteLoop: state.ide.infiniteLoop,
isPlaying: state.ide.isPlaying,
owner: state.project.owner,
isSaved: state.project.updatedAt !== '',
preferencesIsVisible: state.ide.preferencesIsVisible,
project: state.project,
};

View file

@ -174,12 +174,13 @@ class IDEView extends React.Component {
this.autosaveInterval = null;
}
saveProject() {
console.trace('saving!');
// return a Promise to save or null
if (
isUserOwner(this.props) ||
(this.props.user.authenticated && !this.props.project.owner)
) {
console.log('project to save:', this.props.project);
console.trace('project to save:', this.props.project);
return this.props.saveProject(this.cmController.getContent());
} else if (this.props.user.authenticated) {
return this.props.cloneProject();

View file

@ -1,4 +1,16 @@
.toolbar__play-button {
&--unsaved {
// for some reason, I cannot manage to have PreviewFrame save _and_ actuall yload the project (it stops the playback)
// pressing twice works. So just show a floppy the first time around :-)
svg {
display: none;
}
&::after{
content: '\1F4BE'; // save floppy
}
// background-color: blue !important;
}
@include themify() {
@extend %toolbar-button;
display: flex;