1
1
import { ipcRenderer , shell } from 'electron' ;
2
+ import bindAll from 'lodash.bindall' ;
3
+ import PropTypes from 'prop-types' ;
2
4
import React from 'react' ;
3
5
import ReactDOM from 'react-dom' ;
4
- import GUI , { AppStateHOC } from 'scratch-gui' ;
6
+ import { compose } from 'redux' ;
7
+ import GUI , { AppStateHOC , TitledHOC } from 'scratch-gui' ;
5
8
6
9
import ElectronStorageHelper from '../common/ElectronStorageHelper' ;
7
10
@@ -23,27 +26,69 @@ appTarget.className = styles.app || 'app'; // TODO
23
26
document . body . appendChild ( appTarget ) ;
24
27
25
28
GUI . setAppElement ( appTarget ) ;
26
- const WrappedGui = AppStateHOC ( GUI ) ;
27
29
28
- const onStorageInit = storageInstance => {
29
- storageInstance . addHelper ( new ElectronStorageHelper ( storageInstance ) ) ;
30
- // storageInstance.addOfficialScratchWebStores(); // TODO: do we want this?
31
- } ;
32
-
33
- const guiProps = {
34
- onStorageInit,
35
- isScratchDesktop : true ,
36
- projectId : defaultProjectId ,
37
- showTelemetryModal : ( typeof ipcRenderer . sendSync ( 'getTelemetryDidOptIn' ) ) !== 'boolean' ,
38
- onTelemetryModalOptIn : ( ) => {
39
- ipcRenderer . send ( 'setTelemetryDidOptIn' , true ) ;
40
- } ,
41
- onTelemetryModalOptOut : ( ) => {
42
- ipcRenderer . send ( 'setTelemetryDidOptIn' , false ) ;
43
- } ,
44
- onProjectTelemetryEvent : ( event , metadata ) => {
45
- ipcRenderer . send ( event , metadata ) ;
30
+ const ScratchDesktopHOC = function ( WrappedComponent ) {
31
+ class ScratchDesktopComponent extends React . Component {
32
+ constructor ( props ) {
33
+ super ( props ) ;
34
+ bindAll ( this , [
35
+ 'handleProjectTelemetryEvent' ,
36
+ 'handleSetTitleFromSave' ,
37
+ 'handleStorageInit' ,
38
+ 'handleTelemetryModalOptIn' ,
39
+ 'handleTelemetryModalOptOut'
40
+ ] ) ;
41
+ }
42
+ componentDidMount ( ) {
43
+ ipcRenderer . on ( 'setTitleFromSave' , this . handleSetTitleFromSave ) ;
44
+ }
45
+ componentWillUnmount ( ) {
46
+ ipcRenderer . removeListener ( 'setTitleFromSave' , this . handleSetTitleFromSave ) ;
47
+ }
48
+ handleProjectTelemetryEvent ( event , metadata ) {
49
+ ipcRenderer . send ( event , metadata ) ;
50
+ }
51
+ handleSetTitleFromSave ( event , args ) {
52
+ this . props . onUpdateProjectTitle ( args . title ) ;
53
+ }
54
+ handleStorageInit ( storageInstance ) {
55
+ storageInstance . addHelper ( new ElectronStorageHelper ( storageInstance ) ) ;
56
+ }
57
+ handleTelemetryModalOptIn ( ) {
58
+ ipcRenderer . send ( 'setTelemetryDidOptIn' , true ) ;
59
+ }
60
+ handleTelemetryModalOptOut ( ) {
61
+ ipcRenderer . send ( 'setTelemetryDidOptIn' , false ) ;
62
+ }
63
+ render ( ) {
64
+ const shouldShowTelemetryModal = ( typeof ipcRenderer . sendSync ( 'getTelemetryDidOptIn' ) !== 'boolean' ) ;
65
+ return ( < WrappedComponent
66
+ isScratchDesktop
67
+ projectId = { defaultProjectId }
68
+ showTelemetryModal = { shouldShowTelemetryModal }
69
+ onProjectTelemetryEvent = { this . handleProjectTelemetryEvent }
70
+ onStorageInit = { this . handleStorageInit }
71
+ onTelemetryModalOptIn = { this . handleTelemetryModalOptIn }
72
+ onTelemetryModalOptOut = { this . handleTelemetryModalOptOut }
73
+ { ...this . props }
74
+ /> ) ;
75
+ }
46
76
}
77
+
78
+ ScratchDesktopComponent . propTypes = {
79
+ onUpdateProjectTitle : PropTypes . func
80
+ } ;
81
+
82
+ return ScratchDesktopComponent ;
47
83
} ;
48
- const wrappedGui = React . createElement ( WrappedGui , guiProps ) ;
49
- ReactDOM . render ( wrappedGui , appTarget ) ;
84
+
85
+ // note that redux's 'compose' function is just being used as a general utility to make
86
+ // the hierarchy of HOC constructor calls clearer here; it has nothing to do with redux's
87
+ // ability to compose reducers.
88
+ const WrappedGui = compose (
89
+ AppStateHOC ,
90
+ TitledHOC ,
91
+ ScratchDesktopHOC // must come after `TitledHOC` so it has access to `onUpdateProjectTitle`
92
+ ) ( GUI ) ;
93
+
94
+ ReactDOM . render ( < WrappedGui /> , appTarget ) ;
0 commit comments