Voice rooms prototype (#8084)

* Add voice room labs flag

Signed-off-by: Robin Townsend <robin@robin.town>

* Add more widget actions for interacting with Jitsi

Signed-off-by: Robin Townsend <robin@robin.town>

* Factor out a more generic Jitsi creation utility

Signed-off-by: Robin Townsend <robin@robin.town>

* Add utilities for managing voice channels

Signed-off-by: Robin Townsend <robin@robin.town>

* Enable creation of voice rooms

Signed-off-by: Robin Townsend <robin@robin.town>

* Force a maximized view of voice channel widgets

Signed-off-by: Robin Townsend <robin@robin.town>

* Add voice channel store

Signed-off-by: Robin Townsend <robin@robin.town>

* Factor out a more generic FacePile

Signed-off-by: Robin Townsend <robin@robin.town>

* Implement room tile changes for voice rooms

Signed-off-by: Robin Townsend <robin@robin.town>

* Add interactive radio component to the left panel

Signed-off-by: Robin Townsend <robin@robin.town>

* Test voice rooms

Signed-off-by: Robin Townsend <robin@robin.town>

* Update name of call room type

Signed-off-by: Robin Townsend <robin@robin.town>

* Clarify that voice rooms are under development

Signed-off-by: Robin Townsend <robin@robin.town>

* Use readonly

Signed-off-by: Robin Townsend <robin@robin.town>

* Move acks to the end of handlers

Signed-off-by: Robin Townsend <robin@robin.town>

* Add comment about avatar URLs coming from Jitsi

Signed-off-by: Robin Townsend <robin@robin.town>

* Don't use unicode ellipses

for translation reasons?

Signed-off-by: Robin Townsend <robin@robin.town>

* Fix tests

Signed-off-by: Robin Townsend <robin@robin.town>

* Fix tests, again

Signed-off-by: Robin Townsend <robin@robin.town>

* Remove unnecessary export

Signed-off-by: Robin Townsend <robin@robin.town>

* Ack Jitsi events when we wait for them

Signed-off-by: Robin Townsend <robin@robin.town>
This commit is contained in:
Robin 2022-03-22 18:14:11 -04:00 committed by GitHub
parent f416a970ca
commit cfabcdda35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1302 additions and 238 deletions

View file

@ -26,17 +26,48 @@ import TextWithTooltip from "../elements/TextWithTooltip";
import { useRoomMembers } from "../../../hooks/useRoomMembers";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
interface IProps extends HTMLAttributes<HTMLSpanElement> {
faces: ReactNode[];
overflow: boolean;
tooltip?: ReactNode;
children?: ReactNode;
}
const FacePile = ({ faces, overflow, tooltip, children, ...props }: IProps) => {
const pileContents = <>
{ overflow ? <span className="mx_FacePile_more" /> : null }
{ faces }
</>;
return <div {...props} className="mx_FacePile">
{ tooltip ? (
<TextWithTooltip class="mx_FacePile_faces" tooltip={tooltip} tooltipProps={{ yOffset: 32 }}>
{ pileContents }
</TextWithTooltip>
) : (
<div className="mx_FacePile_faces">
{ pileContents }
</div>
) }
{ children }
</div>;
};
export default FacePile;
const DEFAULT_NUM_FACES = 5;
interface IProps extends HTMLAttributes<HTMLSpanElement> {
const isKnownMember = (member: RoomMember) => !!DMRoomMap.shared().getDMRoomsForUserId(member.userId)?.length;
interface IRoomProps extends HTMLAttributes<HTMLSpanElement> {
room: Room;
onlyKnownUsers?: boolean;
numShown?: number;
}
const isKnownMember = (member: RoomMember) => !!DMRoomMap.shared().getDMRoomsForUserId(member.userId)?.length;
const FacePile = ({ room, onlyKnownUsers = true, numShown = DEFAULT_NUM_FACES, ...props }: IProps) => {
export const RoomFacePile = (
{ room, onlyKnownUsers = true, numShown = DEFAULT_NUM_FACES, ...props }: IRoomProps,
) => {
const cli = useContext(MatrixClientContext);
const isJoined = room.getMyMembership() === "join";
let members = useRoomMembers(room);
@ -58,6 +89,8 @@ const FacePile = ({ room, onlyKnownUsers = true, numShown = DEFAULT_NUM_FACES, .
// We reverse the order of the shown faces in CSS to simplify their visual overlap,
// reverse members in tooltip order to make the order between the two match up.
const commaSeparatedMembers = shownMembers.map(m => m.rawDisplayName).reverse().join(", ");
const faces = shownMembers.map(m =>
<MemberAvatar key={m.userId} member={m} width={28} height={28} />);
let tooltip: ReactNode;
if (props.onClick) {
@ -90,16 +123,9 @@ const FacePile = ({ room, onlyKnownUsers = true, numShown = DEFAULT_NUM_FACES, .
}
}
return <div {...props} className="mx_FacePile">
<TextWithTooltip class="mx_FacePile_faces" tooltip={tooltip} tooltipProps={{ yOffset: 32 }}>
{ members.length > numShown ? <span className="mx_FacePile_face mx_FacePile_more" /> : null }
{ shownMembers.map(m =>
<MemberAvatar key={m.userId} member={m} width={28} height={28} className="mx_FacePile_face" />) }
</TextWithTooltip>
return <FacePile faces={faces} overflow={members.length > numShown} tooltip={tooltip}>
{ onlyKnownUsers && <span className="mx_FacePile_summary">
{ _t("%(count)s people you know have already joined", { count: members.length }) }
</span> }
</div>;
</FacePile>;
};
export default FacePile;