@@ -8,119 +8,68 @@ import Toolbar from './Toolbar';
8
8
import ConfigGen from './ConfigGen' ;
9
9
import styles from './BundleGenerator.css' ;
10
10
import c from '../../classjoin' ;
11
- import {
12
- getLoadedModules ,
13
- getRequireConfig ,
14
- getPageConfigType ,
15
- getURL ,
16
- } from '../../interop' ;
17
- import { ModulesByPageType , RequireConfig } from '../../types/require' ;
11
+ import { RequireConfig , PageModule } from '../../types/require' ;
18
12
import RecordingProgress from './RecordingProgress' ;
13
+ import PageCollector from './PageCollector' ;
19
14
20
15
type States = 'RECORDING' | 'RESULTS' | 'WELCOME' ;
21
16
type State = {
22
17
currentState : States ;
23
- modulesByPageType : ModulesByPageType ;
18
+ modulesByURL : { [ key : string ] : PageModule } ;
24
19
requireConfig : RequireConfig | null ;
25
20
} ;
26
21
27
- // TODO:
28
- // - Merge modules from multiple URLs with same layout handle, instead of taking the latest
29
- // - Track URLs, leave comments in `r.js` generated config
30
- // - Allow purging records for a visited URL. IOW, if you've visited 4 product pages, but
31
- // want to purge the results from 1 of them
32
- // - Support a user provided list of URLs to drive the browser too, instead of manual nav
33
- // for frequent users
34
22
export default class BundleGenerator extends React . Component < { } , State > {
35
23
state : State = {
36
- modulesByPageType : [ ] ,
24
+ modulesByURL : { } ,
37
25
currentState : 'WELCOME' ,
38
26
requireConfig : null ,
39
27
} ;
40
- timerID : number | null = null ;
28
+ collector : PageCollector = new PageCollector ( ) ;
41
29
42
30
onRecord = ( ) => {
43
31
this . setState ( ( { currentState } ) => {
44
- const isStop = currentState === 'RECORDING' ;
45
- isStop ? this . stopPolling ( ) : this . pollForModules ( ) ;
32
+ const shouldStopRecording = currentState === 'RECORDING' ;
33
+ shouldStopRecording ? this . stopPolling ( ) : this . pollForModules ( ) ;
46
34
return {
47
- currentState : isStop ? 'RESULTS' : 'RECORDING' ,
35
+ currentState : shouldStopRecording ? 'RESULTS' : 'RECORDING' ,
48
36
} ;
49
37
} ) ;
50
38
} ;
51
39
52
40
onClear = ( ) => {
53
41
this . setState ( {
54
42
currentState : 'WELCOME' ,
55
- modulesByPageType : [ ] ,
43
+ modulesByURL : { } ,
56
44
requireConfig : null ,
57
45
} ) ;
58
46
} ;
59
47
60
48
stopPolling ( ) {
61
- this . timerID && window . clearTimeout ( this . timerID ) ;
49
+ this . collector . unsubscribe ( this . collectorCallback ) ;
62
50
}
63
51
64
- // TODO: Abstract the body of this method outside of the component
65
- // and test it. Also clean it up because it's a mess
66
- pollForModules ( ) {
67
- this . timerID = window . setTimeout ( async ( ) => {
68
- try {
69
- const [
70
- modules ,
71
- requireConfig ,
72
- pageConfigType ,
73
- url ,
74
- ] = await Promise . all ( [
75
- getLoadedModules ( ) ,
76
- getRequireConfig ( ) ,
77
- getPageConfigType ( ) ,
78
- getURL ( ) ,
79
- ] ) ;
80
-
81
- // TODO: Actually handle this case, since it will point to a bug
82
- // in the shaky logic of `_getPageConfigType` in `interop.ts`
83
- if ( ! pageConfigType ) throw new Error ( 'No pageConfigType found' ) ;
84
-
85
- this . setState ( ( { modulesByPageType } ) => {
86
- const [ current ] = modulesByPageType . filter (
87
- m => m . pageConfigType === pageConfigType ,
88
- ) ;
89
- const mod = {
90
- url,
91
- pageConfigType,
92
- // TODO: Address this hack better. m2 has a bug where
93
- // a superfluous mixin is added to the Require registry for any
94
- // require() with a relative URL (./).
95
- modules : modules . filter ( m => ! m . startsWith ( 'mixins!' ) ) ,
96
- } ;
97
- current
98
- ? modulesByPageType . splice (
99
- modulesByPageType . indexOf ( current ) ,
100
- 1 ,
101
- mod ,
102
- )
103
- : modulesByPageType . push ( mod ) ;
104
-
105
- return {
106
- requireConfig,
107
- modulesByPageType,
108
- } ;
109
- } ) ;
110
- } catch ( err ) {
111
- console . error ( 'Failure in pollForModules()' , err ) ;
112
- }
52
+ collectorCallback = ( data : { page : PageModule ; config : RequireConfig } ) => {
53
+ const { page, config } = data ;
54
+ this . setState ( prevState => ( {
55
+ modulesByURL : {
56
+ ...prevState . modulesByURL ,
57
+ [ page . url ] : page ,
58
+ } ,
59
+ requireConfig : config ,
60
+ } ) ) ;
61
+ } ;
113
62
114
- this . pollForModules ( ) ;
115
- } , 200 ) ;
63
+ pollForModules ( ) {
64
+ this . collector . subscribe ( this . collectorCallback ) ;
116
65
}
117
66
118
67
componentWillUnmount ( ) {
119
68
this . stopPolling ( ) ;
120
69
}
121
70
122
71
render ( ) {
123
- const { currentState, modulesByPageType , requireConfig } = this . state ;
72
+ const { currentState, modulesByURL , requireConfig } = this . state ;
124
73
125
74
return (
126
75
< >
@@ -131,11 +80,11 @@ export default class BundleGenerator extends React.Component<{}, State> {
131
80
/>
132
81
{ currentState === 'WELCOME' && welcomeContent }
133
82
{ currentState === 'RECORDING' && (
134
- < RecordingProgress modulesByPageType = { modulesByPageType } />
83
+ < RecordingProgress modulesByURL = { modulesByURL } />
135
84
) }
136
85
{ currentState === 'RESULTS' && requireConfig && (
137
86
< ConfigGen
138
- modulesByPageType = { modulesByPageType }
87
+ pageModules = { Object . values ( modulesByURL ) }
139
88
requireConfig = { requireConfig }
140
89
/>
141
90
) }
0 commit comments