Skip to content

Commit

Permalink
Merge pull request #109 from supabase-community/fix/live-sharing-ux-i…
Browse files Browse the repository at this point in the history
…mprovements

Live Share UX enhancements
  • Loading branch information
jgoux authored Oct 8, 2024
2 parents 6804fa7 + 845225b commit 27eb82e
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 77 deletions.
9 changes: 1 addition & 8 deletions apps/postgres-new/app/(main)/db/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Workspace from '~/components/workspace'
export default function Page({ params }: { params: { id: string } }) {
const databaseId = params.id
const router = useRouter()
const { dbManager, liveShare } = useApp()
const { dbManager } = useApp()

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

// Cleanup live shared database when switching databases
useEffect(() => {
if (liveShare.isLiveSharing && liveShare.databaseId !== databaseId) {
liveShare.stop()
}
}, [liveShare, databaseId])

return <Workspace databaseId={databaseId} visibility="local" />
}
146 changes: 91 additions & 55 deletions apps/postgres-new/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ChatMessage from './chat-message'
import SignInButton from './sign-in-button'
import { useWorkspace } from './workspace'
import { CopyableField } from './copyable-field'
import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'

export function getInitialMessages(tables: TablesData): Message[] {
return [
Expand Down Expand Up @@ -244,49 +245,7 @@ export default function Chat() {
)}
ref={scrollRef}
>
{liveShare.isLiveSharing && (
<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">
<div className="flex items-center justify-center h-full flex-col gap-y-5">
<div className="w-full text-left">
<p className="text-lg">Access your in-browser database</p>
<p className="text-xs text-muted-foreground">
Closing the window will stop the Live Share session
</p>
</div>
<CopyableField
value={`postgres://postgres@${liveShare.databaseId}.${process.env.NEXT_PUBLIC_BROWSER_PROXY_DOMAIN}/postgres?sslmode=require`}
/>

{liveShare.clientIp ? (
<p className="text-sm text-muted-foreground flex items-center gap-2">
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-primary"></span>
</span>
<span>
Connected from{' '}
<span className="text-card-foreground">{liveShare.clientIp}</span>
</span>
</p>
) : (
<p className="text-sm text-muted-foreground flex items-center gap-2">
<span className="relative inline-flex rounded-full h-3 w-3 bg-muted-foreground"></span>
<span>Not connected</span>
</p>
)}
<Button
className="w-full gap-2"
variant="outline"
onClick={() => {
liveShare.stop()
}}
>
<PlugIcon size={16} />
<span>Stop sharing database</span>
</Button>
</div>
</div>
)}
<LiveShareOverlay databaseId={databaseId} />
<m.div
key={databaseId}
className="flex flex-col gap-4 w-full max-w-4xl p-10"
Expand Down Expand Up @@ -374,18 +333,21 @@ export default function Chat() {
) : (
<div className="h-full w-full max-w-4xl flex flex-col gap-10 justify-center items-center">
{user ? (
<m.h3
layout
className="text-2xl font-light text-center"
variants={{
hidden: { opacity: 0, y: 10 },
show: { opacity: 1, y: 0 },
}}
initial="hidden"
animate="show"
>
What would you like to create?
</m.h3>
<>
<LiveShareOverlay databaseId={databaseId} />
<m.h3
layout
className="text-2xl font-light text-center"
variants={{
hidden: { opacity: 0, y: 10 },
show: { opacity: 1, y: 0 },
}}
initial="hidden"
animate="show"
>
What would you like to create?
</m.h3>
</>
) : (
<m.div
className="flex flex-col items-center gap-4 max-w-lg"
Expand Down Expand Up @@ -570,3 +532,77 @@ export default function Chat() {
</div>
)
}

function LiveShareOverlay(props: { databaseId: string }) {
const { liveShare } = useApp()

if (liveShare.isLiveSharing && liveShare.databaseId === props.databaseId) {
return (
<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">
<div className="flex items-center justify-center h-full flex-col gap-y-7">
<div className="w-full text-left">
<p className="text-lg">Access your in-browser database</p>
<p className="text-xs text-muted-foreground">
Closing the window will stop the Live Share session
</p>
</div>
<Tabs defaultValue="uri" className="w-full justify-between bg-muted/50 rounded-md border">
<TabsList className="w-full flex justify-start bg-transparent px-3">
<TabsTrigger
value="uri"
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"
>
URI
</TabsTrigger>
<TabsTrigger
value="psql"
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"
>
PSQL
</TabsTrigger>
</TabsList>
<TabsContent value="uri" className="px-2 pb-2">
<CopyableField
value={`postgres://postgres@${liveShare.databaseId}.${process.env.NEXT_PUBLIC_BROWSER_PROXY_DOMAIN}/postgres?sslmode=require`}
/>
</TabsContent>
<TabsContent value="psql" className="px-2 pb-2">
<CopyableField
value={`psql "postgres://postgres@${liveShare.databaseId}.${process.env.NEXT_PUBLIC_BROWSER_PROXY_DOMAIN}/postgres?sslmode=require"`}
/>
</TabsContent>
</Tabs>

{liveShare.clientIp ? (
<p className="text-sm text-muted-foreground flex items-center gap-2">
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-primary"></span>
</span>
<span>
Connected from <span className="text-card-foreground">{liveShare.clientIp}</span>
</span>
</p>
) : (
<p className="text-sm text-muted-foreground flex items-center gap-2">
<span className="relative inline-flex rounded-full h-3 w-3 bg-muted-foreground"></span>
<span>No client connected</span>
</p>
)}
<Button
className="w-full gap-2"
variant="outline"
onClick={() => {
liveShare.stop()
}}
>
<PlugIcon size={16} />
<span>Stop sharing database</span>
</Button>
</div>
</div>
)

return null
}
}
32 changes: 18 additions & 14 deletions apps/postgres-new/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export default function Sidebar() {
setIsSignInDialogOpen,
setIsRenameDialogOpen,
isLegacyDomain,
liveShare,
} = useApp()
let { id: currentDatabaseId } = useParams<{ id: string }>()
const router = useRouter()
Expand Down Expand Up @@ -130,6 +131,9 @@ export default function Sidebar() {
if (!user) {
setIsSignInDialogOpen(true)
} else {
if (liveShare.isLiveSharing) {
liveShare.stop()
}
router.push('/')
focusRef.current?.focus()
}
Expand Down Expand Up @@ -368,7 +372,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) {
)}
href={`/db/${database.id}`}
>
{isActive && liveShare.isLiveSharing && (
{liveShare.isLiveSharing && liveShare.databaseId === database.id && (
<Tooltip>
<TooltipTrigger asChild>
<RadioIcon size={18} />
Expand Down Expand Up @@ -540,40 +544,40 @@ type ConnectMenuItemProps = {

function LiveShareMenuItem(props: ConnectMenuItemProps) {
const { liveShare, user } = useApp()
const router = useRouter()

// Only show the connect menu item on fully loaded dashboard
if (!props.isActive) {
return null
}

if (!liveShare.isLiveSharing) {
if (liveShare.isLiveSharing && liveShare.databaseId === props.databaseId) {
return (
<DropdownMenuItem
disabled={!user}
className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
onClick={async (e) => {
e.preventDefault()
liveShare.start(props.databaseId)
liveShare.stop()
props.setIsPopoverOpen(false)
}}
>
<LiveShareIcon size={16} className="flex-shrink-0 text-muted-foreground" />
<span>Live Share</span>
<PlugIcon size={16} strokeWidth={2} className="flex-shrink-0 text-muted-foreground" />
<span>Stop sharing</span>
</DropdownMenuItem>
)
}

return (
<DropdownMenuItem
disabled={!user}
className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3"
onClick={async (e) => {
e.preventDefault()
liveShare.stop()
if (liveShare.isLiveSharing) {
liveShare.stop()
}
liveShare.start(props.databaseId)
router.push(`/db/${props.databaseId}`)
props.setIsPopoverOpen(false)
}}
>
<PlugIcon size={16} strokeWidth={2} className="flex-shrink-0 text-muted-foreground" />
<span>Stop sharing</span>
<LiveShareIcon size={16} className="flex-shrink-0 text-muted-foreground" />
<span>Live Share</span>
</DropdownMenuItem>
)
}
Loading

0 comments on commit 27eb82e

Please sign in to comment.