Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/components/gui/gui.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import MediaQuery from 'react-responsive';
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
import tabStyles from 'react-tabs/style/react-tabs.css';
import VM from 'scratch-vm';

import Blocks from '../../containers/blocks.jsx';
import CostumeTab from '../../containers/costume-tab.jsx';
import TargetPane from '../../containers/target-pane.jsx';
Expand Down Expand Up @@ -37,7 +36,7 @@ import TWRestorePointManager from '../../containers/tw-restore-point-manager.jsx
import TWFontsModal from '../../containers/tw-fonts-modal.jsx';
import TWUnknownPlatformModal from '../../containers/tw-unknown-platform-modal.jsx';
import TWInvalidProjectModal from '../../containers/tw-invalid-project-modal.jsx';

import WelcomeModal from '../welcome-modal/welcome-modal.jsx';
import {STAGE_SIZE_MODES, FIXED_WIDTH, UNCONSTRAINED_NON_STAGE_WIDTH} from '../../lib/layout-constants';
import {resolveStageSize} from '../../lib/screen-utils';
import {Theme} from '../../lib/themes';
Expand Down Expand Up @@ -160,9 +159,15 @@ const GUIComponent = props => {
fontsModalVisible,
unknownPlatformModalVisible,
invalidProjectModalVisible,
showWelcomeModal,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: onRequestCloseWelcomeModal is used but not destructured from props.

The variable onRequestCloseWelcomeModal is passed to WelcomeModal on line 245 but is never destructured from props in the component's destructuring block (line 163 area). This causes a ReferenceError at runtime.

Add onRequestCloseWelcomeModal to the props destructuring:

         invalidProjectModalVisible,
         showWelcomeModal,
+        onRequestCloseWelcomeModal,
         vm,
         ...componentProps
     } = omit(props, 'dispatch');

Also applies to: 243-246

🤖 Prompt for AI Agents
In src/components/gui/gui.jsx around line 163 (and relevant usage at lines
243-246), the prop onRequestCloseWelcomeModal is referenced when rendering
<WelcomeModal> but not included in the component's props destructuring, causing
a ReferenceError; update the props destructuring at the top of the component to
include onRequestCloseWelcomeModal, and ensure the same exact prop name is
passed through to WelcomeModal where it’s used (lines ~243-246) so the handler
is defined at runtime.

onRequestCloseWelcomeModal,
vm,
...componentProps
} = omit(props, 'dispatch');
console.log('🎯 showWelcomeModal:', showWelcomeModal);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove debug console.log statement before merging to production.

const welcomeModalElement = showWelcomeModal ? (
<WelcomeModal onRequestClose={onRequestCloseWelcomeModal} />
) : null;
if (children) {
return <Box {...componentProps}>{children}</Box>;
}
Expand Down Expand Up @@ -238,6 +243,7 @@ const GUIComponent = props => {
{...componentProps}
>
{alwaysEnabledModals}

{telemetryModalVisible ? (
<TelemetryModal
isRtl={isRtl}
Expand Down Expand Up @@ -557,6 +563,8 @@ GUIComponent.propTypes = {
customExtensionModalVisible: PropTypes.bool,
fontsModalVisible: PropTypes.bool,
unknownPlatformModalVisible: PropTypes.bool,
showWelcomeModal: PropTypes.bool,
onRequestCloseWelcomeModal: PropTypes.func,
invalidProjectModalVisible: PropTypes.bool,
vm: PropTypes.instanceOf(VM).isRequired
};
Expand Down Expand Up @@ -591,6 +599,7 @@ const mapStateToProps = state => ({
blocksId: state.scratchGui.timeTravel.year.toString(),
stageSizeMode: state.scratchGui.stageSize.stageSize,
theme: state.scratchGui.theme.theme

});

export default injectIntl(connect(
Expand Down
71 changes: 71 additions & 0 deletions src/components/welcome-modal/addons-step.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.addons-step {
display: flex;
flex-direction: column;
height: 100%;
}

.header {
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 1.5rem;
}

.illustration-container {
flex-shrink: 0;
}

.illustration-placeholder {
font-size: 3rem;
padding: 1rem;
background: linear-gradient(135deg, #0FBD8C 0%, #0DA57A 100%);
border-radius: 12px;
color: white;
}

.header-text {
flex: 1;
text-align: left;
}

.title {
font-size: 2rem;
font-weight: 800;
margin: 0 0 0.5rem 0;
color: #333;
}

.subtitle {
font-size: 1.1rem;
color: #666;
margin: 0;
}

/* Iframe container */
.iframe-container {
flex: 1;
border: 2px solid #e0e0e0;
border-radius: 12px;
overflow: hidden;
background: white;
}

.addons-iframe {
width: 100%;
height: 100%;
border: none;
}

/* Footer */
.footer {
flex: 0 0 auto;
margin-top: 1rem;
text-align: center;
}

.footer-note {
margin: 0;
font-size: 0.9rem;
color: #999;
}
46 changes: 46 additions & 0 deletions src/components/welcome-modal/addons-step.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './addons-step.css';

const AddonsStep = () => (
<div className={styles.addonsStep}>
<div className={styles.header}>
<div className={styles.illustrationContainer}>
{/* Your SVG illustration goes here! */}
<div className={styles.illustrationPlaceholder}>
🧩 Your addons SVG illustration here!
</div>
</div>

<div className={styles.headerText}>
<h2 className={styles.title}>Set Up Your Addons 🧩</h2>
<p className={styles.subtitle}>
Customize OmniBlocks with powerful extensions
</p>
</div>
</div>

<div className={styles.iframeContainer}>
<iframe
className={styles.addonsIframe}
src="/addons"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Security Vulnerability: Iframe src="/addons" will fail in production. This path doesn't exist and creates a broken iframe that could be exploited.

Suggested change
src="/addons"
src={`${window.location.origin}/addons`}

title="Addons Setup"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-storage-access-by-user-activation"
/>
</div>

<div className={styles.footer}>
<p className={styles.footerNote}>
💡 Don't worry, you can change these anytime in Settings!
</p>
</div>
</div>
);

AddonsStep.propTypes = {
onNext: PropTypes.func,
isFirstStep: PropTypes.bool,
isLastStep: PropTypes.bool
};

export default AddonsStep;
110 changes: 110 additions & 0 deletions src/components/welcome-modal/final-step.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
.final-step {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
text-align: center;
}

.illustration-container {
flex: 0 0 auto;
margin-bottom: 2rem;
}

.illustration-placeholder {
font-size: 4rem;
padding: 2rem;
background: linear-gradient(135deg, #FFAB19 0%, #FF6B6B 100%);
border-radius: 16px;
color: white;
}

.content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}

.title {
font-size: 3rem;
font-weight: 900;
margin: 0 0 1rem 0;
color: #333;
}

.subtitle {
font-size: 1.25rem;
color: #666;
margin: 0 0 2rem 0;
}

/* Tips section */
.tips-section {
background: #f8f9fa;
border-radius: 12px;
padding: 1.5rem;
margin: 2rem auto;
max-width: 500px;
}

.tips-title {
font-size: 1.25rem;
font-weight: 700;
margin: 0 0 1rem 0;
color: #333;
}

.tips {
display: flex;
flex-direction: column;
gap: 0.75rem;
}

.tip {
display: flex;
align-items: center;
gap: 0.75rem;
text-align: left;
padding: 0.5rem;
}

.tip-icon {
font-size: 1.5rem;
flex-shrink: 0;
}

/* Celebration */
.celebration {
margin-top: 2rem;
display: flex;
gap: 1rem;
justify-content: center;
font-size: 2rem;
}

.emoji {
animation: bounce 1s infinite;
}

.emoji:nth-child(2) {
animation-delay: 0.1s;
}

.emoji:nth-child(3) {
animation-delay: 0.2s;
}

.emoji:nth-child(4) {
animation-delay: 0.3s;
}

@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
57 changes: 57 additions & 0 deletions src/components/welcome-modal/final-step.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './final-step.css';

const FinalStep = () => (
<div className={styles.finalStep}>
<div className={styles.illustrationContainer}>
{/* Your SVG illustration goes here! */}
<div className={styles.illustrationPlaceholder}>
🚀 Your final SVG illustration here!
</div>
</div>

<div className={styles.content}>
<h1 className={styles.title}>
You're All Set! 🎉
</h1>

<p className={styles.subtitle}>
Ready to start creating amazing projects?
</p>

<div className={styles.tipsSection}>
<h3 className={styles.tipsTitle}>Quick Tips 💡</h3>
<div className={styles.tips}>
<div className={styles.tip}>
<span className={styles.tipIcon}>⚙️</span>
<span>Access settings anytime from the menu bar</span>
</div>
<div className={styles.tip}>
<span className={styles.tipIcon}>📚</span>
<span>Check out tutorials to learn advanced features</span>
</div>
<div className={styles.tip}>
<span className={styles.tipIcon}>💾</span>
<span>Remember to save your projects regularly</span>
</div>
</div>
</div>

<div className={styles.celebration}>
<span className={styles.emoji}>🎊</span>
<span className={styles.emoji}>✨</span>
<span className={styles.emoji}>🎨</span>
<span className={styles.emoji}>🚀</span>
</div>
</div>
</div>
);

FinalStep.propTypes = {
onFinish: PropTypes.func,
isFirstStep: PropTypes.bool,
isLastStep: PropTypes.bool
};

export default FinalStep;
Loading
Loading