From 03489400e4cc98887e73162eddd8ab277ef12287 Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Thu, 8 Sep 2022 09:41:26 +0530 Subject: [PATCH] add error modal when js preview not working --- src/components/ContentWrap.jsx | 92 +++++++++++++++++++++++++++------- src/utils.js | 45 ++++++++--------- 2 files changed, 95 insertions(+), 42 deletions(-) diff --git a/src/components/ContentWrap.jsx b/src/components/ContentWrap.jsx index 5a77994..462d564 100644 --- a/src/components/ContentWrap.jsx +++ b/src/components/ContentWrap.jsx @@ -14,6 +14,7 @@ import { trackEvent } from '../analytics'; import { Console } from './Console'; import CssSettingsModal from './CssSettingsModal'; import { PreviewDimension } from './PreviewDimension.jsx'; +import Modal from './Modal.jsx'; const minCodeWrapSize = 33; /* global htmlCodeEl @@ -25,6 +26,7 @@ export default class ContentWrap extends Component { this.state = { isConsoleOpen: false, isCssSettingsModalOpen: false, + isPreviewNotWorkingModalVisible: false, logs: [] }; @@ -43,19 +45,21 @@ export default class ContentWrap extends Component { // `clearConsole` is on window because it gets called from inside iframe also. window.clearConsole = this.clearConsole.bind(this); - this.consoleHeaderDblClickHandler = this.consoleHeaderDblClickHandler.bind( - this - ); - this.clearConsoleBtnClickHandler = this.clearConsoleBtnClickHandler.bind( - this - ); + this.consoleHeaderDblClickHandler = + this.consoleHeaderDblClickHandler.bind(this); + this.clearConsoleBtnClickHandler = + this.clearConsoleBtnClickHandler.bind(this); this.toggleConsole = this.toggleConsole.bind(this); this.evalConsoleExpr = this.evalConsoleExpr.bind(this); + this.dismissPreviewNotWorkingModal = + this.dismissPreviewNotWorkingModal.bind(this); } shouldComponentUpdate(nextProps, nextState) { return ( this.state.isConsoleOpen !== nextState.isConsoleOpen || this.state.isCssSettingsModalOpen !== nextState.isCssSettingsModalOpen || + this.state.isPreviewNotWorkingModalVisible !== + nextState.isPreviewNotWorkingModalVisible || this.state.logs !== nextState.logs || this.state.codeSplitSizes !== nextState.codeSplitSizes || this.state.mainSplitSizes !== nextState.mainSplitSizes || @@ -127,8 +131,12 @@ export default class ContentWrap extends Component { } createPreviewFile(html, css, js) { + const versionMatch = navigator.userAgent.match(/Chrome\/(\d+)/); + const shouldInlineJs = - !window.webkitRequestFileSystem || !window.IS_EXTENSION; + !window.webkitRequestFileSystem || + !window.IS_EXTENSION || + (versionMatch && +versionMatch[1] >= 104); var contents = getCompleteHtml( html, css, @@ -278,6 +286,19 @@ export default class ContentWrap extends Component { 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.fontStyleTag.textContent = window.fontStyleTemplate.textContent.replace( - /fontname/g, - (prefs.editorFont === 'other' - ? prefs.editorCustomFont - : prefs.editorFont) || 'FiraCode' - ); + window.fontStyleTag.textContent = + window.fontStyleTemplate.textContent.replace( + /fontname/g, + (prefs.editorFont === 'other' + ? prefs.editorCustomFont + : prefs.editorFont) || 'FiraCode' + ); } // 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 prop = currentLayoutMode === 2 || currentLayoutMode === 5 ? 'width' : 'height'; - [htmlCodeEl, cssCodeEl, jsCodeEl].forEach(function(el) { + [htmlCodeEl, cssCodeEl, jsCodeEl].forEach(function (el) { const bounds = el.getBoundingClientRect(); const size = bounds[prop]; if (size < 100) { @@ -481,9 +503,10 @@ export default class ContentWrap extends Component { codeModeChangeHandler(e) { var mode = e.target.value; var type = e.target.dataset.type; - var currentMode = this.props.currentItem[ - type === 'html' ? 'htmlMode' : type === 'css' ? 'cssMode' : 'jsMode' - ]; + var currentMode = + this.props.currentItem[ + type === 'html' ? 'htmlMode' : type === 'css' ? 'cssMode' : 'jsMode' + ]; if (currentMode !== mode) { if (type === 'html') { this.updateHtmlMode(mode).then(() => this.setPreviewContent(true)); @@ -604,6 +627,13 @@ export default class ContentWrap extends Component { this.props.onPrettifyBtnClick(codeType); } + dismissPreviewNotWorkingModal() { + this.setState({ + isPreviewNotWorkingModalVisible: false + }); + window.sessionStorage.setItem('previewErrorMessageDismissed', true); + } + render() { // log('contentwrap update'); @@ -892,6 +922,34 @@ export default class ContentWrap extends Component { settings={this.props.currentItem.cssSettings} editorTheme={this.props.prefs.editorTheme} /> + + +

🔴 JavaScript preview not working!

+

+ Latest version of Chrome has changed a few things because of which + JavaScript preview has stopped working. +

+ +

+ 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 -{' '} + + Go to web app + +

+
+ +
+
); diff --git a/src/utils.js b/src/utils.js index 6e479d8..050c096 100644 --- a/src/utils.js +++ b/src/utils.js @@ -36,7 +36,7 @@ var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; * @param Selector that should match for next siblings * @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 index = siblings.indexOf(this); return siblings[index + 1]; @@ -46,7 +46,7 @@ Node.prototype.nextUntil = function(selector) { * @param Selector that should match for next siblings * @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 index = siblings.indexOf(this); return siblings[index - 1]; @@ -55,7 +55,7 @@ Node.prototype.previousUntil = function(selector) { // Safari doesn't have this! window.requestIdleCallback = window.requestIdleCallback || - function(fn) { + function (fn) { setTimeout(fn, 10); }; @@ -102,12 +102,7 @@ export function log() { if (window.DEBUG) { const err = new Error(); console.log( - parseInt( - Date.now() - .toString() - .substr(4), - 10 - ), + parseInt(Date.now().toString().substr(4), 10), ...arguments, err.stack.split('\n')[2].replace(/\(.*\)/, '') ); @@ -133,7 +128,7 @@ export function addInfiniteLoopProtection(code, { timeout }) { range: true, jsx: true }, - function(node) { + function (node) { switch (node.type) { case 'DoWhileStatement': case 'ForStatement': @@ -175,10 +170,10 @@ export function addInfiniteLoopProtection(code, { timeout }) { /* eslint-disable no-param-reassign */ patches - .sort(function(a, b) { + .sort(function (a, b) { return b.pos - a.pos; }) - .forEach(function(patch) { + .forEach(function (patch) { 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 export function once(node, type, callback) { // create event - node.addEventListener(type, function(e) { + node.addEventListener(type, function (e) { // remove event e.target.removeEventListener(type, arguments.callee); // call handler @@ -258,13 +253,13 @@ export function writeFile(name, blob, cb) { var fileWritten = false; function getErrorHandler(type) { - return function() { + return function () { log(arguments); trackEvent('fn', 'error', type); // When there are too many write errors, show a message. writeFile.errorCount = (writeFile.errorCount || 0) + 1; if (writeFile.errorCount === 4) { - setTimeout(function() { + setTimeout(function () { 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." ); @@ -278,13 +273,13 @@ export function writeFile(name, blob, cb) { window.webkitRequestFileSystem( window.TEMPORARY, 1024 * 1024 * 5, - function(fs) { + function (fs) { fs.root.getFile( name, { create: true }, - function(fileEntry) { + function (fileEntry) { fileEntry.createWriter(fileWriter => { function onWriteComplete() { if (fileWritten) { @@ -317,7 +312,7 @@ export function loadJS(src) { script.src = src; script.async = true; ref.parentNode.insertBefore(script, ref); - script.onload = function() { + script.onload = function () { d.resolve(); }; return d.promise; @@ -332,7 +327,7 @@ export function loadCss({ url, id }) { style.setAttribute('id', id); } document.head.appendChild(style); - style.onload = function() { + style.onload = function () { d.resolve(); }; return d.promise; @@ -350,12 +345,12 @@ export function getCompleteHtml(html, css, js, item, isForExport) { if (item.externalLibs) { externalJs = item.externalLibs.js .split('\n') - .reduce(function(scripts, url) { + .reduce(function (scripts, url) { return scripts + (url ? '\n' : ''); }, ''); externalCss = item.externalLibs.css .split('\n') - .reduce(function(links, url) { + .reduce(function (links, url) { return ( links + (url ? '\n' : '') @@ -399,7 +394,7 @@ export function getCompleteHtml(html, css, js, item, isForExport) { } if (typeof js === 'string') { - contents += '