@@ -14,53 +14,21 @@ func Playground() *react.Element {
1414func playgroundComponent (props react.Props ) * react.Element {
1515 var (
1616 code , setCode = react .UseState (`` )
17- shareUrl , setShareUrl = react .UseState (`` )
17+ urlHash , setUrlHash = react .UseState (`` )
1818 output , setOutput = react .UseState ([]any {})
1919 fmtImports , setFmtImports = react .UseState (true )
2020 lightTheme , setLightTheme = react .UseStateLazy (getDefaultToLightTheme )
2121 runButtonRef = react .UseRef ()
22- isLoadingSnippet = react .UseRef ()
23- settingUrlHash = react .UseRef ()
2422 )
2523
2624 react .UseEffect (func () {
2725 setDataTheme (lightTheme )
2826 }, []any {lightTheme })
2927
30- react .UseEffect (func () {
31- if isLoadingSnippet .Current ().Bool () {
32- isLoadingSnippet .SetCurrent (false )
33- return
34- }
35-
36- // code changed so clear share URL
37- settingUrlHash .SetCurrent (true )
38- setShareUrl .Invoke (`` )
39- getLocation ().Set (`hash` , `` )
40- }, []any {code })
41-
28+ // Add an effect to listen for the window's URL hash changing.
4229 react .UseEffectWithCleanup (func () func () {
4330 hashChanged := func () {
44- // if the hash is being set programmatically, ignore this event
45- if settingUrlHash .Current ().Bool () {
46- settingUrlHash .SetCurrent (false )
47- return
48- }
49-
50- hash := getLocation ().Get (`hash` ).String ()
51- isLoadingSnippet .SetCurrent (true )
52- globals .SnippetsStore ().Read (hash , func (snippet string , err error ) {
53- o := Output (setOutput )
54- o .Clear ()
55- if err != nil {
56- setShareUrl .Invoke (`` )
57- o .AddError (err )
58- } else {
59- setShareUrl .Invoke (hash )
60- }
61- // even on error, set the code so the default code is shown.
62- setCode .Invoke (snippet )
63- })
31+ setUrlHash .Invoke (getLocation ().Get (`hash` ).String ())
6432 }
6533 getTopWindow ().Call (`addEventListener` , `hashchange` , hashChanged )
6634 hashChanged () // Load initial hash
@@ -69,12 +37,55 @@ func playgroundComponent(props react.Props) *react.Element {
6937 }
7038 }, []any {})
7139
40+ // Add an effect to update the window's URL hash when the URL hash state has changed.
41+ react .UseEffect (func () {
42+ getLocation ().Set (`hash` , urlHash )
43+ }, []any {urlHash })
44+
45+ // Add an effect to load a snippet or shared code when the URL hash changes.
46+ react .UseEffect (func () {
47+ globals .SnippetsStore ().Read (urlHash , func (snippet string , err error ) {
48+ o := Output (setOutput )
49+ o .Clear ()
50+ if err != nil {
51+ o .AddError (err )
52+ }
53+ // even on error, set the code so the default code is shown.
54+ setCode .Invoke (snippet )
55+ })
56+ }, []any {urlHash })
57+
58+ // Add an effect to clear the URL hash when the code changes.
59+ react .UseEffect (func () {
60+ setUrlHash .Invoke (`` )
61+ }, []any {code })
62+
63+ // Create a callback for when the share button is clicked.
64+ onShareClick := react .UseCallback (func () {
65+ globals .SnippetsStore ().Write (code , func (url string , err error ) {
66+ output := Output (setOutput )
67+ output .Clear ()
68+ if err != nil {
69+ output .AddError (err )
70+ setUrlHash .Invoke (`` )
71+ return
72+ }
73+ setUrlHash .Invoke (url )
74+ })
75+ }, []any {code , setOutput , setUrlHash })
76+
77+ // Create a callback for when a predefined snippet is selected from the drop down.
78+ onSnippetSelected := react .UseCallback (func (selection string ) {
79+ setUrlHash .Invoke (`#` + selection )
80+ }, []any {setUrlHash })
81+
82+ // Create a callback for when the escape key is pressed in the code box.
83+ // Escape will move focus to the run button.
84+ // This is for eccessability so that users can easily run the
85+ // code after editing. Or at minimum, users can exit the text area
86+ // like they would be able to with tab stops but our editor is consuming
87+ // tab key presses so tab stops won't work when in the text area.
7288 onEscapeCode := react .UseCallback (func () {
73- // Escape will move focus to the run button.
74- // This is for eccessability so that users can easily run the
75- // code after editing. Or at minimum, users can exit the text area
76- // like they would be able to with tab stops but our editor is consuming
77- // tab key presses so tab stops won't work when in the text area.
7889 runButtonRef .Current ().Call (`focus` )
7990 }, []any {runButtonRef })
8091
@@ -90,22 +101,6 @@ func playgroundComponent(props react.Props) *react.Element {
90101 println ("Format clicked" , fmtImports ) // TODO(grantnelson-wf): Implement
91102 }, []any {fmtImports })
92103
93- onShareClick := react .UseCallback (func () {
94- globals .SnippetsStore ().Write (code , func (url string , err error ) {
95- settingUrlHash .SetCurrent (true )
96- output := Output (setOutput )
97- output .Clear ()
98- if err != nil {
99- setShareUrl .Invoke (`` )
100- getLocation ().Set (`hash` , `` )
101- output .AddError (err )
102- return
103- }
104- setShareUrl .Invoke (url )
105- getLocation ().Set (`hash` , url )
106- })
107- }, []any {code , setOutput , setShareUrl })
108-
109104 return react .Fragment (
110105 react .Div (react.Props {
111106 `id` : `banner` ,
@@ -117,8 +112,7 @@ func playgroundComponent(props react.Props) *react.Element {
117112 react .Button (`run-button` , `Run` , react.Props {`ref` : runButtonRef }, onRunClick ),
118113 react .Button (`format-button` , `Format` , nil , onFormatClick ),
119114 ToggleBox (`format-imports` , `Rewrite imports on Format` , `Imports` , fmtImports , setFmtImports ),
120- ShareUrlControl (shareUrl , onShareClick ),
121- // TODO(grantnelson-wf): Add a Snippet selection control / dropdown for loading predefined snippets.
115+ ShareUrlControl (urlHash , onShareClick , onSnippetSelected ),
122116 ToggleBox (`color-theme` , `Change color-theme` , `` , lightTheme , setLightTheme ),
123117 ),
124118 ),
0 commit comments