* refactor(bootstrap): add BootstrapShim * feat(security): [#209] generate public/private keys * refactor(encryption): move encryption utils to a service * feat(encryption): [wip] implement convertCryptoKeyToString * fix(user-settings): serialize crypto keys to strings * feat(user-settings): deserialize user settings from IndexedDB * feat(user-settings): upgrade persisted settings on boot * feat(user-settings): automatically migrate persisted user settings * refactor(encryption): simplify CryptoKey stringification * refactor(encryption): DRY up EncryptionService * feat(verification): send public key to new peers * refactor(encryption): use class instance * refactor(serialization): use class instance * refactor(verification): [wip] create usePeerVerification hook * feat(verification): encrypt verification token * feat(verification): send encrypted token to peer * feat(verification): verify peer * refactor(verification): use enum for verification state * feat(verification): expire verification requests * fix(updatePeer): update with fresh state data * feat(verification): display verification state * refactor(usePeerVerification): store verification timer in Peer * feat(verification): present tooltips explaining verification state * feat(ui): show full page loading indicator * feat(init): present bootup failure reasons * refactor(init): move init to its own file * feat(verification): show errors upon verification failure * refactor(verification): move workaround to usePeerVerification * feat(verification): present peer public keys * refactor(verification): move peer public key rendering to its own component * refactor(verification): only pass publicKey into renderer * feat(verification): show user's own public key * refactor(naming): rename Username to UserInfo * refactor(loading): encapsulate height styling * feat(verification): improve user messaging * refactor(style): improve formatting and variable names * feat(verification): add user info tooltip * docs(verification): explain verification
92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import { PropsWithChildren } from 'react'
|
|
import List from '@mui/material/List'
|
|
import ListItemIcon from '@mui/material/ListItemIcon'
|
|
import ListItemText from '@mui/material/ListItemText'
|
|
import Divider from '@mui/material/Divider'
|
|
import VolumeUp from '@mui/icons-material/VolumeUp'
|
|
import ListItem from '@mui/material/ListItem'
|
|
import Box from '@mui/material/Box'
|
|
import CircularProgress from '@mui/material/CircularProgress'
|
|
|
|
import { UserInfo } from 'components/UserInfo'
|
|
import { AudioState, Peer } from 'models/chat'
|
|
import { PeerConnectionType } from 'services/PeerRoom'
|
|
import { TrackerConnection } from 'services/ConnectionTest'
|
|
|
|
import { PeerListHeader } from './PeerListHeader'
|
|
import { PeerListItem } from './PeerListItem'
|
|
import { ConnectionTestResults as IConnectionTestResults } from './useConnectionTest'
|
|
|
|
export const peerListWidth = 300
|
|
|
|
export interface PeerListProps extends PropsWithChildren {
|
|
userId: string
|
|
roomId: string | undefined
|
|
onPeerListClose: () => void
|
|
peerList: Peer[]
|
|
peerConnectionTypes: Record<string, PeerConnectionType>
|
|
audioState: AudioState
|
|
peerAudios: Record<string, HTMLAudioElement>
|
|
connectionTestResults: IConnectionTestResults
|
|
}
|
|
|
|
export const PeerList = ({
|
|
userId,
|
|
roomId,
|
|
onPeerListClose,
|
|
peerList,
|
|
peerConnectionTypes,
|
|
audioState,
|
|
peerAudios,
|
|
connectionTestResults,
|
|
}: PeerListProps) => {
|
|
return (
|
|
<>
|
|
<PeerListHeader
|
|
onPeerListClose={onPeerListClose}
|
|
connectionTestResults={connectionTestResults}
|
|
/>
|
|
<Divider />
|
|
<List>
|
|
<ListItem divider={true}>
|
|
{audioState === AudioState.PLAYING && (
|
|
<ListItemIcon>
|
|
<VolumeUp />
|
|
</ListItemIcon>
|
|
)}
|
|
<ListItemText>
|
|
<UserInfo userId={userId} />
|
|
</ListItemText>
|
|
</ListItem>
|
|
{peerList.map((peer: Peer) => (
|
|
<PeerListItem
|
|
key={peer.peerId}
|
|
peer={peer}
|
|
peerConnectionTypes={peerConnectionTypes}
|
|
peerAudios={peerAudios}
|
|
/>
|
|
))}
|
|
{peerList.length === 0 &&
|
|
typeof roomId === 'string' &&
|
|
connectionTestResults.trackerConnection ===
|
|
TrackerConnection.CONNECTED &&
|
|
connectionTestResults.hasHost ? (
|
|
<>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
m: 2,
|
|
}}
|
|
>
|
|
<CircularProgress size={16} sx={{ mr: 1.5 }} />
|
|
<span>Searching for peers...</span>
|
|
</Box>
|
|
</>
|
|
) : null}
|
|
</List>
|
|
</>
|
|
)
|
|
}
|