From 0dd4623523ea4ef39db068c65578a75c1ecddb1a Mon Sep 17 00:00:00 2001
From: Karishma Chadha <kchadha@scratch.mit.edu>
Date: Tue, 3 Jul 2018 23:03:09 -0400
Subject: [PATCH] Allow specifying variables as local vs. global. Pass var
 names from VM to scratch-blocks for checking for conflicts in all sprites
 when attempting to create a global var.

---
 src/components/prompt/prompt.css | 20 +++++--
 src/components/prompt/prompt.jsx | 89 +++++++++++++++++++++++++-------
 src/containers/blocks.jsx        |  9 +++-
 src/containers/prompt.jsx        | 12 ++++-
 4 files changed, 103 insertions(+), 27 deletions(-)

diff --git a/src/components/prompt/prompt.css b/src/components/prompt/prompt.css
index 34a8f5a21..78e3ecb27 100644
--- a/src/components/prompt/prompt.css
+++ b/src/components/prompt/prompt.css
@@ -15,7 +15,7 @@
     margin: 0 0 0.75rem;
 }
 
-.input {
+.variable-name-text-input {
     margin-bottom: 1.5rem;
     width: 100%;
     border: 1px solid $ui-black-transparent;
@@ -26,6 +26,20 @@
     font-size: .875rem;
 }
 
+.info-message {
+    font-weight: normal;
+    font-size: .875rem;
+    margin-bottom: 1.5rem;
+    text-align: center;
+}
+
+.options-row {
+    display: flex;
+    font-weight: normal;
+    justify-content: space-between;
+    margin-bottom: 1.5rem;
+}
+
 .button-row {
     font-weight: bolder;
     text-align: right;
@@ -58,10 +72,6 @@
     margin: 0 0 1rem;
 }
 
-.hide-more-options {
-    display: none;
-}
-
 .more-options-accordion {
     width: 60%;
     margin: 0 auto;
diff --git a/src/components/prompt/prompt.jsx b/src/components/prompt/prompt.jsx
index 4feffeb0c..20e6af85e 100644
--- a/src/components/prompt/prompt.jsx
+++ b/src/components/prompt/prompt.jsx
@@ -11,10 +11,26 @@ import styles from './prompt.css';
 import dropdownIcon from './icon--dropdown-caret.svg';
 
 const messages = defineMessages({
+    forAllSpritesMessage: {
+        defaultMessage: 'For all sprites',
+        description: 'Option message when creating a variable for making it available to all sprites',
+        id: 'gui.gui.variableScopeOptionAllSprites'
+    },
+    forThisSpriteMessage: {
+        defaultMessage: 'For this sprite only',
+        description: 'Option message when creating a varaible for making it only available to the current sprite',
+        id: 'gui.gui.variableScopeOptionSpriteOnly'
+    },
     moreOptionsMessage: {
         defaultMessage: 'More Options',
         description: 'Dropdown message for variable/list options',
         id: 'gui.gui.variablePrompt'
+    },
+    availableToAllSpritesMessage: {
+        defaultMessage: 'This variable will be available to all sprites.',
+        description: 'A message that displays in a variable modal when the stage is selected indicating ' +
+            'that the variable being created will available to all sprites.',
+        id: 'gui.gui.variablePromptAllSpritesMessage'
     }
 });
 
@@ -31,29 +47,64 @@ const PromptComponent = props => (
             <Box>
                 <input
                     autoFocus
-                    className={styles.input}
+                    className={styles.variableNameTextInput}
                     placeholder={props.placeholder}
                     onChange={props.onChange}
                     onKeyPress={props.onKeyPress}
                 />
             </Box>
-            <Box className={props.showMoreOptions ? styles.moreOptions : styles.hideMoreOptions}>
-                <ComingSoonTooltip
-                    className={styles.moreOptionsAccordion}
-                    place="right"
-                    tooltipId="variable-options-accordion"
-                >
-                    <div className={styles.moreOptionsText}>
-                        <FormattedMessage
-                            {...messages.moreOptionsMessage}
-                        />
-                        <img
-                            className={styles.moreOptionsIcon}
-                            src={dropdownIcon}
-                        />
-                    </div>
-                </ComingSoonTooltip>
-            </Box>
+            {props.showMoreOptions ?
+                <div>
+                    {props.isStage ?
+                        <div className={styles.infoMessage}>
+                            <FormattedMessage
+                                {...messages.availableToAllSpritesMessage}
+                            />
+                        </div> :
+                        <Box className={styles.optionsRow}>
+                            <label>
+                                <input
+                                    checked
+                                    name="variableScopeOption"
+                                    type="radio"
+                                    value="global"
+                                    onChange={props.onOptionSelection}
+                                />
+                                <FormattedMessage
+                                    {...messages.forAllSpritesMessage}
+                                />
+                            </label>
+                            <label>
+                                <input
+                                    name="variableScopeOption"
+                                    type="radio"
+                                    value="local"
+                                    onChange={props.onOptionSelection}
+                                />
+                                <FormattedMessage
+                                    {...messages.forThisSpriteMessage}
+                                />
+                            </label>
+                        </Box>}
+                    <Box className={styles.moreOptions}>
+                        <ComingSoonTooltip
+                            className={styles.moreOptionsAccordion}
+                            place="right"
+                            tooltipId="variable-options-accordion"
+                        >
+                            <div className={styles.moreOptionsText}>
+                                <FormattedMessage
+                                    {...messages.moreOptionsMessage}
+                                />
+                                <img
+                                    className={styles.moreOptionsIcon}
+                                    src={dropdownIcon}
+                                />
+                            </div>
+                        </ComingSoonTooltip>
+                    </Box>
+                </div> : null}
+
             <Box className={styles.buttonRow}>
                 <button
                     className={styles.cancelButton}
@@ -81,11 +132,13 @@ const PromptComponent = props => (
 );
 
 PromptComponent.propTypes = {
+    isStage: PropTypes.bool.isRequired,
     label: PropTypes.string.isRequired,
     onCancel: PropTypes.func.isRequired,
     onChange: PropTypes.func.isRequired,
     onKeyPress: PropTypes.func.isRequired,
     onOk: PropTypes.func.isRequired,
+    onOptionSelection: PropTypes.func.isRequired,
     placeholder: PropTypes.string,
     showMoreOptions: PropTypes.bool.isRequired,
     title: PropTypes.string.isRequired
diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx
index 1b411d633..f9db7468b 100644
--- a/src/containers/blocks.jsx
+++ b/src/containers/blocks.jsx
@@ -322,12 +322,16 @@ class Blocks extends React.Component {
         const p = {prompt: {callback, message, defaultValue}};
         p.prompt.title = optTitle ? optTitle :
             this.ScratchBlocks.VARIABLE_MODAL_TITLE;
+        p.prompt.varType = typeof optVarType === 'string' ?
+            optVarType : this.ScratchBlocks.SCALAR_VARIABLE_TYPE;
         p.prompt.showMoreOptions =
             optVarType !== this.ScratchBlocks.BROADCAST_MESSAGE_VARIABLE_TYPE;
         this.setState(p);
     }
-    handlePromptCallback (data) {
-        this.state.prompt.callback(data);
+    handlePromptCallback (input, optionSelection) {
+        this.state.prompt.callback(input, optionSelection,
+            (optionSelection === 'local') ? [] :
+                this.props.vm.runtime.getAllVarNamesOfType(this.state.prompt.varType));
         this.handlePromptClose();
     }
     handlePromptClose () {
@@ -366,6 +370,7 @@ class Blocks extends React.Component {
                 />
                 {this.state.prompt ? (
                     <Prompt
+                        isStage={vm.runtime.getEditingTarget().isStage}
                         label={this.state.prompt.message}
                         placeholder={this.state.prompt.defaultValue}
                         showMoreOptions={this.state.prompt.showMoreOptions}
diff --git a/src/containers/prompt.jsx b/src/containers/prompt.jsx
index a798b02ed..72c8ad8a3 100644
--- a/src/containers/prompt.jsx
+++ b/src/containers/prompt.jsx
@@ -8,19 +8,21 @@ class Prompt extends React.Component {
         super(props);
         bindAll(this, [
             'handleOk',
+            'handleOptionSelection',
             'handleCancel',
             'handleChange',
             'handleKeyPress'
         ]);
         this.state = {
-            inputValue: ''
+            inputValue: '',
+            optionSelection: null
         };
     }
     handleKeyPress (event) {
         if (event.key === 'Enter') this.handleOk();
     }
     handleOk () {
-        this.props.onOk(this.state.inputValue);
+        this.props.onOk(this.state.inputValue, this.state.optionSelection);
     }
     handleCancel () {
         this.props.onCancel();
@@ -28,9 +30,13 @@ class Prompt extends React.Component {
     handleChange (e) {
         this.setState({inputValue: e.target.value});
     }
+    handleOptionSelection (e) {
+        this.setState({optionSelection: e.target.value});
+    }
     render () {
         return (
             <PromptComponent
+                isStage={this.props.isStage}
                 label={this.props.label}
                 placeholder={this.props.placeholder}
                 showMoreOptions={this.props.showMoreOptions}
@@ -39,12 +45,14 @@ class Prompt extends React.Component {
                 onChange={this.handleChange}
                 onKeyPress={this.handleKeyPress}
                 onOk={this.handleOk}
+                onOptionSelection={this.handleOptionSelection}
             />
         );
     }
 }
 
 Prompt.propTypes = {
+    isStage: PropTypes.bool.isRequired,
     label: PropTypes.string.isRequired,
     onCancel: PropTypes.func.isRequired,
     onOk: PropTypes.func.isRequired,
-- 
GitLab