diff --git a/client/src/app/App1.tsx b/client/src/app/App1.tsx index 68e7d55..01b1bda 100644 --- a/client/src/app/App1.tsx +++ b/client/src/app/App1.tsx @@ -3,35 +3,38 @@ import React, { useEffect, useState } from 'react'; import { connect } from 'src/fluence'; import './App.scss'; -import { FluenceClientContext } from './FluenceClientContext'; +import { FluenceClientContext, useFluenceClient } from './FluenceClientContext'; import { UserList } from './UserList'; import * as calls from 'src/fluence/calls'; const App = () => { const [client, setClient] = useState(null); - const [isConnected, setIsConnected] = useState(false); - const [isInRoom, setIsInRoom] = useState(false); + const [isInRoom, setIsInRoom] = useState(false); const [nickName, setNickName] = useState('myNickName'); useEffect(() => { const fn = async () => { const c = await connect(); - setIsConnected(true); setClient(c); }; - // fn(); + fn(); }, []); const joinRoom = async () => { - const c = await connect(); - setIsConnected(true); - setClient(c); - await calls.joinRoom(nickName); + if (!client) { + return; + } + + await calls.joinRoom(client, nickName); setIsInRoom(true); }; const leaveRoom = async () => { - await calls.leaveRoom(); + if (!client) { + return; + } + + await calls.leaveRoom(client); setIsInRoom(false); }; @@ -39,7 +42,7 @@ const App = () => {
-
Connection status: {isConnected ? 'connected' : 'disconnected'}
+
Connection status: {client ? 'connected' : 'disconnected'}
{ />
-
@@ -64,7 +67,7 @@ const App = () => {
-
{isConnected && client && isInRoom && }
+
{isInRoom && client && }
); diff --git a/client/src/app/UserList.tsx b/client/src/app/UserList.tsx index deeb9c0..49e02bc 100644 --- a/client/src/app/UserList.tsx +++ b/client/src/app/UserList.tsx @@ -28,7 +28,7 @@ type PeerId = string; const refreshTimeoutMs = 7000; -export const UserList = () => { +export const UserList = (props: { selfName: string }) => { const client = useFluenceClient()!; const [users, setUsers] = useState>(new Map()); @@ -45,7 +45,7 @@ export const UserList = () => { calls.updateOnlineStatuses(client); }, refreshTimeoutMs); - subscribeToEvent(client, fluentPadServiceId, notifyUserAddedFnName, (args, _) => { + const unsub1 = subscribeToEvent(client, fluentPadServiceId, notifyUserAddedFnName, (args, _) => { const users = args.flatMap((x) => x).flatMap((x) => x) as calls.User[]; setUsers((prev) => { const result = new Map(prev); @@ -54,29 +54,31 @@ export const UserList = () => { continue; } + const isCurrentUser = u.peer_id === client.selfPeerId.toB58String(); + result.set(u.peer_id, { name: u.name, id: u.peer_id, - isOnline: false, - shouldBecomeOnline: false, + isOnline: isCurrentUser, + shouldBecomeOnline: isCurrentUser, }); } return result; }); }); - subscribeToEvent(client, fluentPadServiceId, notifyUserRemovedFnName, (args, _) => { - const users = args.flatMap((x) => x) as calls.User[]; + const unsub2 = subscribeToEvent(client, fluentPadServiceId, notifyUserRemovedFnName, (args, _) => { + const users = args.flatMap((x) => x) as PeerId[]; setUsers((prev) => { const result = new Map(prev); for (let u of users) { - result.delete(u.peer_id); + result.delete(u); } return result; }); }); - const unsub = subscribeToEvent(client, fluentPadServiceId, notifyOnlineFnName, (args, _) => { + const unsub3 = subscribeToEvent(client, fluentPadServiceId, notifyOnlineFnName, (args, _) => { const [[peerId], immediately] = args; setUsers((prev) => { const result = new Map(prev); @@ -94,11 +96,14 @@ export const UserList = () => { }); // don't block - calls.getInitialUserList(client); + calls.getUserList(client); + calls.notifySelfAdded(client, props.selfName); return () => { clearTimeout(listRefreshTimer); - unsub(); + unsub1(); + unsub2(); + unsub3(); }; }, []); diff --git a/client/src/fluence/calls.ts b/client/src/fluence/calls.ts index 2799bf8..4fd2345 100644 --- a/client/src/fluence/calls.ts +++ b/client/src/fluence/calls.ts @@ -5,6 +5,7 @@ import { historyServiceId, notifyOnlineFnName, notifyUserAddedFnName, + notifyUserRemovedFnName, servicesNodePid, userListServiceId, } from './constants'; @@ -40,27 +41,6 @@ const throwIfError = (result: ServiceResult) => { } }; -const notifyOnlineStatusesAir = ` - (fold allUsers.$.users! u - (par - (seq - (call u.$.relay_id ("op" "identity") []) - (seq - (call u.$.peer_id ("op" "identity") []) - (seq - (call u.$.relay_id ("op" "identity") []) - (seq - (call myRelay ("op" "identity") []) - (call myPeerId (fluentPadServiceId notifyOnline) [u.$.peer_id immediately]) - ) - ) - ) - ) - (next u) - ) - ) -`; - export const updateOnlineStatuses = async (client: FluenceClient) => { const particle = new Particle( ` @@ -68,7 +48,24 @@ export const updateOnlineStatuses = async (client: FluenceClient) => { (call myRelay ("op" "identity") []) (seq (call node (userlist "get_users") [] allUsers) - ${notifyOnlineStatusesAir} + (fold allUsers.$.users! u + (par + (seq + (call u.$.relay_id ("op" "identity") []) + (seq + (call u.$.peer_id ("op" "identity") []) + (seq + (call u.$.relay_id ("op" "identity") []) + (seq + (call myRelay ("op" "identity") []) + (call myPeerId (fluentPadServiceId notifyOnline) [u.$.peer_id immediately]) + ) + ) + ) + ) + (next u) + ) + ) ) ) `, @@ -86,19 +83,53 @@ export const updateOnlineStatuses = async (client: FluenceClient) => { sendParticle(client, particle); }; -export const getInitialUserList = async (client: FluenceClient) => { +export const notifySelfAdded = (client: FluenceClient, name: string) => { const particle = new Particle( ` (seq (call myRelay ("op" "identity") []) (seq (call node (userlist "get_users") [] allUsers) - (par - (seq - (call myRelay ("op" "identity") []) - (call myPeerId (fluentPadServiceId notifyUserAdded) [allUsers.$.users!]) + (fold allUsers.$.users! u + (par + (seq + (call u.$.relay_id ("op" "identity") []) + (call u.$.peer_id (fluentPadServiceId notifyUserAdded) [myUser]) + ) + (next u) ) - ${notifyOnlineStatusesAir} + ) + ) + ) + `, + { + node: servicesNodePid, + userlist: userListServiceId, + myRelay: client.relayPeerID.toB58String(), + myPeerId: client.selfPeerId.toB58String(), + fluentPadServiceId: fluentPadServiceId, + notifyUserAdded: notifyUserAddedFnName, + myUser: { + name: name, + peer_id: client.selfPeerId.toB58String(), + relay_id: client.relayPeerID.toB58String(), + }, + }, + ); + + sendParticle(client, particle); +}; + +export const getUserList = async (client: FluenceClient) => { + const particle = new Particle( + ` + (seq + (call myRelay ("op" "identity") []) + (seq + (call node (userlist "get_users") [] allUsers) + (seq + (call myRelay ("op" "identity") []) + (call myPeerId (fluentPadServiceId notifyUserAdded) [allUsers.$.users!]) ) ) ) @@ -117,7 +148,7 @@ export const getInitialUserList = async (client: FluenceClient) => { await sendParticle(client, particle); }; -export const joinRoom = async (nickName: string) => { +export const joinRoom = async (client: FluenceClient, nickName: string) => { let joinRoomAir = ` (call node (userlist "join") [user] result) `; @@ -125,30 +156,50 @@ export const joinRoom = async (nickName: string) => { const data = new Map(); data.set('user', { name: nickName, - peer_id: fluenceClient.selfPeerId.toB58String(), - relay_id: fluenceClient.relayPeerID.toB58String(), + peer_id: client.selfPeerId.toB58String(), + relay_id: client.relayPeerID.toB58String(), }); data.set('userlist', userListServiceId); data.set('node', servicesNodePid); - const [result] = await fluenceClient.fetch<[GetUsersResult]>(joinRoomAir, ['result'], data); + const [result] = await client.fetch<[GetUsersResult]>(joinRoomAir, ['result'], data); throwIfError(result); return result.users; }; -export const leaveRoom = async () => { - let leaveRoomAir = ` - (call node (userlist "leave") [ownPeerId] callResult) - `; +export const leaveRoom = async (client: FluenceClient) => { + const particle = new Particle( + ` + (seq + (call myRelay ("op" "identity") []) + (seq + (call node (userlist "leave") [myPeerId]) + (seq + (call node (userlist "get_users") [] allUsers) + (fold allUsers.$.users! u + (par + (seq + (call u.$.relay_id ("op" "identity") []) + (call u.$.peer_id (fluentPadServiceId notifyUserRemoved) [myPeerId]) + ) + (next u) + ) + ) + ) + ) + ) + `, + { + node: servicesNodePid, + userlist: userListServiceId, + myRelay: client.relayPeerID.toB58String(), + myPeerId: client.selfPeerId.toB58String(), + fluentPadServiceId: fluentPadServiceId, + notifyUserRemoved: notifyUserRemovedFnName, + }, + ); - const data = new Map(); - data.set('ownPeerId', fluenceClient.selfPeerId.toB58String()); - data.set('userlist', userListServiceId); - data.set('node', servicesNodePid); - - const [result] = await fluenceClient.fetch<[ServiceResult]>(leaveRoomAir, ['callResult'], data); - throwIfError(result); - return result; + await sendParticle(client, particle); }; export const removeUser = async (userPeerId: string) => {