128 lines
4.0 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from 'react';
import {
fluentPadServiceId,
notifyOnlineFnName,
notifyUserAddedFnName,
notifyUserRemovedFnName,
2021-01-16 13:24:26 +03:00
} from 'src/app/constants';
import { useFluenceClient } from '../app/FluenceClientContext';
2021-01-16 16:28:00 +03:00
import * as api from 'src/app/api';
2021-01-17 20:22:10 +03:00
import { PeerIdB58, subscribeToEvent } from '@fluencelabs/fluence';
2021-03-04 15:40:14 +03:00
import { withErrorHandlingAsync } from './util';
2021-01-16 16:25:28 +03:00
interface User {
2021-01-17 20:22:10 +03:00
id: PeerIdB58;
name: string;
isOnline: boolean;
shouldBecomeOnline: boolean;
}
const turnUserAsOfflineCandidate = (u: User): User => {
return {
...u,
isOnline: u.shouldBecomeOnline,
shouldBecomeOnline: false,
};
};
2021-01-14 21:52:33 +03:00
const refreshTimeoutMs = 2000;
export const UserList = (props: { selfName: string }) => {
const client = useFluenceClient()!;
2021-01-17 20:22:10 +03:00
const [users, setUsers] = useState<Map<PeerIdB58, User>>(new Map());
useEffect(() => {
const listRefreshTimer = setInterval(() => {
setUsers((prev) => {
const newUsers = Array.from(prev).map(
([key, user]) => [key, turnUserAsOfflineCandidate(user)] as const,
);
return new Map(newUsers);
});
// don't block
2021-03-04 15:40:14 +03:00
withErrorHandlingAsync(async () => {
await api.updateOnlineStatuses(client);
});
}, refreshTimeoutMs);
const unsub1 = subscribeToEvent(client, fluentPadServiceId, notifyUserAddedFnName, (args, _) => {
const [users, setOnline] = args as [api.User[], boolean];
setUsers((prev) => {
const result = new Map(prev);
for (let u of users) {
if (result.has(u.peer_id)) {
continue;
}
2021-01-17 20:22:10 +03:00
const isCurrentUser = u.peer_id === client.selfPeerId;
result.set(u.peer_id, {
name: u.name,
id: u.peer_id,
isOnline: isCurrentUser || setOnline,
shouldBecomeOnline: isCurrentUser || setOnline,
});
}
return result;
});
});
const unsub2 = subscribeToEvent(client, fluentPadServiceId, notifyUserRemovedFnName, (args, _) => {
2021-01-17 20:22:10 +03:00
const [userLeft] = args as [PeerIdB58];
setUsers((prev) => {
const result = new Map(prev);
2021-01-17 20:22:10 +03:00
result.delete(userLeft);
return result;
});
});
const unsub3 = subscribeToEvent(client, fluentPadServiceId, notifyOnlineFnName, (args, _) => {
2021-01-17 20:22:10 +03:00
const [userOnline] = args as [PeerIdB58[]];
setUsers((prev) => {
const result = new Map(prev);
2021-01-17 20:22:10 +03:00
for (let u of userOnline) {
const toSetOnline = result.get(u);
if (toSetOnline) {
toSetOnline.shouldBecomeOnline = true;
toSetOnline.isOnline = true;
}
}
return result;
});
});
// don't block
2021-03-04 15:40:14 +03:00
withErrorHandlingAsync(async () => {
await api.getUserList(client);
await api.notifySelfAdded(client, props.selfName);
});
return () => {
clearTimeout(listRefreshTimer);
unsub1();
unsub2();
unsub3();
};
}, []);
const usersArray = Array.from(users)
.map((x) => x[1])
.sort((a, b) => a.name.localeCompare(b.name));
return (
2021-01-16 16:25:28 +03:00
<div className="userlist">
<ul>
2021-01-14 21:52:33 +03:00
{usersArray.map((x) => (
<li key={x.id}>
2021-01-17 20:22:10 +03:00
<span className={x.id === client.selfPeerId ? 'bold' : ''}>{x.name}</span>
2021-01-16 16:25:28 +03:00
<span className={x.isOnline ? 'green' : 'red'}> ({x.isOnline ? 'online' : 'offline'})</span>
</li>
))}
</ul>
</div>
);
};