import './index.css' import Editor from '@monaco-editor/react' import { useSocketIOProviderState } from '@textea/y-socket.io/hooks' import { createSocketIOProvider, SocketIOProvider } from '@textea/y-socket.io/provider' import React, { useDeferredValue, useEffect, useState } from 'react' import { MonacoBinding } from 'y-monaco' import { Awareness } from 'y-protocols/awareness' import * as Y from 'yjs' import { ClientData } from './types' const yDoc = new Y.Doc() const type = yDoc.getText('javascript') const roomId = 'test-id' const awareness = new Awareness(yDoc) type User = { id: Awareness['clientID'] name: string } const DEFAULT_USER: Readonly = { id: awareness.clientID, name: `ID_${awareness.clientID.toString(16).toUpperCase()}` } awareness.setLocalState(DEFAULT_USER) let _monacoBinding: MonacoBinding export const App: React.FC = () => { const [text, setText] = useState('') const [userName, setUserName] = useState(DEFAULT_USER.name) const [otherUsers, setOtherUsers] = useState([]) const [provider, setProvider] = useState>() const isConnecting = useSocketIOProviderState(provider, (state) => state.connecting) const isConnected = useSocketIOProviderState(provider, (state) => state.connected) const isSynced = useSocketIOProviderState(provider, (state) => state.synced) const deferredIsSynced = useDeferredValue(isSynced) const status = isConnecting ? 'Connecting' : isConnected ? deferredIsSynced ? 'Synced' : 'Syncing' : 'Disconnected' const clientData = useSocketIOProviderState(provider, (state) => state.data) const role = isConnected ? clientData ? clientData.isOwner ? 'Admin' : 'User' : 'Loading...' : 'Not Available' useEffect(() => { const handleAwarenessUpdate = () => { const localUser = awareness.getLocalState() as User | null if (localUser) { setUserName(localUser.name) } setOtherUsers( [...awareness.getStates().entries()].filter( ([clientId]) => clientId !== yDoc.clientID) .map(([, state]) => state as User) ) } awareness.on('update', handleAwarenessUpdate) const provider = createSocketIOProvider('ws://localhost:1234', roomId, yDoc, { awareness, autoConnect: false }) setProvider(provider) return () => { awareness.off('update', handleAwarenessUpdate) provider.destroy() } }, []) if (!provider) { return

Loading...

} return ( <>

{role === 'Admin' && ( <> {' '} )}

Status: {status}

Role: {role}

{ const model = editor.getModel() if (model == null) { throw new Error('model is null') } _monacoBinding = new MonacoBinding(type, model, new Set([editor]), awareness) }} value={text} onChange={ (value) => { if (value) { setText(value) } } } defaultLanguage='javascript' />

{ awareness.setLocalStateField('name', event.target.value) }} />

{otherUsers.length > 0 && (
Users:
    {otherUsers.map((user) => (
  • {user.name}
  • ))}
)} ) } export default App