mirror of
https://github.com/fluencelabs/fluent-pad
synced 2025-04-24 16:32:13 +00:00
Users list with online statuses syncrhonization works
This commit is contained in:
parent
4879878e9f
commit
735c5cbe0c
@ -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<FluenceClient | null>(null);
|
||||
const [isConnected, setIsConnected] = useState<boolean>(false);
|
||||
const [isInRoom, setIsInRoom] = useState(false);
|
||||
const [isInRoom, setIsInRoom] = useState<boolean>(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 = () => {
|
||||
<FluenceClientContext.Provider value={client}>
|
||||
<div className="App">
|
||||
<div>
|
||||
<div>Connection status: {isConnected ? 'connected' : 'disconnected'}</div>
|
||||
<div>Connection status: {client ? 'connected' : 'disconnected'}</div>
|
||||
<div>
|
||||
<label>Nickname: </label>
|
||||
<input
|
||||
@ -53,7 +56,7 @@ const App = () => {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button disabled={isInRoom} onClick={joinRoom}>
|
||||
<button disabled={isInRoom || !client} onClick={joinRoom}>
|
||||
Join Room
|
||||
</button>
|
||||
</div>
|
||||
@ -64,7 +67,7 @@ const App = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>{isConnected && client && isInRoom && <UserList />}</div>
|
||||
<div>{isInRoom && client && <UserList selfName={nickName} />}</div>
|
||||
</div>
|
||||
</FluenceClientContext.Provider>
|
||||
);
|
||||
|
@ -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<Map<PeerId, User>>(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();
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
@ -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) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user