@@ -17,6 +17,7 @@ import {
1717} from 'react'
1818import { DbManager } from '~/lib/db'
1919import { useAsyncMemo } from '~/lib/hooks'
20+ import { parseParameterStatus } from '~/lib/pg-wire-util'
2021import { createClient } from '~/utils/supabase/client'
2122
2223export type AppProps = PropsWithChildren
@@ -105,9 +106,15 @@ export default function AppProvider({ children }: AppProps) {
105106 return await dbManager . getRuntimePgVersion ( )
106107 } , [ dbManager ] )
107108
108- const [ connectedDatabaseId , setConnectedDatabaseId ] = useState < string | null > ( null )
109- const [ ws , setWs ] = useState < WebSocket | null > ( null )
110- const connectDatabase = useCallback (
109+ const [ liveSharedDatabaseId , setLiveSharedDatabaseId ] = useState < string | null > ( null )
110+ const [ connectedClientIp , setConnectedClientIp ] = useState < string | null > ( null )
111+ const [ liveShareWebsocket , setLiveShareWebsocket ] = useState < WebSocket | null > ( null )
112+ const cleanUp = useCallback ( ( ) => {
113+ setLiveShareWebsocket ( null )
114+ setLiveSharedDatabaseId ( null )
115+ setConnectedClientIp ( null )
116+ } , [ setLiveShareWebsocket , setLiveSharedDatabaseId , setConnectedClientIp ] )
117+ const startLiveShare = useCallback (
111118 async ( databaseId : string ) => {
112119 if ( ! dbManager ) {
113120 throw new Error ( 'dbManager is not available' )
@@ -122,43 +129,53 @@ export default function AppProvider({ children }: AppProps) {
122129 ws . binaryType = 'arraybuffer'
123130
124131 ws . onopen = ( ) => {
125- setConnectedDatabaseId ( databaseId )
132+ setLiveSharedDatabaseId ( databaseId )
126133 }
127134 ws . onmessage = async ( event ) => {
128135 const message = new Uint8Array ( await event . data )
136+
137+ const messageType = String . fromCharCode ( message [ 0 ] )
138+ if ( messageType === 'S' ) {
139+ const { name, value } = parseParameterStatus ( message )
140+ if ( name === 'client_ip' ) {
141+ setConnectedClientIp ( value === '' ? null : value )
142+ return
143+ }
144+ }
145+
129146 const response = await db . execProtocolRaw ( message )
130147 ws . send ( response )
131148 }
132149 ws . onclose = ( event ) => {
133- setConnectedDatabaseId ( null )
150+ cleanUp ( )
134151 }
135152 ws . onerror = ( error ) => {
136153 console . error ( 'webSocket error:' , error )
137- setConnectedDatabaseId ( null )
154+ cleanUp ( )
138155 }
139156
140- setWs ( ws )
157+ setLiveShareWebsocket ( ws )
141158 } ,
142- [ dbManager ]
159+ [ dbManager , cleanUp ]
143160 )
144- const disconnectDatabase = useCallback ( ( ) => {
145- ws ?. close ( )
146- setWs ( null )
147- setConnectedDatabaseId ( null )
148- } , [ ws ] )
149- const connectedDatabase = {
150- connect : connectDatabase ,
151- disconnect : disconnectDatabase ,
152- databaseId : connectedDatabaseId ,
153- isConnected : Boolean ( connectedDatabaseId ) ,
161+ const stopLiveShare = useCallback ( ( ) => {
162+ liveShareWebsocket ?. close ( )
163+ cleanUp ( )
164+ } , [ cleanUp , liveShareWebsocket ] )
165+ const liveShare = {
166+ start : startLiveShare ,
167+ stop : stopLiveShare ,
168+ databaseId : liveSharedDatabaseId ,
169+ clientIp : connectedClientIp ,
170+ isLiveSharing : Boolean ( liveSharedDatabaseId ) ,
154171 }
155172
156173 return (
157174 < AppContext . Provider
158175 value = { {
159176 user,
160177 isLoadingUser,
161- connectedDatabase ,
178+ liveShare ,
162179 signIn,
163180 signOut,
164181 isSignInDialogOpen,
@@ -195,11 +212,12 @@ export type AppContextValues = {
195212 dbManager ?: DbManager
196213 pgliteVersion ?: string
197214 pgVersion ?: string
198- connectedDatabase : {
199- connect : ( databaseId : string ) => Promise < void >
200- disconnect : ( ) => void
215+ liveShare : {
216+ start : ( databaseId : string ) => Promise < void >
217+ stop : ( ) => void
201218 databaseId : string | null
202- isConnected : boolean
219+ clientIp : string | null
220+ isLiveSharing : boolean
203221 }
204222}
205223
0 commit comments