@@ -10,18 +10,24 @@ import Button from '../button/button.jsx';
1010import { ComingSoonTooltip } from '../coming-soon/coming-soon.jsx' ;
1111import Divider from '../divider/divider.jsx' ;
1212import LanguageSelector from '../../containers/language-selector.jsx' ;
13- import ProjectLoader from '../../containers/project-loader .jsx' ;
13+ import SBFileUploader from '../../containers/sb-file-uploader .jsx' ;
1414import MenuBarMenu from './menu-bar-menu.jsx' ;
1515import { MenuItem , MenuSection } from '../menu/menu.jsx' ;
1616import ProjectTitleInput from './project-title-input.jsx' ;
1717import AccountNav from '../../containers/account-nav.jsx' ;
1818import LoginDropdown from './login-dropdown.jsx' ;
19- import ProjectSaver from '../../containers/project-saver .jsx' ;
19+ import SB3Downloader from '../../containers/sb3-downloader .jsx' ;
2020import DeletionRestorer from '../../containers/deletion-restorer.jsx' ;
2121import TurboMode from '../../containers/turbo-mode.jsx' ;
2222
2323import { openTipsLibrary } from '../../reducers/modals' ;
2424import { setPlayer } from '../../reducers/mode' ;
25+ import {
26+ getIsUpdating ,
27+ getIsShowingProject ,
28+ requestNewProject ,
29+ saveProject
30+ } from '../../reducers/project-state' ;
2531import {
2632 openAccountMenu ,
2733 closeAccountMenu ,
@@ -123,42 +129,50 @@ class MenuBar extends React.Component {
123129 constructor ( props ) {
124130 super ( props ) ;
125131 bindAll ( this , [
132+ 'handleClickNew' ,
133+ 'handleClickSave' ,
134+ 'handleCloseFileMenuAndThen' ,
126135 'handleLanguageMouseUp' ,
127136 'handleRestoreOption' ,
128- 'handleCloseFileMenuAndThen' ,
129137 'restoreOptionMessage'
130138 ] ) ;
131- this . state = { projectSaveInProgress : false } ;
132139 }
133- handleLanguageMouseUp ( e ) {
134- if ( ! this . props . languageMenuOpen ) {
135- this . props . onClickLanguage ( e ) ;
140+ componentDidUpdate ( prevProps ) {
141+ // if we're no longer showing the project (loading, or whatever), close menus
142+ if ( this . props . isShowingProject && ! prevProps . isShowingProject ) {
143+ this . props . onRequestCloseFile ( ) ;
144+ this . props . onRequestCloseEdit ( ) ;
145+ }
146+ }
147+ handleClickNew ( ) {
148+ const canSave = this . props . canUpdateProject ; // logged in
149+ // if canSave===true, it's safe to replace current project, since we will auto-save first
150+ const readyToReplaceProject =
151+ canSave || confirm ( 'Replace contents of the current project?' ) ; // eslint-disable-line no-alert
152+ if ( readyToReplaceProject ) {
153+ this . props . onClickNew ( canSave ) ;
136154 }
137155 }
156+ handleClickSave ( ) {
157+ this . props . onClickSave ( ) ;
158+ }
138159 handleRestoreOption ( restoreFun ) {
139160 return ( ) => {
140161 restoreFun ( ) ;
141162 this . props . onRequestCloseEdit ( ) ;
142163 } ;
143164 }
144- handleUpdateProject ( updateFun ) {
145- return ( ) => {
146- this . props . onRequestCloseFile ( ) ;
147- this . setState ( { projectSaveInProgress : true } ,
148- ( ) => {
149- updateFun ( ) . then ( ( ) => {
150- this . setState ( { projectSaveInProgress : false } ) ;
151- } ) ;
152- }
153- ) ;
154- } ;
155- }
156165 handleCloseFileMenuAndThen ( fn ) {
157166 return ( ) => {
158167 this . props . onRequestCloseFile ( ) ;
159168 fn ( ) ;
160169 } ;
161170 }
171+ handleLanguageMouseUp ( e ) {
172+ if ( ! this . props . languageMenuOpen ) {
173+ this . props . onClickLanguage ( e ) ;
174+ }
175+ }
162176 restoreOptionMessage ( deletedItem ) {
163177 switch ( deletedItem ) {
164178 case 'Sprite' :
@@ -196,6 +210,13 @@ class MenuBar extends React.Component {
196210 id = "gui.menuBar.saveNow"
197211 />
198212 ) ;
213+ const newProjectMessage = (
214+ < FormattedMessage
215+ defaultMessage = "New"
216+ description = "Menu bar item for creating a new project"
217+ id = "gui.menuBar.new"
218+ />
219+ ) ;
199220 const shareButton = (
200221 < Button
201222 className = { classNames ( styles . shareButton ) }
@@ -210,9 +231,11 @@ class MenuBar extends React.Component {
210231 ) ;
211232 return (
212233 < Box
213- className = { classNames ( styles . menuBar , {
214- [ styles . saveInProgress ] : this . state . projectSaveInProgress
215- } ) }
234+ className = { classNames (
235+ this . props . className ,
236+ styles . menuBar ,
237+ { [ styles . saveInProgress ] : this . props . isUpdating }
238+ ) }
216239 >
217240 < div className = { styles . mainMenu } >
218241 < div className = { styles . fileGroup } >
@@ -262,33 +285,35 @@ class MenuBar extends React.Component {
262285 place = { this . props . isRtl ? 'left' : 'right' }
263286 onRequestClose = { this . props . onRequestCloseFile }
264287 >
265- < MenuItemTooltip
266- id = "new"
267- isRtl = { this . props . isRtl }
268- >
269- < MenuItem >
270- < FormattedMessage
271- defaultMessage = "New"
272- description = "Menu bar item for creating a new project"
273- id = "gui.menuBar.new"
274- />
288+ { /* for now, only enable New when there is no session */ }
289+ { this . props . sessionExists ? (
290+ < MenuItemTooltip
291+ id = "new"
292+ isRtl = { this . props . isRtl }
293+ >
294+ < MenuItem > { newProjectMessage } </ MenuItem >
295+ </ MenuItemTooltip >
296+ ) : (
297+ < MenuItem
298+ isRtl = { this . props . isRtl }
299+ onClick = { this . handleClickNew }
300+ >
301+ { newProjectMessage }
275302 </ MenuItem >
276- </ MenuItemTooltip >
303+ ) }
277304 < MenuSection >
278- < ProjectSaver > { ( saveProject , updateProject ) => (
279- this . props . canUpdateProject ? (
280- < MenuItem onClick = { this . handleUpdateProject ( updateProject ) } >
281- { saveNowMessage }
282- </ MenuItem >
283- ) : (
284- < MenuItemTooltip
285- id = "save"
286- isRtl = { this . props . isRtl }
287- >
288- < MenuItem > { saveNowMessage } </ MenuItem >
289- </ MenuItemTooltip >
290- )
291- ) } </ ProjectSaver >
305+ { this . props . canUpdateProject ? (
306+ < MenuItem onClick = { this . handleClickSave } >
307+ { saveNowMessage }
308+ </ MenuItem >
309+ ) : (
310+ < MenuItemTooltip
311+ id = "save"
312+ isRtl = { this . props . isRtl }
313+ >
314+ < MenuItem > { saveNowMessage } </ MenuItem >
315+ </ MenuItemTooltip >
316+ ) }
292317 < MenuItemTooltip
293318 id = "copy"
294319 isRtl = { this . props . isRtl }
@@ -303,30 +328,33 @@ class MenuBar extends React.Component {
303328 </ MenuItemTooltip >
304329 </ MenuSection >
305330 < MenuSection >
306- < ProjectLoader > { ( renderFileInput , loadProject , loadProps ) => (
307- < MenuItem
308- onClick = { loadProject }
309- { ...loadProps }
310- >
311- < FormattedMessage
312- defaultMessage = "Load from your computer"
313- description = "Menu bar item for uploading a project from your computer"
314- id = "gui.menuBar.uploadFromComputer"
315- />
316- { renderFileInput ( ) }
317- </ MenuItem >
318- ) } </ ProjectLoader >
319- < ProjectSaver > { saveProject => (
331+ < SBFileUploader >
332+ { ( renderFileInput , loadProject ) => (
333+ < MenuItem
334+ onClick = { loadProject }
335+ >
336+ < FormattedMessage
337+ defaultMessage = "Load from your computer"
338+ description = {
339+ 'Menu bar item for uploading a project from your computer'
340+ }
341+ id = "gui.menuBar.uploadFromComputer"
342+ />
343+ { renderFileInput ( ) }
344+ </ MenuItem >
345+ ) }
346+ </ SBFileUploader >
347+ < SB3Downloader > { downloadProject => (
320348 < MenuItem
321- onClick = { this . handleCloseFileMenuAndThen ( saveProject ) }
349+ onClick = { this . handleCloseFileMenuAndThen ( downloadProject ) }
322350 >
323351 < FormattedMessage
324352 defaultMessage = "Save to your computer"
325353 description = "Menu bar item for downloading a project to your computer"
326354 id = "gui.menuBar.downloadToComputer"
327355 />
328356 </ MenuItem >
329- ) } </ ProjectSaver >
357+ ) } </ SB3Downloader >
330358 </ MenuSection >
331359 </ MenuBarMenu >
332360 </ div >
@@ -588,18 +616,23 @@ class MenuBar extends React.Component {
588616MenuBar . propTypes = {
589617 accountMenuOpen : PropTypes . bool ,
590618 canUpdateProject : PropTypes . bool ,
619+ className : PropTypes . string ,
591620 editMenuOpen : PropTypes . bool ,
592621 enableCommunity : PropTypes . bool ,
593622 fileMenuOpen : PropTypes . bool ,
594623 intl : intlShape ,
595624 isRtl : PropTypes . bool ,
625+ isShowingProject : PropTypes . bool ,
626+ isUpdating : PropTypes . bool ,
596627 languageMenuOpen : PropTypes . bool ,
597628 loginMenuOpen : PropTypes . bool ,
598629 onClickAccount : PropTypes . func ,
599630 onClickEdit : PropTypes . func ,
600631 onClickFile : PropTypes . func ,
601632 onClickLanguage : PropTypes . func ,
602633 onClickLogin : PropTypes . func ,
634+ onClickNew : PropTypes . func ,
635+ onClickSave : PropTypes . func ,
603636 onLogOut : PropTypes . func ,
604637 onOpenRegistration : PropTypes . func ,
605638 onOpenTipLibrary : PropTypes . func ,
@@ -609,25 +642,32 @@ MenuBar.propTypes = {
609642 onRequestCloseLanguage : PropTypes . func ,
610643 onRequestCloseLogin : PropTypes . func ,
611644 onSeeCommunity : PropTypes . func ,
645+ onShare : PropTypes . func ,
612646 onToggleLoginOpen : PropTypes . func ,
613647 onUpdateProjectTitle : PropTypes . func ,
614648 renderLogin : PropTypes . func ,
615649 sessionExists : PropTypes . bool ,
650+ startSaving : PropTypes . func ,
616651 username : PropTypes . string
617652} ;
618653
619- const mapStateToProps = state => ( {
620- canUpdateProject : typeof ( state . session && state . session . session && state . session . session . user ) !== 'undefined' ,
621- accountMenuOpen : accountMenuOpen ( state ) ,
622- fileMenuOpen : fileMenuOpen ( state ) ,
623- editMenuOpen : editMenuOpen ( state ) ,
624- isRtl : state . locales . isRtl ,
625- languageMenuOpen : languageMenuOpen ( state ) ,
626- loginMenuOpen : loginMenuOpen ( state ) ,
627- sessionExists : state . session && typeof state . session . session !== 'undefined' ,
628- username : state . session && state . session . session && state . session . session . user ?
629- state . session . session . user . username : null
630- } ) ;
654+ const mapStateToProps = state => {
655+ const loadingState = state . scratchGui . projectState . loadingState ;
656+ const user = state . session && state . session . session && state . session . session . user ;
657+ return {
658+ accountMenuOpen : accountMenuOpen ( state ) ,
659+ canUpdateProject : typeof user !== 'undefined' ,
660+ fileMenuOpen : fileMenuOpen ( state ) ,
661+ editMenuOpen : editMenuOpen ( state ) ,
662+ isRtl : state . locales . isRtl ,
663+ isUpdating : getIsUpdating ( loadingState ) ,
664+ isShowingProject : getIsShowingProject ( loadingState ) ,
665+ languageMenuOpen : languageMenuOpen ( state ) ,
666+ loginMenuOpen : loginMenuOpen ( state ) ,
667+ sessionExists : state . session && typeof state . session . session !== 'undefined' ,
668+ username : user ? user . username : null
669+ } ;
670+ } ;
631671
632672const mapDispatchToProps = dispatch => ( {
633673 onOpenTipLibrary : ( ) => dispatch ( openTipsLibrary ( ) ) ,
@@ -641,7 +681,10 @@ const mapDispatchToProps = dispatch => ({
641681 onRequestCloseLanguage : ( ) => dispatch ( closeLanguageMenu ( ) ) ,
642682 onClickLogin : ( ) => dispatch ( openLoginMenu ( ) ) ,
643683 onRequestCloseLogin : ( ) => dispatch ( closeLoginMenu ( ) ) ,
644- onSeeCommunity : ( ) => dispatch ( setPlayer ( true ) )
684+ onClickNew : canSave => dispatch ( requestNewProject ( canSave ) ) ,
685+ onClickSave : ( ) => dispatch ( saveProject ( ) ) ,
686+ onSeeCommunity : ( ) => dispatch ( setPlayer ( true ) ) ,
687+ onShare : ( ) => { } // NOTE: implement this
645688} ) ;
646689
647690export default injectIntl ( connect (
0 commit comments