@@ -15,11 +15,16 @@ func playgroundComponent(props react.Props) *react.Element {
1515 code , setCode = react .UseState (`` )
1616 shareHash , setShareHash = react .UseState (`` )
1717 output , setOutput = react .UseState ([]any {})
18- runButtonRef = react .UseRef ( )
18+ asyncOpInProgress = react .UseRefWith ( false )
1919 )
2020
2121 // readSnippet reads a snippet or shared code from the store based on the given hash.
2222 readSnippet := react .UseCallback (func (hash string ) {
23+ if asyncOpInProgress .Current () {
24+ return
25+ }
26+
27+ asyncOpInProgress .SetCurrent (true )
2328 globals .SnippetsStore ().Read (hash , func (snippet string , err error ) {
2429 o := Output (setOutput )
2530 o .Clear ()
@@ -31,8 +36,16 @@ func playgroundComponent(props react.Props) *react.Element {
3136 }
3237 // even on error, set the code so the default code is shown.
3338 setCode .Invoke (snippet )
39+ asyncOpInProgress .SetCurrent (false )
3440 })
35- }, []any {setCode , setShareHash , setOutput })
41+ }, []any {setCode , setShareHash , setOutput , asyncOpInProgress })
42+
43+ // This is emitted once on component mount to read the initial snippet
44+ // and set the initial code based on the url hash or set to the default code.
45+ react .UseEffect (func () {
46+ hash := getUrlHash ()
47+ readSnippet .Invoke (hash )
48+ }, []any {})
3649
3750 // This callback is invoked when the top window's URL hash changes.
3851 // When the window's URL hash changed before the share hash state,
@@ -58,24 +71,31 @@ func playgroundComponent(props react.Props) *react.Element {
5871 setUrlHash (shareHash )
5972 }, []any {shareHash })
6073
61- // This clears the share hash when the code changes.
62- react .UseEffect (func () {
74+ // onUserChangedCode is called by the code box to clear the share hash
75+ // when the user changes the code.
76+ onUserChangedCode := react .UseCallback (func () {
6377 setShareHash .Invoke (`` )
64- }, []any {code })
78+ }, []any {setShareHash })
6579
6680 // onShare writes the code to the store when the share button is clicked.
6781 onShare := react .UseCallback (func () {
68- globals .SnippetsStore ().Write (code , func (url string , err error ) {
82+ if asyncOpInProgress .Current () {
83+ return
84+ }
85+
86+ asyncOpInProgress .SetCurrent (true )
87+ globals .SnippetsStore ().Write (code , func (hash string , err error ) {
6988 output := Output (setOutput )
7089 output .Clear ()
7190 if err != nil {
7291 output .AddError (err )
7392 setShareHash .Invoke (`` )
7493 return
7594 }
76- setShareHash .Invoke (url )
95+ setShareHash .Invoke (hash )
96+ asyncOpInProgress .SetCurrent (false )
7797 })
78- }, []any {code , setOutput , setShareHash })
98+ }, []any {code , setOutput , setShareHash , asyncOpInProgress })
7999
80100 // onSnippetSelected performs a read when a predefined snippet is selected from the drop down.
81101 onSnippetSelected := react .UseCallback (func (selection string ) {
@@ -89,10 +109,13 @@ func playgroundComponent(props react.Props) *react.Element {
89109 // like they would be able to with tab stops but our editor is consuming
90110 // tab key presses so tab stops won't work when in the text area.
91111 onEscapeCode := react .UseCallback (func () {
92- runButtonRef .Current ().Call (`focus` )
93- }, []any {runButtonRef })
112+ runButton := js .Global .Get (`document` ).Call (`querySelector` , `#run-button` )
113+ if runButton != js .Undefined && runButton != nil {
114+ runButton .Call (`focus` )
115+ }
116+ }, []any {})
94117
95- onSaveKeyPress := react .UseCallback (func () {
118+ onSave := react .UseCallback (func () {
96119 println ("Save key pressed" ) // TODO(grantnelson-wf): Implement by running format or just do nothing?
97120 }, []any {})
98121
@@ -105,26 +128,12 @@ func playgroundComponent(props react.Props) *react.Element {
105128 }, []any {})
106129
107130 return react .Fragment (
108- Banner (runButtonRef , shareHash , onRun , onFormat , onShare , onSnippetSelected ),
131+ Banner (shareHash , onRun , onFormat , onShare , onSnippetSelected ),
109132 react .Div (react.Props {
110133 `id` : `code-output-box` ,
111134 },
112- CodeBox (code , setCode , onSaveKeyPress , onEscapeCode ),
135+ CodeBox (code , setCode , onUserChangedCode , onSave , onEscapeCode ),
113136 OutputBox (output ),
114137 ),
115138 )
116139}
117-
118- func getTopWindow () * js.Object { return js .Global .Get (`window` ).Get (`top` ) }
119- func getLocation () * js.Object { return getTopWindow ().Get (`location` ) }
120-
121- func getUrlHash () string { return getLocation ().Get (`hash` ).String () }
122- func setUrlHash (hash string ) { getLocation ().Set (`hash` , hash ) }
123-
124- func addEventListener (event string , handler react.Func ) {
125- getTopWindow ().Call (`addEventListener` , event , handler )
126- }
127-
128- func removeEventListener (event string , handler react.Func ) {
129- getTopWindow ().Call (`removeEventListener` , event , handler )
130- }
0 commit comments