@@ -15,7 +15,6 @@ import { blankOverlay, petstore } from "./defaults";
15
15
import speakeasyWhiteLogo from "./assets/speakeasy-white.svg" ;
16
16
import openapiLogo from "./assets/openapi.svg" ;
17
17
import { compress , decompress } from "@/compress" ;
18
- import { CopyButton } from "@/components/CopyButton" ;
19
18
import { Button } from "@/components/ui/button" ;
20
19
import {
21
20
ImperativePanelGroupHandle ,
@@ -25,7 +24,13 @@ import {
25
24
} from "react-resizable-panels" ;
26
25
import posthog from "posthog-js" ;
27
26
import { useDebounceCallback , useMediaQuery } from "usehooks-ts" ;
28
- import { formatDocument , guessDocumentLanguage } from "./lib/utils" ;
27
+ import {
28
+ arraysEqual ,
29
+ formatDocument ,
30
+ guessDocumentLanguage ,
31
+ } from "./lib/utils" ;
32
+ import ShareDialog , { ShareDialogHandle } from "./components/ShareDialog" ;
33
+ import { Loader2Icon , ShareIcon } from "lucide-react" ;
29
34
30
35
const Link = ( { children, href } : { children : ReactNode ; href : string } ) => (
31
36
< a
@@ -73,7 +78,6 @@ function Playground() {
73
78
const result = useRef ( blankOverlay ) ;
74
79
const [ resultLoading , setResultLoading ] = useState ( false ) ;
75
80
const [ error , setError ] = useState ( "" ) ;
76
- const [ shareUrl , setShareUrl ] = useState ( "" ) ;
77
81
const [ shareUrlLoading , setShareUrlLoading ] = useState ( false ) ;
78
82
const [ overlayMarkers , setOverlayMarkers ] = useState < editor . IMarkerData [ ] > (
79
83
[ ] ,
@@ -135,7 +139,12 @@ function Playground() {
135
139
136
140
const onChangeOverlayDebounced = useDebounceCallback ( onChangeOverlay , 500 ) ;
137
141
142
+ const shareDialogRef = useRef < ShareDialogHandle > ( null ) ;
143
+ const lastSharedStart = useRef < string > ( "" ) ;
144
+
138
145
const getShareUrl = useCallback ( async ( ) => {
146
+ if ( ! shareDialogRef . current ) return ;
147
+
139
148
try {
140
149
setShareUrlLoading ( true ) ;
141
150
const info = await GetInfo ( original . current , false ) ;
@@ -144,14 +153,19 @@ function Playground() {
144
153
original : original . current ,
145
154
info : info ,
146
155
} ) ;
147
- const blob = await compress ( start ) ;
156
+
157
+ const alreadySharedThis = lastSharedStart . current === start ;
158
+ if ( alreadySharedThis ) {
159
+ shareDialogRef . current . setOpen ( true ) ;
160
+ return ;
161
+ }
148
162
149
163
const response = await fetch ( "/api/share" , {
150
164
method : "POST" ,
151
165
headers : {
152
166
"Content-Type" : "application/json" ,
153
167
} ,
154
- body : blob ,
168
+ body : await compress ( start ) ,
155
169
} ) ;
156
170
157
171
if ( response . ok ) {
@@ -161,7 +175,10 @@ function Playground() {
161
175
currentUrl . hash = "" ;
162
176
currentUrl . searchParams . set ( "s" , base64Data ) ;
163
177
164
- setShareUrl ( currentUrl . toString ( ) ) ;
178
+ lastSharedStart . current = start ;
179
+ shareDialogRef . current . setUrl ( currentUrl . toString ( ) ) ;
180
+ shareDialogRef . current . setOpen ( true ) ;
181
+
165
182
history . pushState ( null , "" , currentUrl . toString ( ) ) ;
166
183
posthog . capture ( "overlay.speakeasy.com:share" , {
167
184
openapi : JSON . parse ( info ) ,
@@ -283,14 +300,25 @@ function Playground() {
283
300
284
301
const maxLayout = useCallback ( ( index : number ) => {
285
302
const panelGroup = ref . current ;
286
- const desiredWidths = [ 10 , 10 , 10 ] ;
287
- if ( index < desiredWidths . length && index >= 0 ) {
288
- desiredWidths [ index ] = 80 ;
303
+ if ( ! panelGroup ) return ;
304
+
305
+ const currentLayout = panelGroup ?. getLayout ( ) ;
306
+
307
+ if ( ! arraysEqual ( currentLayout , defaultLayout ) ) {
308
+ panelGroup . setLayout ( defaultLayout ) ;
309
+ return ;
289
310
}
290
- if ( panelGroup ) {
291
- // Reset each Panel to 50% of the group's width
292
- panelGroup . setLayout ( desiredWidths ) ;
311
+
312
+ const baseWidth = 10 ;
313
+ const maxedWidth = 80 ;
314
+ const desiredWidths = Array ( 3 ) . fill ( baseWidth ) ;
315
+
316
+ if ( index < desiredWidths . length && index >= 0 ) {
317
+ desiredWidths [ index ] = maxedWidth ;
293
318
}
319
+
320
+ // Reset each Panel to 50% of the group's width
321
+ panelGroup . setLayout ( desiredWidths ) ;
294
322
} , [ ] ) ;
295
323
296
324
if ( ! ready ) {
@@ -312,7 +340,7 @@ function Playground() {
312
340
For proper user experience, please use a desktop device
313
341
</ Alert >
314
342
) : null }
315
- < div style = { { paddingBottom : "1rem" , width : "100vw" } } >
343
+ < div style = { { width : "100vw" } } >
316
344
< div className = "border-b border-muted p-4 md:p-6 text-left" >
317
345
< div className = "flex gap-2" >
318
346
< div className = "flex flex-1" >
@@ -341,7 +369,7 @@ function Playground() {
341
369
</ div >
342
370
</ div >
343
371
< div className = "flex flex-1 flex-row-reverse" >
344
- < div className = "flex flex-col justify-between" >
372
+ < div className = "flex flex-col gap-4 justify-between" >
345
373
< div className = "flex gap-x-2" >
346
374
< span >
347
375
< Link href = "https://www.speakeasy.com?utm_source=overlay.speakeasy.com" >
@@ -365,21 +393,27 @@ function Playground() {
365
393
</ Link >
366
394
</ span >
367
395
</ div >
368
- < div className = "flex gap-x-2 justify-evenly " >
396
+ < div className = "flex gap-x-2 justify-end " >
369
397
< Button
370
- className = "border-b border-transparent transition-all duration-200 hover:border-current"
398
+ className = "border-b border-transparent hover:border-current"
371
399
style = { {
372
400
color : "#FBE331" ,
373
401
backgroundColor : "#1E1E1E" ,
374
402
} }
375
403
onClick = { getShareUrl }
376
404
disabled = { shareUrlLoading }
377
405
>
406
+ { shareUrlLoading ? (
407
+ < Loader2Icon
408
+ className = "animate-spin"
409
+ style = { { height : "75%" } }
410
+ />
411
+ ) : (
412
+ < ShareIcon style = { { height : "75%" } } />
413
+ ) }
378
414
Share
379
415
</ Button >
380
- < div className = "flex items-center gap-x-2 grow" >
381
- { shareUrl ? < CopyButton value = { shareUrl } /> : null }
382
- </ div >
416
+ < ShareDialog ref = { shareDialogRef } />
383
417
</ div >
384
418
</ div >
385
419
</ div >
0 commit comments