mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-27 00:30:09 +02:00
add error modal when js preview not working
This commit is contained in:
@@ -14,6 +14,7 @@ import { trackEvent } from '../analytics';
|
|||||||
import { Console } from './Console';
|
import { Console } from './Console';
|
||||||
import CssSettingsModal from './CssSettingsModal';
|
import CssSettingsModal from './CssSettingsModal';
|
||||||
import { PreviewDimension } from './PreviewDimension.jsx';
|
import { PreviewDimension } from './PreviewDimension.jsx';
|
||||||
|
import Modal from './Modal.jsx';
|
||||||
const minCodeWrapSize = 33;
|
const minCodeWrapSize = 33;
|
||||||
|
|
||||||
/* global htmlCodeEl
|
/* global htmlCodeEl
|
||||||
@@ -25,6 +26,7 @@ export default class ContentWrap extends Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
isConsoleOpen: false,
|
isConsoleOpen: false,
|
||||||
isCssSettingsModalOpen: false,
|
isCssSettingsModalOpen: false,
|
||||||
|
isPreviewNotWorkingModalVisible: false,
|
||||||
logs: []
|
logs: []
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,19 +45,21 @@ export default class ContentWrap extends Component {
|
|||||||
// `clearConsole` is on window because it gets called from inside iframe also.
|
// `clearConsole` is on window because it gets called from inside iframe also.
|
||||||
window.clearConsole = this.clearConsole.bind(this);
|
window.clearConsole = this.clearConsole.bind(this);
|
||||||
|
|
||||||
this.consoleHeaderDblClickHandler = this.consoleHeaderDblClickHandler.bind(
|
this.consoleHeaderDblClickHandler =
|
||||||
this
|
this.consoleHeaderDblClickHandler.bind(this);
|
||||||
);
|
this.clearConsoleBtnClickHandler =
|
||||||
this.clearConsoleBtnClickHandler = this.clearConsoleBtnClickHandler.bind(
|
this.clearConsoleBtnClickHandler.bind(this);
|
||||||
this
|
|
||||||
);
|
|
||||||
this.toggleConsole = this.toggleConsole.bind(this);
|
this.toggleConsole = this.toggleConsole.bind(this);
|
||||||
this.evalConsoleExpr = this.evalConsoleExpr.bind(this);
|
this.evalConsoleExpr = this.evalConsoleExpr.bind(this);
|
||||||
|
this.dismissPreviewNotWorkingModal =
|
||||||
|
this.dismissPreviewNotWorkingModal.bind(this);
|
||||||
}
|
}
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return (
|
return (
|
||||||
this.state.isConsoleOpen !== nextState.isConsoleOpen ||
|
this.state.isConsoleOpen !== nextState.isConsoleOpen ||
|
||||||
this.state.isCssSettingsModalOpen !== nextState.isCssSettingsModalOpen ||
|
this.state.isCssSettingsModalOpen !== nextState.isCssSettingsModalOpen ||
|
||||||
|
this.state.isPreviewNotWorkingModalVisible !==
|
||||||
|
nextState.isPreviewNotWorkingModalVisible ||
|
||||||
this.state.logs !== nextState.logs ||
|
this.state.logs !== nextState.logs ||
|
||||||
this.state.codeSplitSizes !== nextState.codeSplitSizes ||
|
this.state.codeSplitSizes !== nextState.codeSplitSizes ||
|
||||||
this.state.mainSplitSizes !== nextState.mainSplitSizes ||
|
this.state.mainSplitSizes !== nextState.mainSplitSizes ||
|
||||||
@@ -127,8 +131,12 @@ export default class ContentWrap extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createPreviewFile(html, css, js) {
|
createPreviewFile(html, css, js) {
|
||||||
|
const versionMatch = navigator.userAgent.match(/Chrome\/(\d+)/);
|
||||||
|
|
||||||
const shouldInlineJs =
|
const shouldInlineJs =
|
||||||
!window.webkitRequestFileSystem || !window.IS_EXTENSION;
|
!window.webkitRequestFileSystem ||
|
||||||
|
!window.IS_EXTENSION ||
|
||||||
|
(versionMatch && +versionMatch[1] >= 104);
|
||||||
var contents = getCompleteHtml(
|
var contents = getCompleteHtml(
|
||||||
html,
|
html,
|
||||||
css,
|
css,
|
||||||
@@ -278,6 +286,19 @@ export default class ContentWrap extends Component {
|
|||||||
this.showErrors(resultItem.errors.lang, resultItem.errors.data);
|
this.showErrors(resultItem.errors.lang, resultItem.errors.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const versionMatch = navigator.userAgent.match(/Chrome\/(\d+)/);
|
||||||
|
if (
|
||||||
|
result[2].code &&
|
||||||
|
versionMatch &&
|
||||||
|
+versionMatch[1] >= 104 &&
|
||||||
|
window.IS_EXTENSION &&
|
||||||
|
!window.sessionStorage.getItem('previewErrorMessageDismissed')
|
||||||
|
) {
|
||||||
|
this.setState({
|
||||||
|
isPreviewNotWorkingModalVisible: true
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,12 +341,13 @@ export default class ContentWrap extends Component {
|
|||||||
window.editorThemeLinkTag.href = `lib/codemirror/theme/${prefs.editorTheme}.css`;
|
window.editorThemeLinkTag.href = `lib/codemirror/theme/${prefs.editorTheme}.css`;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.fontStyleTag.textContent = window.fontStyleTemplate.textContent.replace(
|
window.fontStyleTag.textContent =
|
||||||
/fontname/g,
|
window.fontStyleTemplate.textContent.replace(
|
||||||
(prefs.editorFont === 'other'
|
/fontname/g,
|
||||||
? prefs.editorCustomFont
|
(prefs.editorFont === 'other'
|
||||||
: prefs.editorFont) || 'FiraCode'
|
? prefs.editorCustomFont
|
||||||
);
|
: prefs.editorFont) || 'FiraCode'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all the code wrap if they are minimized or maximized
|
// Check all the code wrap if they are minimized or maximized
|
||||||
@@ -336,7 +358,7 @@ export default class ContentWrap extends Component {
|
|||||||
const { currentLayoutMode } = this.props;
|
const { currentLayoutMode } = this.props;
|
||||||
const prop =
|
const prop =
|
||||||
currentLayoutMode === 2 || currentLayoutMode === 5 ? 'width' : 'height';
|
currentLayoutMode === 2 || currentLayoutMode === 5 ? 'width' : 'height';
|
||||||
[htmlCodeEl, cssCodeEl, jsCodeEl].forEach(function(el) {
|
[htmlCodeEl, cssCodeEl, jsCodeEl].forEach(function (el) {
|
||||||
const bounds = el.getBoundingClientRect();
|
const bounds = el.getBoundingClientRect();
|
||||||
const size = bounds[prop];
|
const size = bounds[prop];
|
||||||
if (size < 100) {
|
if (size < 100) {
|
||||||
@@ -481,9 +503,10 @@ export default class ContentWrap extends Component {
|
|||||||
codeModeChangeHandler(e) {
|
codeModeChangeHandler(e) {
|
||||||
var mode = e.target.value;
|
var mode = e.target.value;
|
||||||
var type = e.target.dataset.type;
|
var type = e.target.dataset.type;
|
||||||
var currentMode = this.props.currentItem[
|
var currentMode =
|
||||||
type === 'html' ? 'htmlMode' : type === 'css' ? 'cssMode' : 'jsMode'
|
this.props.currentItem[
|
||||||
];
|
type === 'html' ? 'htmlMode' : type === 'css' ? 'cssMode' : 'jsMode'
|
||||||
|
];
|
||||||
if (currentMode !== mode) {
|
if (currentMode !== mode) {
|
||||||
if (type === 'html') {
|
if (type === 'html') {
|
||||||
this.updateHtmlMode(mode).then(() => this.setPreviewContent(true));
|
this.updateHtmlMode(mode).then(() => this.setPreviewContent(true));
|
||||||
@@ -604,6 +627,13 @@ export default class ContentWrap extends Component {
|
|||||||
this.props.onPrettifyBtnClick(codeType);
|
this.props.onPrettifyBtnClick(codeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dismissPreviewNotWorkingModal() {
|
||||||
|
this.setState({
|
||||||
|
isPreviewNotWorkingModalVisible: false
|
||||||
|
});
|
||||||
|
window.sessionStorage.setItem('previewErrorMessageDismissed', true);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// log('contentwrap update');
|
// log('contentwrap update');
|
||||||
|
|
||||||
@@ -892,6 +922,34 @@ export default class ContentWrap extends Component {
|
|||||||
settings={this.props.currentItem.cssSettings}
|
settings={this.props.currentItem.cssSettings}
|
||||||
editorTheme={this.props.prefs.editorTheme}
|
editorTheme={this.props.prefs.editorTheme}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
show={this.state.isPreviewNotWorkingModalVisible}
|
||||||
|
closeHandler={this.dismissPreviewNotWorkingModal}
|
||||||
|
>
|
||||||
|
<h1>🔴 JavaScript preview not working!</h1>
|
||||||
|
<p>
|
||||||
|
Latest version of Chrome has changed a few things because of which
|
||||||
|
JavaScript preview has stopped working.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you want to work with just HTML & CSS, you can still continue
|
||||||
|
here. Otherwise, it is recommended to switch to the Web Maker web
|
||||||
|
app which is much more powerful and works offline too -{' '}
|
||||||
|
<a href="https://webmaker.app/app" target="_blank">
|
||||||
|
Go to web app
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-h-end">
|
||||||
|
<button
|
||||||
|
class="btn btn--primary"
|
||||||
|
onClick={this.dismissPreviewNotWorkingModal}
|
||||||
|
>
|
||||||
|
Dismiss
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
);
|
);
|
||||||
|
45
src/utils.js
45
src/utils.js
@@ -36,7 +36,7 @@ var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|||||||
* @param Selector that should match for next siblings
|
* @param Selector that should match for next siblings
|
||||||
* @return element Next element that mathes `selector`
|
* @return element Next element that mathes `selector`
|
||||||
*/
|
*/
|
||||||
Node.prototype.nextUntil = function(selector) {
|
Node.prototype.nextUntil = function (selector) {
|
||||||
const siblings = Array.from(this.parentNode.querySelectorAll(selector));
|
const siblings = Array.from(this.parentNode.querySelectorAll(selector));
|
||||||
const index = siblings.indexOf(this);
|
const index = siblings.indexOf(this);
|
||||||
return siblings[index + 1];
|
return siblings[index + 1];
|
||||||
@@ -46,7 +46,7 @@ Node.prototype.nextUntil = function(selector) {
|
|||||||
* @param Selector that should match for next siblings
|
* @param Selector that should match for next siblings
|
||||||
* @return element Next element that mathes `selector`
|
* @return element Next element that mathes `selector`
|
||||||
*/
|
*/
|
||||||
Node.prototype.previousUntil = function(selector) {
|
Node.prototype.previousUntil = function (selector) {
|
||||||
const siblings = Array.from(this.parentNode.querySelectorAll(selector));
|
const siblings = Array.from(this.parentNode.querySelectorAll(selector));
|
||||||
const index = siblings.indexOf(this);
|
const index = siblings.indexOf(this);
|
||||||
return siblings[index - 1];
|
return siblings[index - 1];
|
||||||
@@ -55,7 +55,7 @@ Node.prototype.previousUntil = function(selector) {
|
|||||||
// Safari doesn't have this!
|
// Safari doesn't have this!
|
||||||
window.requestIdleCallback =
|
window.requestIdleCallback =
|
||||||
window.requestIdleCallback ||
|
window.requestIdleCallback ||
|
||||||
function(fn) {
|
function (fn) {
|
||||||
setTimeout(fn, 10);
|
setTimeout(fn, 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,12 +102,7 @@ export function log() {
|
|||||||
if (window.DEBUG) {
|
if (window.DEBUG) {
|
||||||
const err = new Error();
|
const err = new Error();
|
||||||
console.log(
|
console.log(
|
||||||
parseInt(
|
parseInt(Date.now().toString().substr(4), 10),
|
||||||
Date.now()
|
|
||||||
.toString()
|
|
||||||
.substr(4),
|
|
||||||
10
|
|
||||||
),
|
|
||||||
...arguments,
|
...arguments,
|
||||||
err.stack.split('\n')[2].replace(/\(.*\)/, '')
|
err.stack.split('\n')[2].replace(/\(.*\)/, '')
|
||||||
);
|
);
|
||||||
@@ -133,7 +128,7 @@ export function addInfiniteLoopProtection(code, { timeout }) {
|
|||||||
range: true,
|
range: true,
|
||||||
jsx: true
|
jsx: true
|
||||||
},
|
},
|
||||||
function(node) {
|
function (node) {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'DoWhileStatement':
|
case 'DoWhileStatement':
|
||||||
case 'ForStatement':
|
case 'ForStatement':
|
||||||
@@ -175,10 +170,10 @@ export function addInfiniteLoopProtection(code, { timeout }) {
|
|||||||
|
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
patches
|
patches
|
||||||
.sort(function(a, b) {
|
.sort(function (a, b) {
|
||||||
return b.pos - a.pos;
|
return b.pos - a.pos;
|
||||||
})
|
})
|
||||||
.forEach(function(patch) {
|
.forEach(function (patch) {
|
||||||
code = code.slice(0, patch.pos) + patch.str + code.slice(patch.pos);
|
code = code.slice(0, patch.pos) + patch.str + code.slice(patch.pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -213,7 +208,7 @@ export function getHumanDate(timestamp) {
|
|||||||
// create a one-time event
|
// create a one-time event
|
||||||
export function once(node, type, callback) {
|
export function once(node, type, callback) {
|
||||||
// create event
|
// create event
|
||||||
node.addEventListener(type, function(e) {
|
node.addEventListener(type, function (e) {
|
||||||
// remove event
|
// remove event
|
||||||
e.target.removeEventListener(type, arguments.callee);
|
e.target.removeEventListener(type, arguments.callee);
|
||||||
// call handler
|
// call handler
|
||||||
@@ -258,13 +253,13 @@ export function writeFile(name, blob, cb) {
|
|||||||
var fileWritten = false;
|
var fileWritten = false;
|
||||||
|
|
||||||
function getErrorHandler(type) {
|
function getErrorHandler(type) {
|
||||||
return function() {
|
return function () {
|
||||||
log(arguments);
|
log(arguments);
|
||||||
trackEvent('fn', 'error', type);
|
trackEvent('fn', 'error', type);
|
||||||
// When there are too many write errors, show a message.
|
// When there are too many write errors, show a message.
|
||||||
writeFile.errorCount = (writeFile.errorCount || 0) + 1;
|
writeFile.errorCount = (writeFile.errorCount || 0) + 1;
|
||||||
if (writeFile.errorCount === 4) {
|
if (writeFile.errorCount === 4) {
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
alert(
|
alert(
|
||||||
"Oops! Seems like your preview isn't updating. It's recommended to switch to the web app: https://webmaker.app/app/.\n\n If you still want to get the extension working, please try the following steps until it fixes:\n - Refresh Web Maker\n - Restart browser\n - Update browser\n - Reinstall Web Maker (don't forget to export all your creations from saved items pane (click the OPEN button) before reinstalling)\n\nIf nothing works, please tweet out to @webmakerApp."
|
"Oops! Seems like your preview isn't updating. It's recommended to switch to the web app: https://webmaker.app/app/.\n\n If you still want to get the extension working, please try the following steps until it fixes:\n - Refresh Web Maker\n - Restart browser\n - Update browser\n - Reinstall Web Maker (don't forget to export all your creations from saved items pane (click the OPEN button) before reinstalling)\n\nIf nothing works, please tweet out to @webmakerApp."
|
||||||
);
|
);
|
||||||
@@ -278,13 +273,13 @@ export function writeFile(name, blob, cb) {
|
|||||||
window.webkitRequestFileSystem(
|
window.webkitRequestFileSystem(
|
||||||
window.TEMPORARY,
|
window.TEMPORARY,
|
||||||
1024 * 1024 * 5,
|
1024 * 1024 * 5,
|
||||||
function(fs) {
|
function (fs) {
|
||||||
fs.root.getFile(
|
fs.root.getFile(
|
||||||
name,
|
name,
|
||||||
{
|
{
|
||||||
create: true
|
create: true
|
||||||
},
|
},
|
||||||
function(fileEntry) {
|
function (fileEntry) {
|
||||||
fileEntry.createWriter(fileWriter => {
|
fileEntry.createWriter(fileWriter => {
|
||||||
function onWriteComplete() {
|
function onWriteComplete() {
|
||||||
if (fileWritten) {
|
if (fileWritten) {
|
||||||
@@ -317,7 +312,7 @@ export function loadJS(src) {
|
|||||||
script.src = src;
|
script.src = src;
|
||||||
script.async = true;
|
script.async = true;
|
||||||
ref.parentNode.insertBefore(script, ref);
|
ref.parentNode.insertBefore(script, ref);
|
||||||
script.onload = function() {
|
script.onload = function () {
|
||||||
d.resolve();
|
d.resolve();
|
||||||
};
|
};
|
||||||
return d.promise;
|
return d.promise;
|
||||||
@@ -332,7 +327,7 @@ export function loadCss({ url, id }) {
|
|||||||
style.setAttribute('id', id);
|
style.setAttribute('id', id);
|
||||||
}
|
}
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
style.onload = function() {
|
style.onload = function () {
|
||||||
d.resolve();
|
d.resolve();
|
||||||
};
|
};
|
||||||
return d.promise;
|
return d.promise;
|
||||||
@@ -350,12 +345,12 @@ export function getCompleteHtml(html, css, js, item, isForExport) {
|
|||||||
if (item.externalLibs) {
|
if (item.externalLibs) {
|
||||||
externalJs = item.externalLibs.js
|
externalJs = item.externalLibs.js
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.reduce(function(scripts, url) {
|
.reduce(function (scripts, url) {
|
||||||
return scripts + (url ? '\n<script src="' + url + '"></script>' : '');
|
return scripts + (url ? '\n<script src="' + url + '"></script>' : '');
|
||||||
}, '');
|
}, '');
|
||||||
externalCss = item.externalLibs.css
|
externalCss = item.externalLibs.css
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.reduce(function(links, url) {
|
.reduce(function (links, url) {
|
||||||
return (
|
return (
|
||||||
links +
|
links +
|
||||||
(url ? '\n<link rel="stylesheet" href="' + url + '"></link>' : '')
|
(url ? '\n<link rel="stylesheet" href="' + url + '"></link>' : '')
|
||||||
@@ -399,7 +394,7 @@ export function getCompleteHtml(html, css, js, item, isForExport) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof js === 'string') {
|
if (typeof js === 'string') {
|
||||||
contents += '<script>\n' + js + '\n//# sourceURL=userscript.js';
|
contents += js ? '<script>\n' + js + '\n//# sourceURL=userscript.js' : '';
|
||||||
} else {
|
} else {
|
||||||
var origin = chrome.i18n.getMessage()
|
var origin = chrome.i18n.getMessage()
|
||||||
? `chrome-extension://${chrome.i18n.getMessage('@@extension_id')}`
|
? `chrome-extension://${chrome.i18n.getMessage('@@extension_id')}`
|
||||||
@@ -458,7 +453,7 @@ export function handleDownloadsPermission() {
|
|||||||
{
|
{
|
||||||
permissions: ['downloads']
|
permissions: ['downloads']
|
||||||
},
|
},
|
||||||
function(result) {
|
function (result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
d.resolve();
|
d.resolve();
|
||||||
} else {
|
} else {
|
||||||
@@ -466,7 +461,7 @@ export function handleDownloadsPermission() {
|
|||||||
{
|
{
|
||||||
permissions: ['downloads']
|
permissions: ['downloads']
|
||||||
},
|
},
|
||||||
function(granted) {
|
function (granted) {
|
||||||
if (granted) {
|
if (granted) {
|
||||||
trackEvent('fn', 'downloadsPermGiven');
|
trackEvent('fn', 'downloadsPermGiven');
|
||||||
d.resolve();
|
d.resolve();
|
||||||
@@ -535,7 +530,7 @@ export function handleModeRequirements(mode) {
|
|||||||
} else if (mode === CssModes.LESS) {
|
} else if (mode === CssModes.LESS) {
|
||||||
loadJS(`${baseTranspilerPath}/less.min.js`).then(setLoadedFlag);
|
loadJS(`${baseTranspilerPath}/less.min.js`).then(setLoadedFlag);
|
||||||
} else if (mode === CssModes.SCSS || mode === CssModes.SASS) {
|
} else if (mode === CssModes.SCSS || mode === CssModes.SASS) {
|
||||||
loadJS(`${baseTranspilerPath}/sass.js`).then(function() {
|
loadJS(`${baseTranspilerPath}/sass.js`).then(function () {
|
||||||
window.sass = new Sass(`${baseTranspilerPath}/sass.worker.js`);
|
window.sass = new Sass(`${baseTranspilerPath}/sass.worker.js`);
|
||||||
setLoadedFlag();
|
setLoadedFlag();
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user