From a7b7d7f0f9895d6a0a73958aff280c1d78fa7ecd Mon Sep 17 00:00:00 2001 From: Abhigyan Date: Wed, 16 Oct 2024 14:56:07 +0530 Subject: [PATCH 01/18] Fixes form reinitialization on language change (#3229) --- client/modules/User/components/LoginForm.jsx | 10 ++++++++-- client/modules/User/components/SignupForm.jsx | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx index becf41137..c7d8b75b4 100644 --- a/client/modules/User/components/LoginForm.jsx +++ b/client/modules/User/components/LoginForm.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -8,22 +8,28 @@ import { validateLogin } from '../../../utils/reduxFormUtils'; import { validateAndLoginUser } from '../actions'; function LoginForm() { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const dispatch = useDispatch(); function onSubmit(formProps) { return dispatch(validateAndLoginUser(formProps)); } const [showPassword, setShowPassword] = useState(false); + const [formUpdateKey, setFormUpdateKey] = useState(false); + const handleVisibility = () => { setShowPassword(!showPassword); }; + useEffect(() => { + setFormUpdateKey(!formUpdateKey); + }, [i18n.language]); return (
{({ handleSubmit, submitError, submitting, modifiedSinceLastSubmit }) => ( diff --git a/client/modules/User/components/SignupForm.jsx b/client/modules/User/components/SignupForm.jsx index 75ab6910e..ac83e36c6 100644 --- a/client/modules/User/components/SignupForm.jsx +++ b/client/modules/User/components/SignupForm.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -34,7 +34,7 @@ function validateEmail(email) { } function SignupForm() { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const dispatch = useDispatch(); function onSubmit(formProps) { @@ -42,18 +42,23 @@ function SignupForm() { } const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [formUpdateKey, setFormUpdateKey] = useState(false); const handleVisibility = () => { setShowPassword(!showPassword); }; const handleConfirmVisibility = () => { setShowConfirmPassword(!showConfirmPassword); }; + useEffect(() => { + setFormUpdateKey(!formUpdateKey); + }, [i18n.language]); return ( {({ handleSubmit, pristine, submitting, invalid }) => ( From d8bf87906c1005294ddcd62ac7927c292c1b319b Mon Sep 17 00:00:00 2001 From: Abhigyan Date: Sun, 3 Nov 2024 15:44:48 +0530 Subject: [PATCH 02/18] imporved:user touched values are persisited while translating the errors --- client/modules/User/components/LoginForm.jsx | 155 ++++++----- client/modules/User/components/SignupForm.jsx | 258 +++++++++--------- 2 files changed, 224 insertions(+), 189 deletions(-) diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx index c7d8b75b4..f25029d05 100644 --- a/client/modules/User/components/LoginForm.jsx +++ b/client/modules/User/components/LoginForm.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -15,13 +15,25 @@ function LoginForm() { return dispatch(validateAndLoginUser(formProps)); } const [showPassword, setShowPassword] = useState(false); - const [formUpdateKey, setFormUpdateKey] = useState(false); + const formRef = useRef(null); const handleVisibility = () => { setShowPassword(!showPassword); }; useEffect(() => { - setFormUpdateKey(!formUpdateKey); + const form = formRef.current; + if (!form) return; + + const { values } = form.getState(); // store current form touched values + form.reset(); + + // Restore prev form values and trigger validation + Object.keys(values).forEach((field) => { + if (values[field]) { + // Only reapply touched values + form.change(field, values[field]); + } + }); }, [i18n.language]); return ( @@ -29,77 +41,86 @@ function LoginForm() { fields={['email', 'password']} validate={validateLogin} onSubmit={onSubmit} - key={formUpdateKey} > - {({ handleSubmit, submitError, submitting, modifiedSinceLastSubmit }) => ( - - - {(field) => ( -
- - - {field.meta.touched && field.meta.error && ( - - {field.meta.error} - - )} -
- )} -
- - {(field) => ( -
- -
+ {({ + handleSubmit, + submitError, + submitting, + modifiedSinceLastSubmit, + form + }) => { + formRef.current = form; + + return ( + + + {(field) => ( +
+ - + {field.meta.touched && field.meta.error && ( + + {field.meta.error} + + )} +
+ )} +
+ + {(field) => ( +
+ +
+ + +
+ {field.meta.touched && field.meta.error && ( + + {field.meta.error} + + )}
- {field.meta.touched && field.meta.error && ( - - {field.meta.error} - - )} -
+ )} + + {submitError && !modifiedSinceLastSubmit && ( + {submitError} )} - - {submitError && !modifiedSinceLastSubmit && ( - {submitError} - )} - - - )} + + + ); + }} ); } diff --git a/client/modules/User/components/SignupForm.jsx b/client/modules/User/components/SignupForm.jsx index ac83e36c6..2fe2e6061 100644 --- a/client/modules/User/components/SignupForm.jsx +++ b/client/modules/User/components/SignupForm.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -42,7 +42,7 @@ function SignupForm() { } const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); - const [formUpdateKey, setFormUpdateKey] = useState(false); + const formRef = useRef(null); const handleVisibility = () => { setShowPassword(!showPassword); }; @@ -50,7 +50,19 @@ function SignupForm() { setShowConfirmPassword(!showConfirmPassword); }; useEffect(() => { - setFormUpdateKey(!formUpdateKey); + const form = formRef.current; + if (!form) return; + + const { values } = form.getState(); // store current form touched values + form.reset(); + + // Restore prev form values and trigger validation + Object.keys(values).forEach((field) => { + if (values[field]) { + // Only reapply touched values + form.change(field, values[field]); + } + }); }, [i18n.language]); return ( @@ -58,136 +70,138 @@ function SignupForm() { fields={['username', 'email', 'password', 'confirmPassword']} validate={validateSignup} onSubmit={onSubmit} - key={formUpdateKey} > - {({ handleSubmit, pristine, submitting, invalid }) => ( -
- - {(field) => ( -
- - - {field.meta.touched && field.meta.error && ( - - {field.meta.error} - - )} -
- )} -
- - {(field) => ( -
- - - {field.meta.touched && field.meta.error && ( - - {field.meta.error} - - )} -
- )} -
- - {(field) => ( -
- -
+ {({ handleSubmit, pristine, submitting, invalid, form }) => { + formRef.current = form; + return ( + + + {(field) => ( +
+ - + {field.meta.touched && field.meta.error && ( + + {field.meta.error} + + )}
- {field.meta.touched && field.meta.error && ( - - {field.meta.error} - - )} -
- )} - - - {(field) => ( -
- -
+ )} + + + {(field) => ( +
+ - + {field.meta.touched && field.meta.error && ( + + {field.meta.error} + + )} +
+ )} +
+ + {(field) => ( +
+ +
+ + +
+ {field.meta.touched && field.meta.error && ( + + {field.meta.error} + + )} +
+ )} +
+ + {(field) => ( +
+ +
+ + +
+ {field.meta.touched && field.meta.error && ( + + {field.meta.error} + + )}
- {field.meta.touched && field.meta.error && ( - - {field.meta.error} - - )} -
- )} - - - - )} + )} + + + + ); + }} ); } From 12ff6554fd849483614cf97b894edfeaed5971dc Mon Sep 17 00:00:00 2001 From: raclim Date: Sat, 9 Nov 2024 19:23:39 -0500 Subject: [PATCH 03/18] separate console styles into another file --- client/modules/IDE/components/Console.jsx | 224 +++------------------- client/modules/IDE/utils/consoleStyles.js | 189 ++++++++++++++++++ 2 files changed, 211 insertions(+), 202 deletions(-) create mode 100644 client/modules/IDE/utils/consoleStyles.js diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index f4f8f3239..228780094 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -1,32 +1,11 @@ -import React, { useRef, useEffect } from 'react'; +import React, { useRef, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { bindActionCreators } from 'redux'; - import { useSelector, useDispatch } from 'react-redux'; import classNames from 'classnames'; import { Console as ConsoleFeed } from 'console-feed'; -import warnLightUrl from '../../../images/console-warn-light.svg?byUrl'; -import warnDarkUrl from '../../../images/console-warn-dark.svg?byUrl'; -import warnContrastUrl from '../../../images/console-warn-contrast.svg?byUrl'; -import errorLightUrl from '../../../images/console-error-light.svg?byUrl'; -import errorDarkUrl from '../../../images/console-error-dark.svg?byUrl'; -import errorContrastUrl from '../../../images/console-error-contrast.svg?byUrl'; -import debugLightUrl from '../../../images/console-debug-light.svg?byUrl'; -import debugDarkUrl from '../../../images/console-debug-dark.svg?byUrl'; -import debugContrastUrl from '../../../images/console-debug-contrast.svg?byUrl'; -import infoLightUrl from '../../../images/console-info-light.svg?byUrl'; -import infoDarkUrl from '../../../images/console-info-dark.svg?byUrl'; -import infoContrastUrl from '../../../images/console-info-contrast.svg?byUrl'; import ConsoleInput from './ConsoleInput'; -import commandLightUrl from '../../../images/console-command-light.svg?byUrl'; -import resultLightUrl from '../../../images/console-result-light.svg?byUrl'; -import commandDarkUrl from '../../../images/console-command-dark.svg?byUrl'; -import resultDarkUrl from '../../../images/console-result-dark.svg?byUrl'; -import commandContrastUrl from '../../../images/console-command-contrast.svg?byUrl'; -import resultContrastUrl from '../../../images/console-result-contrast.svg?byUrl'; - import UpArrowIcon from '../../../images/up-arrow.svg'; import DownArrowIcon from '../../../images/down-arrow.svg'; @@ -35,170 +14,7 @@ import * as ConsoleActions from '../../IDE/actions/console'; import { useDidUpdate } from '../hooks/custom-hooks'; import useHandleMessageEvent from '../hooks/useHandleMessageEvent'; import { listen } from '../../../utils/dispatcher'; - -const CONSOLE_FEED_LIGHT_STYLES = { - BASE_BACKGROUND_COLOR: '', - LOG_ERROR_BACKGROUND: 'hsl(0, 100%, 97%)', - LOG_ERROR_COLOR: '#D11518', - LOG_ERROR_BORDER: 'hsl(0, 100%, 92%)', - LOG_WARN_BACKGROUND: 'hsl(50, 100%, 95%)', - LOG_WARN_COLOR: '#996B00', - LOG_WARN_BORDER: 'hsl(50, 100%, 88%)', - LOG_INFO_COLOR: '#4D4D4D', - LOG_DEBUG_COLOR: '#0071AD', - LOG_DEBUG_BACKGROUND: '#D6F1FF', - LOG_DEBUG_BORDER: '#C2EBFF', - LOG_COLOR: '#4D4D4D', - ARROW_COLOR: '#666', - OBJECT_NAME_COLOR: '#333', - OBJECT_VALUE_NULL_COLOR: '#747474', - OBJECT_VALUE_UNDEFINED_COLOR: '#747474', - OBJECT_VALUE_STRING_COLOR: '#47820A', - OBJECT_VALUE_REGEXP_COLOR: '#A06801', - OBJECT_VALUE_NUMBER_COLOR: '#333', - OBJECT_VALUE_BOOLEAN_COLOR: '#D52889', - OBJECT_VALUE_FUNCTION_KEYWORD_COLOR: '#0B7CA9', - LOG_AMOUNT_BACKGROUND: '#5276B7', - LOG_AMOUNT_COLOR: '#FFF', - LOG_WARN_AMOUNT_BACKGROUND: '#996B00', - LOG_ERROR_AMOUNT_BACKGROUND: '#D11518', - LOG_DEBUG_AMOUNT_BACKGROUND: '#0071AD' -}; - -const CONSOLE_FEED_DARK_STYLES = { - BASE_BACKGROUND_COLOR: '', - BASE_COLOR: 'white', - OBJECT_NAME_COLOR: 'white', - OBJECT_VALUE_NULL_COLOR: '#DE4A9B', - OBJECT_VALUE_UNDEFINED_COLOR: '#DE4A9B', - OBJECT_VALUE_REGEXP_COLOR: '#EE9900', - OBJECT_VALUE_STRING_COLOR: '#58a10b', - OBJECT_VALUE_SYMBOL_COLOR: 'hsl(230, 100%, 80%)', - OBJECT_VALUE_NUMBER_COLOR: 'white', - OBJECT_VALUE_BOOLEAN_COLOR: '#DE4A9B', - OBJECT_VALUE_FUNCTION_KEYWORD_COLOR: '#b58318', - LOG_ERROR_BACKGROUND: '#1F0000', - LOG_ERROR_COLOR: '#DF3A3D', - LOG_WARN_BACKGROUND: 'hsl(50, 100%, 10%)', - LOG_WARN_COLOR: '#F5BC38', - LOG_INFO_COLOR: '#D9D9D9', - LOG_INFO_BORDER: '#4D4D4D', - LOG_COLOR: '#D9D9D9', - LOG_DEBUG_COLOR: '#0C99E2', - LOG_DEBUG_BACKGROUND: '#05232E', - LOG_DEBUG_BORDER: '#0C546E', - TABLE_BORDER_COLOR: 'grey', - TABLE_TH_BACKGROUND_COLOR: 'transparent', - TABLE_TH_HOVER_COLOR: 'grey', - TABLE_SORT_ICON_COLOR: 'grey', - TABLE_DATA_BACKGROUND_IMAGE: 'grey', - TABLE_DATA_BACKGROUND_SIZE: 'grey', - ARROW_COLOR: '#D9D9D9', - LOG_AMOUNT_BACKGROUND: '#5276B7', - LOG_AMOUNT_COLOR: '#333', - LOG_WARN_AMOUNT_BACKGROUND: '#996B00', - LOG_ERROR_AMOUNT_BACKGROUND: '#D11518', - LOG_DEBUG_AMOUNT_BACKGROUND: '#0071AD' -}; - -const CONSOLE_FEED_CONTRAST_STYLES = { - BASE_BACKGROUND_COLOR: '', - BASE_COLOR: 'white', - OBJECT_NAME_COLOR: 'white', - OBJECT_VALUE_NULL_COLOR: '#FFA9D9', - OBJECT_VALUE_UNDEFINED_COLOR: '#FFA9D9', - OBJECT_VALUE_REGEXP_COLOR: '#2DE9B6', - OBJECT_VALUE_STRING_COLOR: '#2DE9B6', - OBJECT_VALUE_SYMBOL_COLOR: '#B3BEFF', - OBJECT_VALUE_NUMBER_COLOR: '#FFA9D9', - OBJECT_VALUE_BOOLEAN_COLOR: '#FFA9D9', - OBJECT_VALUE_FUNCTION_KEYWORD_COLOR: '#F5DC23', - LOG_ERROR_BACKGROUND: '#1F0000', - LOG_ERROR_COLOR: '#EA7B7D', - LOG_WARN_BACKGROUND: 'hsl(50, 100%, 10%)', - LOG_WARN_COLOR: '#F5BC38', - LOG_INFO_COLOR: '#D9D9D9', - LOG_INFO_BORDER: '#4D4D4D', - LOG_COLOR: '#D9D9D9', - LOG_DEBUG_COLOR: '#38B6F5', - LOG_DEBUG_BACKGROUND: '#05232E', - LOG_DEBUG_BORDER: '#0C546E', - TABLE_BORDER_COLOR: 'grey', - TABLE_TH_BACKGROUND_COLOR: 'transparent', - TABLE_TH_HOVER_COLOR: 'grey', - TABLE_SORT_ICON_COLOR: 'grey', - TABLE_DATA_BACKGROUND_IMAGE: 'grey', - TABLE_DATA_BACKGROUND_SIZE: 'grey', - ARROW_COLOR: '#D9D9D9', - LOG_AMOUNT_BACKGROUND: '#5276B7', - LOG_AMOUNT_COLOR: '#333', - LOG_WARN_AMOUNT_BACKGROUND: '#966C08', - LOG_ERROR_AMOUNT_BACKGROUND: '#DD3134', - LOG_DEBUG_AMOUNT_BACKGROUND: '#097BB3' -}; - -const getConsoleFeedStyle = (theme, fontSize) => { - const style = { - BASE_FONT_FAMILY: 'Inconsolata, monospace' - }; - const CONSOLE_FEED_LIGHT_ICONS = { - LOG_WARN_ICON: `url(${warnLightUrl})`, - LOG_ERROR_ICON: `url(${errorLightUrl})`, - LOG_DEBUG_ICON: `url(${debugLightUrl})`, - LOG_INFO_ICON: `url(${infoLightUrl})`, - LOG_COMMAND_ICON: `url(${commandLightUrl})`, - LOG_RESULT_ICON: `url(${resultLightUrl})` - }; - const CONSOLE_FEED_DARK_ICONS = { - LOG_WARN_ICON: `url(${warnDarkUrl})`, - LOG_ERROR_ICON: `url(${errorDarkUrl})`, - LOG_DEBUG_ICON: `url(${debugDarkUrl})`, - LOG_INFO_ICON: `url(${infoDarkUrl})`, - LOG_COMMAND_ICON: `url(${commandDarkUrl})`, - LOG_RESULT_ICON: `url(${resultDarkUrl})` - }; - const CONSOLE_FEED_CONTRAST_ICONS = { - LOG_WARN_ICON: `url(${warnContrastUrl})`, - LOG_ERROR_ICON: `url(${errorContrastUrl})`, - LOG_DEBUG_ICON: `url(${debugContrastUrl})`, - LOG_INFO_ICON: `url(${infoContrastUrl})`, - LOG_COMMAND_ICON: `url(${commandContrastUrl})`, - LOG_RESULT_ICON: `url(${resultContrastUrl})` - }; - const CONSOLE_FEED_SIZES = { - TREENODE_LINE_HEIGHT: 1.2, - BASE_FONT_SIZE: `${fontSize}px`, - ARROW_FONT_SIZE: `${fontSize}px`, - LOG_ICON_WIDTH: `${fontSize}px`, - LOG_ICON_HEIGHT: `${1.45 * fontSize}px` - }; - - switch (theme) { - case 'light': - return Object.assign( - CONSOLE_FEED_LIGHT_STYLES || {}, - CONSOLE_FEED_LIGHT_ICONS, - CONSOLE_FEED_SIZES, - style - ); - case 'dark': - return Object.assign( - CONSOLE_FEED_DARK_STYLES || {}, - CONSOLE_FEED_DARK_ICONS, - CONSOLE_FEED_SIZES, - style - ); - case 'contrast': - return Object.assign( - CONSOLE_FEED_CONTRAST_STYLES || {}, - CONSOLE_FEED_CONTRAST_ICONS, - CONSOLE_FEED_SIZES, - style - ); - default: - return ''; - } -}; +import getConsoleFeedStyle from '../utils/consoleStyles'; const Console = () => { const { t } = useTranslation(); @@ -206,12 +22,7 @@ const Console = () => { const isExpanded = useSelector((state) => state.ide.consoleIsExpanded); const isPlaying = useSelector((state) => state.ide.isPlaying); const { theme, fontSize } = useSelector((state) => state.preferences); - const { - collapseConsole, - expandConsole, - clearConsole, - dispatchConsoleEvent - } = bindActionCreators({ ...IDEActions, ...ConsoleActions }, useDispatch()); + const dispatch = useDispatch(); const cm = useRef({}); @@ -219,13 +30,20 @@ const Console = () => { cm.current.scrollTop = cm.current.scrollHeight; }); + const consoleFeedStyle = useMemo(() => getConsoleFeedStyle(theme, fontSize), [ + theme, + fontSize + ]); + const handleMessageEvent = useHandleMessageEvent(); + useEffect(() => { - const unsubscribe = listen(handleMessageEvent); - return function cleanup() { - unsubscribe(); - }; - }); + listen(handleMessageEvent); + }, [handleMessageEvent]); + + const handleClearConsole = () => dispatch(ConsoleActions.clearConsole()); + const handleCollapseConsole = () => dispatch(IDEActions.collapseConsole()); + const handleExpandConsole = () => dispatch(IDEActions.expandConsole()); const consoleClass = classNames({ 'preview-console': true, @@ -239,21 +57,21 @@ const Console = () => {
diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index ca3ab02fd..8f358c93a 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -4,12 +4,13 @@ import CodeMirror from 'codemirror'; import { Encode } from 'console-feed'; import RightArrowIcon from '../../../images/right-arrow.svg'; +import { dispatchConsoleEvent } from '../../IDE/actions/console'; import { dispatchMessage, MessageTypes } from '../../../utils/dispatcher'; // heavily inspired by // https://github.com/codesandbox/codesandbox-client/blob/92a1131f4ded6f7d9c16945dc7c18aa97c8ada27/packages/app/src/app/components/Preview/DevTools/Console/Input/index.tsx -function ConsoleInput({ theme, dispatchConsoleEvent, fontSize }) { +function ConsoleInput({ theme, fontSize }) { const [commandHistory, setCommandHistory] = useState([]); const [commandCursor, setCommandCursor] = useState(-1); const codemirrorContainer = useRef(null); @@ -25,12 +26,6 @@ function ConsoleInput({ theme, dispatchConsoleEvent, fontSize }) { }); cmInstance.current.getWrapperElement().style['font-size'] = `${fontSize}px`; - - return () => { - if (cmInstance.current) { - cmInstance.current = null; - } - }; }, []); useEffect(() => { @@ -78,7 +73,7 @@ function ConsoleInput({ theme, dispatchConsoleEvent, fontSize }) { cmInstance.current.off('keydown', handleEnterKey); } }; - }, [commandHistory, dispatchConsoleEvent]); + }, [commandHistory]); useEffect(() => { const handleUpArrowKey = (cm, e) => { @@ -158,7 +153,6 @@ function ConsoleInput({ theme, dispatchConsoleEvent, fontSize }) { ConsoleInput.propTypes = { theme: PropTypes.string.isRequired, - dispatchConsoleEvent: PropTypes.func.isRequired, fontSize: PropTypes.number.isRequired }; From 1e4c4d5a642ad608b1bae8904f29fe94df8517c1 Mon Sep 17 00:00:00 2001 From: raclim Date: Thu, 14 Nov 2024 13:53:33 -0500 Subject: [PATCH 08/18] change back report variable, make value conditional --- client/utils/previewEntry.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 138e3960b..6c8d43378 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -148,9 +148,10 @@ window.onunhandledrejection = async function onUnhandledRejection(event) { }; // Monkeypatch p5._friendlyError -const p5Call = window.p5; -if (p5Call) { +const _report = window.p5?.report; + +if (_report) { window.p5._report = function resolvedReport(message, method, color) { const urls = Object.keys(window.objectUrls); const paths = Object.keys(window.objectPaths); @@ -176,6 +177,6 @@ if (p5Call) { paths.forEach((path) => { newMessage = newMessage.replaceAll(path, window.objectPaths[path]); }); - p5Call.apply(window.p5, [newMessage, method, color]); + _report.apply(window.p5, [newMessage, method, color]); }; } From 24490ece5cb3c870b2a0bc002b5e4b3d7ae2857c Mon Sep 17 00:00:00 2001 From: raclim Date: Thu, 14 Nov 2024 13:55:31 -0500 Subject: [PATCH 09/18] remove extra space --- client/utils/previewEntry.js | 1 - 1 file changed, 1 deletion(-) diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 6c8d43378..292020c5a 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -148,7 +148,6 @@ window.onunhandledrejection = async function onUnhandledRejection(event) { }; // Monkeypatch p5._friendlyError - const _report = window.p5?.report; if (_report) { From 4e674cb0e42a076c2aa6cf9231530cd966f48343 Mon Sep 17 00:00:00 2001 From: raclim Date: Thu, 14 Nov 2024 14:18:15 -0500 Subject: [PATCH 10/18] fix typo --- client/utils/previewEntry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 292020c5a..a361c0047 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -148,7 +148,7 @@ window.onunhandledrejection = async function onUnhandledRejection(event) { }; // Monkeypatch p5._friendlyError -const _report = window.p5?.report; +const _report = window.p5?._report; if (_report) { window.p5._report = function resolvedReport(message, method, color) { From 0912253e045cd4680bf02c134ad423a4e5134093 Mon Sep 17 00:00:00 2001 From: raclim Date: Thu, 14 Nov 2024 15:45:00 -0500 Subject: [PATCH 11/18] set light as default console theme --- client/modules/IDE/utils/consoleStyles.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/modules/IDE/utils/consoleStyles.js b/client/modules/IDE/utils/consoleStyles.js index b6d95095c..62bba0c6f 100644 --- a/client/modules/IDE/utils/consoleStyles.js +++ b/client/modules/IDE/utils/consoleStyles.js @@ -161,6 +161,7 @@ const getConsoleFeedStyle = (theme, fontSize) => { switch (theme) { case 'light': + default: return Object.assign( CONSOLE_FEED_LIGHT_STYLES || {}, CONSOLE_FEED_LIGHT_ICONS, @@ -181,8 +182,6 @@ const getConsoleFeedStyle = (theme, fontSize) => { CONSOLE_FEED_SIZES, style ); - default: - return ''; } }; From a850d5c603a93199c90627538e1405d80a10b4b2 Mon Sep 17 00:00:00 2001 From: raclim Date: Thu, 14 Nov 2024 16:01:55 -0500 Subject: [PATCH 12/18] add style to console editor div, remove styling hook --- client/modules/IDE/components/ConsoleInput.jsx | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 8f358c93a..c026d29d4 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -24,20 +24,8 @@ function ConsoleInput({ theme, fontSize }) { mode: 'javascript', inputStyle: 'contenteditable' }); - - cmInstance.current.getWrapperElement().style['font-size'] = `${fontSize}px`; }, []); - useEffect(() => { - if (cmInstance.current) { - cmInstance.current.setOption('theme', `p5-${theme}`); - cmInstance.current.getWrapperElement().style[ - 'font-size' - ] = `${fontSize}px`; - cmInstance.current.refresh(); - } - }, [theme, fontSize]); - useEffect(() => { const handleEnterKey = (cm, e) => { if (e.key === 'Enter' && !e.shiftKey) { @@ -146,7 +134,11 @@ function ConsoleInput({ theme, fontSize }) { }} />
-
+
); } From be3d961ec00b7a1d8e301b20877f035c8276838a Mon Sep 17 00:00:00 2001 From: Abhigyan Date: Sat, 16 Nov 2024 11:52:24 +0530 Subject: [PATCH 13/18] extracted common code into a custom hook,removed commnets --- client/modules/IDE/hooks/custom-hooks.js | 19 +++++++++++++++++++ client/modules/User/components/LoginForm.jsx | 18 +++--------------- client/modules/User/components/SignupForm.jsx | 19 +++---------------- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/client/modules/IDE/hooks/custom-hooks.js b/client/modules/IDE/hooks/custom-hooks.js index 1b2c14e44..1683b27b7 100644 --- a/client/modules/IDE/hooks/custom-hooks.js +++ b/client/modules/IDE/hooks/custom-hooks.js @@ -68,3 +68,22 @@ export const useEventListener = ( document.addEventListener(event, callback, useCapture); return () => document.removeEventListener(event, callback, useCapture); }, list); + +// Usage: usePreserveFormValuesOnLanguageChange(formRef, language) +// This hook ensures that form values are preserved when the language changes. +// Pass a ref to the form instance and the current language as arguments. +export const usePreserveFormValuesOnLanguageChange = (formRef, language) => { + useEffect(() => { + const form = formRef.current; + if (!form) return; + + const { values } = form.getState(); + form.reset(); + + Object.keys(values).forEach((field) => { + if (values[field]) { + form.change(field, values[field]); + } + }); + }, [language]); +}; diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx index f25029d05..aaa700fe2 100644 --- a/client/modules/User/components/LoginForm.jsx +++ b/client/modules/User/components/LoginForm.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -6,6 +6,7 @@ import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'; import Button from '../../../common/Button'; import { validateLogin } from '../../../utils/reduxFormUtils'; import { validateAndLoginUser } from '../actions'; +import { usePreserveFormValuesOnLanguageChange } from '../../IDE/hooks/custom-hooks'; function LoginForm() { const { t, i18n } = useTranslation(); @@ -20,21 +21,8 @@ function LoginForm() { const handleVisibility = () => { setShowPassword(!showPassword); }; - useEffect(() => { - const form = formRef.current; - if (!form) return; - const { values } = form.getState(); // store current form touched values - form.reset(); - - // Restore prev form values and trigger validation - Object.keys(values).forEach((field) => { - if (values[field]) { - // Only reapply touched values - form.change(field, values[field]); - } - }); - }, [i18n.language]); + usePreserveFormValuesOnLanguageChange(formRef, i18n.language); return (
{ setShowConfirmPassword(!showConfirmPassword); }; - useEffect(() => { - const form = formRef.current; - if (!form) return; - - const { values } = form.getState(); // store current form touched values - form.reset(); - - // Restore prev form values and trigger validation - Object.keys(values).forEach((field) => { - if (values[field]) { - // Only reapply touched values - form.change(field, values[field]); - } - }); - }, [i18n.language]); + usePreserveFormValuesOnLanguageChange(formRef, i18n.language); return ( Date: Mon, 18 Nov 2024 10:03:34 -0500 Subject: [PATCH 14/18] update hook for preserving form values on language change --- client/common/useSyncFormTranslations.js | 22 +++++++++++++++++++ client/modules/IDE/hooks/custom-hooks.js | 19 ---------------- client/modules/User/components/LoginForm.jsx | 4 ++-- client/modules/User/components/SignupForm.jsx | 4 ++-- 4 files changed, 26 insertions(+), 23 deletions(-) create mode 100644 client/common/useSyncFormTranslations.js diff --git a/client/common/useSyncFormTranslations.js b/client/common/useSyncFormTranslations.js new file mode 100644 index 000000000..411c94236 --- /dev/null +++ b/client/common/useSyncFormTranslations.js @@ -0,0 +1,22 @@ +import { useEffect } from 'react'; + +// Usage: useSyncFormTranslations(formRef, language) +// This hook ensures that form values are preserved when the language changes. +// Pass a ref to the form instance and the current language as arguments. +const useSyncFormTranslations = (formRef, language) => { + useEffect(() => { + const form = formRef.current; + if (!form) return; + + const { values } = form.getState(); + form.reset(); + + Object.keys(values).forEach((field) => { + if (values[field]) { + form.change(field, values[field]); + } + }); + }, [language]); +}; + +export default useSyncFormTranslations; diff --git a/client/modules/IDE/hooks/custom-hooks.js b/client/modules/IDE/hooks/custom-hooks.js index 1683b27b7..1b2c14e44 100644 --- a/client/modules/IDE/hooks/custom-hooks.js +++ b/client/modules/IDE/hooks/custom-hooks.js @@ -68,22 +68,3 @@ export const useEventListener = ( document.addEventListener(event, callback, useCapture); return () => document.removeEventListener(event, callback, useCapture); }, list); - -// Usage: usePreserveFormValuesOnLanguageChange(formRef, language) -// This hook ensures that form values are preserved when the language changes. -// Pass a ref to the form instance and the current language as arguments. -export const usePreserveFormValuesOnLanguageChange = (formRef, language) => { - useEffect(() => { - const form = formRef.current; - if (!form) return; - - const { values } = form.getState(); - form.reset(); - - Object.keys(values).forEach((field) => { - if (values[field]) { - form.change(field, values[field]); - } - }); - }, [language]); -}; diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx index aaa700fe2..eb6eac840 100644 --- a/client/modules/User/components/LoginForm.jsx +++ b/client/modules/User/components/LoginForm.jsx @@ -6,7 +6,7 @@ import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'; import Button from '../../../common/Button'; import { validateLogin } from '../../../utils/reduxFormUtils'; import { validateAndLoginUser } from '../actions'; -import { usePreserveFormValuesOnLanguageChange } from '../../IDE/hooks/custom-hooks'; +import { useSyncFormTranslations } from '../../../common/useSyncFormTranslations'; function LoginForm() { const { t, i18n } = useTranslation(); @@ -22,7 +22,7 @@ function LoginForm() { setShowPassword(!showPassword); }; - usePreserveFormValuesOnLanguageChange(formRef, i18n.language); + useSyncFormTranslations(formRef, i18n.language); return ( { setShowConfirmPassword(!showConfirmPassword); }; - usePreserveFormValuesOnLanguageChange(formRef, i18n.language); + useSyncFormTranslations(formRef, i18n.language); return ( Date: Mon, 18 Nov 2024 10:23:34 -0500 Subject: [PATCH 15/18] add hook to loginform test --- client/modules/User/components/LoginForm.unit.test.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/modules/User/components/LoginForm.unit.test.jsx b/client/modules/User/components/LoginForm.unit.test.jsx index 28fb9383c..2f4262c16 100644 --- a/client/modules/User/components/LoginForm.unit.test.jsx +++ b/client/modules/User/components/LoginForm.unit.test.jsx @@ -23,6 +23,10 @@ jest.mock('../actions', () => ({ ) })); +jest.mock('../../../common/useSyncFormTranslations', () => ({ + useSyncFormTranslations: jest.fn() +})); + const subject = () => { reduxRender(, { store From ae3e46bcc891380266a2ef81d6028375a5da7721 Mon Sep 17 00:00:00 2001 From: raclim Date: Mon, 18 Nov 2024 10:41:44 -0500 Subject: [PATCH 16/18] fix import errors --- client/modules/User/components/LoginForm.jsx | 2 +- client/modules/User/components/SignupForm.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx index eb6eac840..42441861f 100644 --- a/client/modules/User/components/LoginForm.jsx +++ b/client/modules/User/components/LoginForm.jsx @@ -6,7 +6,7 @@ import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'; import Button from '../../../common/Button'; import { validateLogin } from '../../../utils/reduxFormUtils'; import { validateAndLoginUser } from '../actions'; -import { useSyncFormTranslations } from '../../../common/useSyncFormTranslations'; +import useSyncFormTranslations from '../../../common/useSyncFormTranslations'; function LoginForm() { const { t, i18n } = useTranslation(); diff --git a/client/modules/User/components/SignupForm.jsx b/client/modules/User/components/SignupForm.jsx index 14390e6d3..fbb5c49b8 100644 --- a/client/modules/User/components/SignupForm.jsx +++ b/client/modules/User/components/SignupForm.jsx @@ -7,7 +7,7 @@ import { validateSignup } from '../../../utils/reduxFormUtils'; import { validateAndSignUpUser } from '../actions'; import Button from '../../../common/Button'; import apiClient from '../../../utils/apiClient'; -import { useSyncFormTranslations } from '../../../common/useSyncFormTranslations'; +import useSyncFormTranslations from '../../../common/useSyncFormTranslations'; function asyncValidate(fieldToValidate, value) { if (!value || value.trim().length === 0) { From 0d24b14e4986d49971effaa78e5707867d1307ac Mon Sep 17 00:00:00 2001 From: raclim Date: Mon, 18 Nov 2024 10:48:31 -0500 Subject: [PATCH 17/18] update import in login test --- client/modules/User/components/LoginForm.unit.test.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/modules/User/components/LoginForm.unit.test.jsx b/client/modules/User/components/LoginForm.unit.test.jsx index 2f4262c16..7ab207fb0 100644 --- a/client/modules/User/components/LoginForm.unit.test.jsx +++ b/client/modules/User/components/LoginForm.unit.test.jsx @@ -23,9 +23,7 @@ jest.mock('../actions', () => ({ ) })); -jest.mock('../../../common/useSyncFormTranslations', () => ({ - useSyncFormTranslations: jest.fn() -})); +jest.mock('../../../common/useSyncFormTranslations', () => jest.fn()); const subject = () => { reduxRender(, { From 0ae18303b6a3ed2aa83dc0170a932dcac2753b33 Mon Sep 17 00:00:00 2001 From: raclim Date: Mon, 18 Nov 2024 10:54:55 -0500 Subject: [PATCH 18/18] 2.15.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3c3c03201..de6eb98b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "p5.js-web-editor", - "version": "2.15.2", + "version": "2.15.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "p5.js-web-editor", - "version": "2.15.2", + "version": "2.15.3", "license": "LGPL-2.1", "dependencies": { "@auth0/s3": "^1.0.0", diff --git a/package.json b/package.json index 1be4c2556..40c364e6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "p5.js-web-editor", - "version": "2.15.2", + "version": "2.15.3", "description": "The web editor for p5.js.", "scripts": { "clean": "rimraf dist",