Skip to content

Commit 27eb82e

Browse files
authored
Merge pull request #109 from supabase-community/fix/live-sharing-ux-improvements
Live Share UX enhancements
2 parents 6804fa7 + 845225b commit 27eb82e

File tree

4 files changed

+230
-77
lines changed

4 files changed

+230
-77
lines changed

apps/postgres-new/app/(main)/db/[id]/page.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Workspace from '~/components/workspace'
88
export default function Page({ params }: { params: { id: string } }) {
99
const databaseId = params.id
1010
const router = useRouter()
11-
const { dbManager, liveShare } = useApp()
11+
const { dbManager } = useApp()
1212

1313
useEffect(() => {
1414
async function run() {
@@ -25,12 +25,5 @@ export default function Page({ params }: { params: { id: string } }) {
2525
run()
2626
}, [dbManager, databaseId, router])
2727

28-
// Cleanup live shared database when switching databases
29-
useEffect(() => {
30-
if (liveShare.isLiveSharing && liveShare.databaseId !== databaseId) {
31-
liveShare.stop()
32-
}
33-
}, [liveShare, databaseId])
34-
3528
return <Workspace databaseId={databaseId} visibility="local" />
3629
}

apps/postgres-new/components/chat.tsx

Lines changed: 91 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import ChatMessage from './chat-message'
2626
import SignInButton from './sign-in-button'
2727
import { useWorkspace } from './workspace'
2828
import { CopyableField } from './copyable-field'
29+
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'
2930

3031
export function getInitialMessages(tables: TablesData): Message[] {
3132
return [
@@ -244,49 +245,7 @@ export default function Chat() {
244245
)}
245246
ref={scrollRef}
246247
>
247-
{liveShare.isLiveSharing && (
248-
<div className="h-full w-full max-w-4xl flex flex-col gap-10 p-10 absolute backdrop-blur-sm bg-card/90 z-10">
249-
<div className="flex items-center justify-center h-full flex-col gap-y-5">
250-
<div className="w-full text-left">
251-
<p className="text-lg">Access your in-browser database</p>
252-
<p className="text-xs text-muted-foreground">
253-
Closing the window will stop the Live Share session
254-
</p>
255-
</div>
256-
<CopyableField
257-
value={`postgres://postgres@${liveShare.databaseId}.${process.env.NEXT_PUBLIC_BROWSER_PROXY_DOMAIN}/postgres?sslmode=require`}
258-
/>
259-
260-
{liveShare.clientIp ? (
261-
<p className="text-sm text-muted-foreground flex items-center gap-2">
262-
<span className="relative flex h-3 w-3">
263-
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
264-
<span className="relative inline-flex rounded-full h-3 w-3 bg-primary"></span>
265-
</span>
266-
<span>
267-
Connected from{' '}
268-
<span className="text-card-foreground">{liveShare.clientIp}</span>
269-
</span>
270-
</p>
271-
) : (
272-
<p className="text-sm text-muted-foreground flex items-center gap-2">
273-
<span className="relative inline-flex rounded-full h-3 w-3 bg-muted-foreground"></span>
274-
<span>Not connected</span>
275-
</p>
276-
)}
277-
<Button
278-
className="w-full gap-2"
279-
variant="outline"
280-
onClick={() => {
281-
liveShare.stop()
282-
}}
283-
>
284-
<PlugIcon size={16} />
285-
<span>Stop sharing database</span>
286-
</Button>
287-
</div>
288-
</div>
289-
)}
248+
<LiveShareOverlay databaseId={databaseId} />
290249
<m.div
291250
key={databaseId}
292251
className="flex flex-col gap-4 w-full max-w-4xl p-10"
@@ -374,18 +333,21 @@ export default function Chat() {
374333
) : (
375334
<div className="h-full w-full max-w-4xl flex flex-col gap-10 justify-center items-center">
376335
{user ? (
377-
<m.h3
378-
layout
379-
className="text-2xl font-light text-center"
380-
variants={{
381-
hidden: { opacity: 0, y: 10 },
382-
show: { opacity: 1, y: 0 },
383-
}}
384-
initial="hidden"
385-
animate="show"
386-
>
387-
What would you like to create?
388-
</m.h3>
336+
<>
337+
<LiveShareOverlay databaseId={databaseId} />
338+
<m.h3
339+
layout
340+
className="text-2xl font-light text-center"
341+
variants={{
342+
hidden: { opacity: 0, y: 10 },
343+
show: { opacity: 1, y: 0 },
344+
}}
345+
initial="hidden"
346+
animate="show"
347+
>
348+
What would you like to create?
349+
</m.h3>
350+
</>
389351
) : (
390352
<m.div
391353
className="flex flex-col items-center gap-4 max-w-lg"
@@ -570,3 +532,77 @@ export default function Chat() {
570532
</div>
571533
)
572534
}
535+
536+
function LiveShareOverlay(props: { databaseId: string }) {
537+
const { liveShare } = useApp()
538+
539+
if (liveShare.isLiveSharing && liveShare.databaseId === props.databaseId) {
540+
return (
541+
<div className="h-full w-full max-w-4xl flex flex-col gap-10 p-10 absolute backdrop-blur-sm bg-card/90 z-10">
542+
<div className="flex items-center justify-center h-full flex-col gap-y-7">
543+
<div className="w-full text-left">
544+
<p className="text-lg">Access your in-browser database</p>
545+
<p className="text-xs text-muted-foreground">
546+
Closing the window will stop the Live Share session
547+
</p>
548+
</div>
549+
<Tabs defaultValue="uri" className="w-full justify-between bg-muted/50 rounded-md border">
550+
<TabsList className="w-full flex justify-start bg-transparent px-3">
551+
<TabsTrigger
552+
value="uri"
553+
className="hover:text-foreground data-[state=active]:border-b-2 data-[state=active]:border-foreground data-[state=active]:bg-none! data-[state=active]:text-foreground data-[state=active]:shadow-none rounded-none relative cursor-pointer text-foreground-lighter flex items-center space-x-2 text-center transition focus:outline-none focus-visible:ring focus-visible:ring-foreground-muted focus-visible:border-foreground-muted text-xs px-2.5 py-1"
554+
>
555+
URI
556+
</TabsTrigger>
557+
<TabsTrigger
558+
value="psql"
559+
className="hover:text-foreground data-[state=active]:border-b-2 data-[state=active]:border-foreground data-[state=active]:bg-none! data-[state=active]:text-foreground data-[state=active]:shadow-none rounded-none relative cursor-pointer text-foreground-lighter flex items-center space-x-2 text-center transition focus:outline-none focus-visible:ring focus-visible:ring-foreground-muted focus-visible:border-foreground-muted text-xs px-2.5 py-1"
560+
>
561+
PSQL
562+
</TabsTrigger>
563+
</TabsList>
564+
<TabsContent value="uri" className="px-2 pb-2">
565+
<CopyableField
566+
value={`postgres://postgres@${liveShare.databaseId}.${process.env.NEXT_PUBLIC_BROWSER_PROXY_DOMAIN}/postgres?sslmode=require`}
567+
/>
568+
</TabsContent>
569+
<TabsContent value="psql" className="px-2 pb-2">
570+
<CopyableField
571+
value={`psql "postgres://postgres@${liveShare.databaseId}.${process.env.NEXT_PUBLIC_BROWSER_PROXY_DOMAIN}/postgres?sslmode=require"`}
572+
/>
573+
</TabsContent>
574+
</Tabs>
575+
576+
{liveShare.clientIp ? (
577+
<p className="text-sm text-muted-foreground flex items-center gap-2">
578+
<span className="relative flex h-3 w-3">
579+
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
580+
<span className="relative inline-flex rounded-full h-3 w-3 bg-primary"></span>
581+
</span>
582+
<span>
583+
Connected from <span className="text-card-foreground">{liveShare.clientIp}</span>
584+
</span>
585+
</p>
586+
) : (
587+
<p className="text-sm text-muted-foreground flex items-center gap-2">
588+
<span className="relative inline-flex rounded-full h-3 w-3 bg-muted-foreground"></span>
589+
<span>No client connected</span>
590+
</p>
591+
)}
592+
<Button
593+
className="w-full gap-2"
594+
variant="outline"
595+
onClick={() => {
596+
liveShare.stop()
597+
}}
598+
>
599+
<PlugIcon size={16} />
600+
<span>Stop sharing database</span>
601+
</Button>
602+
</div>
603+
</div>
604+
)
605+
606+
return null
607+
}
608+
}

apps/postgres-new/components/sidebar.tsx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export default function Sidebar() {
5353
setIsSignInDialogOpen,
5454
setIsRenameDialogOpen,
5555
isLegacyDomain,
56+
liveShare,
5657
} = useApp()
5758
let { id: currentDatabaseId } = useParams<{ id: string }>()
5859
const router = useRouter()
@@ -130,6 +131,9 @@ export default function Sidebar() {
130131
if (!user) {
131132
setIsSignInDialogOpen(true)
132133
} else {
134+
if (liveShare.isLiveSharing) {
135+
liveShare.stop()
136+
}
133137
router.push('/')
134138
focusRef.current?.focus()
135139
}
@@ -368,7 +372,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) {
368372
)}
369373
href={`/db/${database.id}`}
370374
>
371-
{isActive && liveShare.isLiveSharing && (
375+
{liveShare.isLiveSharing && liveShare.databaseId === database.id && (
372376
<Tooltip>
373377
<TooltipTrigger asChild>
374378
<RadioIcon size={18} />
@@ -540,40 +544,40 @@ type ConnectMenuItemProps = {
540544

541545
function LiveShareMenuItem(props: ConnectMenuItemProps) {
542546
const { liveShare, user } = useApp()
547+
const router = useRouter()
543548

544-
// Only show the connect menu item on fully loaded dashboard
545-
if (!props.isActive) {
546-
return null
547-
}
548-
549-
if (!liveShare.isLiveSharing) {
549+
if (liveShare.isLiveSharing && liveShare.databaseId === props.databaseId) {
550550
return (
551551
<DropdownMenuItem
552-
disabled={!user}
553552
className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
554553
onClick={async (e) => {
555554
e.preventDefault()
556-
liveShare.start(props.databaseId)
555+
liveShare.stop()
557556
props.setIsPopoverOpen(false)
558557
}}
559558
>
560-
<LiveShareIcon size={16} className="flex-shrink-0 text-muted-foreground" />
561-
<span>Live Share</span>
559+
<PlugIcon size={16} strokeWidth={2} className="flex-shrink-0 text-muted-foreground" />
560+
<span>Stop sharing</span>
562561
</DropdownMenuItem>
563562
)
564563
}
565564

566565
return (
567566
<DropdownMenuItem
567+
disabled={!user}
568568
className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
569569
onClick={async (e) => {
570570
e.preventDefault()
571-
liveShare.stop()
571+
if (liveShare.isLiveSharing) {
572+
liveShare.stop()
573+
}
574+
liveShare.start(props.databaseId)
575+
router.push(`/db/${props.databaseId}`)
572576
props.setIsPopoverOpen(false)
573577
}}
574578
>
575-
<PlugIcon size={16} strokeWidth={2} className="flex-shrink-0 text-muted-foreground" />
576-
<span>Stop sharing</span>
579+
<LiveShareIcon size={16} className="flex-shrink-0 text-muted-foreground" />
580+
<span>Live Share</span>
577581
</DropdownMenuItem>
578582
)
579583
}

0 commit comments

Comments
 (0)