1
0
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:
Kushagra Gour
2022-09-08 09:41:26 +05:30
parent 2f40d21bae
commit 03489400e4
2 changed files with 95 additions and 42 deletions

View File

@@ -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,7 +341,8 @@ 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 =
window.fontStyleTemplate.textContent.replace(
/fontname/g, /fontname/g,
(prefs.editorFont === 'other' (prefs.editorFont === 'other'
? prefs.editorCustomFont ? prefs.editorCustomFont
@@ -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,7 +503,8 @@ 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 =
this.props.currentItem[
type === 'html' ? 'htmlMode' : type === 'css' ? 'cssMode' : 'jsMode' type === 'html' ? 'htmlMode' : type === 'css' ? 'cssMode' : 'jsMode'
]; ];
if (currentMode !== mode) { if (currentMode !== mode) {
@@ -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>
); );

View File

@@ -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();
}); });