Skip to content

Commit 8ab95ac

Browse files
cleared up some URL interactions
1 parent 51f200c commit 8ab95ac

5 files changed

Lines changed: 188 additions & 130 deletions

File tree

playground/internal/react/bindings.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,16 +243,12 @@ func (r *Ref) Current() *js.Object {
243243
panic(ErrRefNotInitialized)
244244
}
245245

246-
func (r *Ref) Get(key string) *js.Object {
247-
return r.Current().Get(key)
248-
}
249-
250-
func (r *Ref) Set(key string, value any) {
251-
r.Current().Set(key, value)
252-
}
253-
254-
func (r *Ref) Call(name string, args ...any) {
255-
r.Current().Call(name, args...)
246+
func (r *Ref) SetCurrent(value any) {
247+
if r != nil && r.holder != nil {
248+
r.holder.Set(`current`, value)
249+
return
250+
}
251+
panic(ErrRefNotInitialized)
256252
}
257253

258254
// UseEffect registers an effect function that is called after rendering.

playground/internal/react/codeBox.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func codeBoxComponent(props Props) *Element {
5555

5656
onScroll := UseCallback(func(e *js.Object) {
5757
scrollTop := e.Get(`target`).Get(`scrollTop`).Int()
58-
lineNumsRef.Set(`scrollTop`, scrollTop)
58+
lineNumsRef.Current().Set(`scrollTop`, scrollTop)
5959
}, []any{lineNumsRef})
6060

6161
onSelect := UseCallback(func(e *js.Object) {
@@ -69,7 +69,7 @@ func codeBoxComponent(props Props) *Element {
6969

7070
UseEffect(func() {
7171
// On first render, focus the code textarea.
72-
textAreaRef.Call(`focus`)
72+
textAreaRef.Current().Call(`focus`)
7373
setSelection(textAreaRef, common.Selection{})
7474
}, []any{})
7575

@@ -151,7 +151,7 @@ func (cba *codeBoxAssistant) SetCode(sel common.Selection, code string) {
151151

152152
// Pre-update the textarea value so that the caret and scroll can be set
153153
// correctly before the next render so that the next render doesn't reset them.
154-
cba.textAreaRef.Set(`value`, code)
154+
cba.textAreaRef.Current().Set(`value`, code)
155155

156156
// Match the diretionallity of the prior selection.
157157
if getSelection(cba.textAreaRef).Reversed() {
@@ -167,8 +167,9 @@ func (cba *codeBoxAssistant) SetCode(sel common.Selection, code string) {
167167
}
168168

169169
func verticallyAutoScroll(textAreaRef *Ref, caret int, code string) {
170-
totalHeight := textAreaRef.Get(`scrollHeight`).Int()
171-
visibleHeight := textAreaRef.Get(`clientHeight`).Int()
170+
textArea := textAreaRef.Current()
171+
totalHeight := textArea.Get(`scrollHeight`).Int()
172+
visibleHeight := textArea.Get(`clientHeight`).Int()
172173
if totalHeight <= visibleHeight {
173174
return // No vertical scrolling needed.
174175
}
@@ -177,17 +178,18 @@ func verticallyAutoScroll(textAreaRef *Ref, caret int, code string) {
177178
curLine := strings.Count(code[:caret], "\n") + 1
178179
scrollTop := int(float64(curLine) * float64(totalHeight) / float64(lineCount))
179180

180-
curTop := textAreaRef.Get(`scrollTop`).Int()
181+
curTop := textArea.Get(`scrollTop`).Int()
181182
if scrollTop < curTop {
182-
textAreaRef.Set(`scrollTop`, scrollTop)
183+
textArea.Set(`scrollTop`, scrollTop)
183184
} else if scrollTop -= visibleHeight; scrollTop > curTop {
184-
textAreaRef.Set(`scrollTop`, scrollTop)
185+
textArea.Set(`scrollTop`, scrollTop)
185186
}
186187
}
187188

188189
func horizontallyAutoScroll(textAreaRef *Ref, caret int, code string) {
189-
totalWidth := textAreaRef.Get(`scrollWidth`).Int()
190-
visibleWidth := textAreaRef.Get(`clientWidth`).Int()
190+
textArea := textAreaRef.Current()
191+
totalWidth := textArea.Get(`scrollWidth`).Int()
192+
visibleWidth := textArea.Get(`clientWidth`).Int()
191193
if totalWidth <= visibleWidth {
192194
return // No horizontal scrolling needed.
193195
}
@@ -197,24 +199,26 @@ func horizontallyAutoScroll(textAreaRef *Ref, caret int, code string) {
197199
curLine := editor.MeasureLineLength(code[par:caret])
198200
scrollLeft := int(float64(curLine) * float64(totalWidth) / float64(longestLine))
199201

200-
curLeft := textAreaRef.Get(`scrollLeft`).Int()
202+
curLeft := textArea.Get(`scrollLeft`).Int()
201203
if scrollLeft < curLeft {
202-
textAreaRef.Set(`scrollLeft`, scrollLeft)
204+
textArea.Set(`scrollLeft`, scrollLeft)
203205
} else if scrollLeft -= visibleWidth; scrollLeft > curLeft {
204-
textAreaRef.Set(`scrollLeft`, scrollLeft)
206+
textArea.Set(`scrollLeft`, scrollLeft)
205207
}
206208
}
207209

208210
func getSelection(textAreaRef *Ref) common.Selection {
209-
start := textAreaRef.Get(`selectionStart`).Int()
210-
end := textAreaRef.Get(`selectionEnd`).Int()
211+
textArea := textAreaRef.Current()
212+
start := textArea.Get(`selectionStart`).Int()
213+
end := textArea.Get(`selectionEnd`).Int()
211214
return common.Selection{Start: start, End: end}
212215
}
213216

214217
// setSelection sets the selection on the given textarea ref.
215218
func setSelection(textAreaRef *Ref, sel common.Selection) {
216-
textAreaRef.Set(`selectionStart`, sel.Start)
217-
textAreaRef.Set(`selectionEnd`, sel.End)
219+
textArea := textAreaRef.Current()
220+
textArea.Set(`selectionStart`, sel.Start)
221+
textArea.Set(`selectionEnd`, sel.End)
218222
}
219223

220224
func getLineNumbers(lineCount int) string {

playground/internal/react/playground.go

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package react
22

33
import (
4-
"fmt"
5-
64
"github.com/gopherjs/gopherjs/compiler"
75
"github.com/gopherjs/gopherjs/js"
86
)
@@ -19,45 +17,63 @@ func playgroundComponent(props Props) *Element {
1917
fmtImports, setFmtImports = UseState(true)
2018
lightTheme, setLightTheme = UseStateLazy(getDefaultToLightTheme)
2119
runButtonRef = UseRef()
20+
isLoadingSnippet = UseRef()
21+
settingUrlHash = UseRef()
2222
)
2323

2424
UseEffect(func() {
2525
setDataTheme(lightTheme)
2626
}, []any{lightTheme})
2727

2828
UseEffect(func() {
29+
if isLoadingSnippet.Current().Bool() {
30+
isLoadingSnippet.SetCurrent(false)
31+
return
32+
}
33+
2934
// code changed so clear share URL
35+
settingUrlHash.SetCurrent(true)
3036
setShareUrl.Invoke(``)
3137
getLocation().Set(`hash`, ``)
3238
}, []any{code})
3339

34-
UseEffect(func() {
35-
hash := getLocation().Get(`hash`).String()
36-
globals.SnippetsStore().Read(hash, func(snippet string, err error) {
37-
if err != nil {
40+
UseEffectWithCleanup(func() func() {
41+
hashChanged := func() {
42+
// if the hash is being set programmatically, ignore this event
43+
if settingUrlHash.Current().Bool() {
44+
settingUrlHash.SetCurrent(false)
45+
return
46+
}
47+
48+
hash := getLocation().Get(`hash`).String()
49+
isLoadingSnippet.SetCurrent(true)
50+
globals.SnippetsStore().Read(hash, func(snippet string, err error) {
3851
o := Output(setOutput)
3952
o.Clear()
40-
o.AddError(err)
41-
}
42-
// even on error, set the code so the default code is shown.
43-
setCode.Invoke(snippet)
44-
})
53+
if err != nil {
54+
setShareUrl.Invoke(``)
55+
o.AddError(err)
56+
} else {
57+
setShareUrl.Invoke(hash)
58+
}
59+
// even on error, set the code so the default code is shown.
60+
setCode.Invoke(snippet)
61+
})
62+
}
63+
getTopWindow().Call(`addEventListener`, `hashchange`, hashChanged)
64+
hashChanged() // Load initial hash
65+
return func() {
66+
getTopWindow().Call(`removeEventListener`, `hashchange`, hashChanged)
67+
}
4568
}, []any{})
4669

47-
/* TODO(grantnelson-wf): Implement hashchange loading
48-
dom.GetWindow().Top().AddEventListener("hashchange", false, func(event dom.Event) {
49-
event.PreventDefault()
50-
callback()
51-
})
52-
*/
53-
5470
onEscapeCode := UseCallback(func() {
5571
// Escape will move focus to the run button.
5672
// This is for eccessability so that users can easily run the
5773
// code after editing. Or at minimum, users can exit the text area
5874
// like they would be able to with tab stops but our editor is consuming
5975
// tab key presses so tab stops won't work when in the text area.
60-
runButtonRef.Call(`focus`)
76+
runButtonRef.Current().Call(`focus`)
6177
}, []any{runButtonRef})
6278

6379
onSaveKeyPress := UseCallback(func() {
@@ -73,16 +89,18 @@ func playgroundComponent(props Props) *Element {
7389
}, []any{fmtImports})
7490

7591
onShareClick := UseCallback(func() {
76-
fmt.Printf(">> Code to share: %q\n", code) // TODO(grantnelson-wf): REMOVE
7792
globals.SnippetsStore().Write(code, func(url string, err error) {
93+
settingUrlHash.SetCurrent(true)
94+
output := Output(setOutput)
95+
output.Clear()
7896
if err != nil {
7997
setShareUrl.Invoke(``)
80-
output := Output(setOutput)
81-
output.Clear()
98+
getLocation().Set(`hash`, ``)
8299
output.AddError(err)
83100
return
84101
}
85102
setShareUrl.Invoke(url)
103+
getLocation().Set(`hash`, url)
86104
})
87105
}, []any{code, setOutput, setShareUrl})
88106

@@ -127,6 +145,10 @@ func setDataTheme(lightTheme bool) {
127145
js.Global.Get(`document`).Get(`documentElement`).Call(`setAttribute`, `data-theme`, theme)
128146
}
129147

148+
func getTopWindow() *js.Object {
149+
return js.Global.Get(`window`).Get(`top`)
150+
}
151+
130152
func getLocation() *js.Object {
131-
return js.Global.Get(`window`).Get(`top`).Get(`location`)
153+
return getTopWindow().Get(`location`)
132154
}

playground/internal/react/shareUrlControl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func shareUrlComponent(props Props) *Element {
1818

1919
UseEffect(func() {
2020
if len(shareUrl) > 0 {
21-
shareUrlRef.Call(`focus`)
21+
shareUrlRef.Current().Call(`focus`)
2222
}
2323
}, []any{shareUrl})
2424

0 commit comments

Comments
 (0)