Group Calling: show participant name on hover
This commit is contained in:
parent
5cc7c9a66a
commit
6a6f8e28ce
5 changed files with 145 additions and 45 deletions
|
@ -6281,17 +6281,33 @@ button.module-image__border-overlay:focus {
|
|||
background-color: $color-gray-75;
|
||||
}
|
||||
|
||||
&--audio-muted::before {
|
||||
&--title {
|
||||
@include font-caption;
|
||||
background: linear-gradient($color-black-alpha-40, transparent);
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
padding: 6px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&--contact-name {
|
||||
margin-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&--audio-muted::after {
|
||||
@include color-svg(
|
||||
'../images/icons/v2/mic-off-solid-28.svg',
|
||||
$color-white
|
||||
);
|
||||
bottom: 12px;
|
||||
content: '';
|
||||
height: 28px;
|
||||
height: 14px;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
width: 28px;
|
||||
right: 6px;
|
||||
width: 14px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
@ -6461,7 +6477,7 @@ button.module-image__border-overlay:focus {
|
|||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.module-ongoing-call__group-call-remote-participant--audio-muted::before {
|
||||
.module-ongoing-call__group-call-remote-participant--audio-muted::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,44 @@ import { LocalizerType } from '../types/Util';
|
|||
import { CallMode, VideoFrameSource } from '../types/Calling';
|
||||
import { ActiveCallType, SetRendererCanvasType } from '../state/ducks/calling';
|
||||
|
||||
const NoVideo = ({
|
||||
activeCall,
|
||||
i18n,
|
||||
}: {
|
||||
activeCall: ActiveCallType;
|
||||
i18n: LocalizerType;
|
||||
}): JSX.Element => {
|
||||
const {
|
||||
avatarPath,
|
||||
color,
|
||||
name,
|
||||
phoneNumber,
|
||||
profileName,
|
||||
title,
|
||||
} = activeCall.conversation;
|
||||
|
||||
return (
|
||||
<div className="module-calling-pip__video--remote">
|
||||
<CallBackgroundBlur avatarPath={avatarPath} color={color}>
|
||||
<div className="module-calling-pip__video--avatar">
|
||||
<Avatar
|
||||
avatarPath={avatarPath}
|
||||
color={color || 'ultramarine'}
|
||||
noteToSelf={false}
|
||||
conversationType="direct"
|
||||
i18n={i18n}
|
||||
name={name}
|
||||
phoneNumber={phoneNumber}
|
||||
profileName={profileName}
|
||||
title={title}
|
||||
size={52}
|
||||
/>
|
||||
</div>
|
||||
</CallBackgroundBlur>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export interface PropsType {
|
||||
activeCall: ActiveCallType;
|
||||
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
|
||||
|
@ -27,35 +65,7 @@ export const CallingPipRemoteVideo = ({
|
|||
|
||||
if (call.callMode === CallMode.Direct) {
|
||||
if (!call.hasRemoteVideo) {
|
||||
const {
|
||||
avatarPath,
|
||||
color,
|
||||
name,
|
||||
phoneNumber,
|
||||
profileName,
|
||||
title,
|
||||
} = conversation;
|
||||
|
||||
return (
|
||||
<div className="module-calling-pip__video--remote">
|
||||
<CallBackgroundBlur avatarPath={avatarPath} color={color}>
|
||||
<div className="module-calling-pip__video--avatar">
|
||||
<Avatar
|
||||
avatarPath={avatarPath}
|
||||
color={color || 'ultramarine'}
|
||||
noteToSelf={false}
|
||||
conversationType="direct"
|
||||
i18n={i18n}
|
||||
name={name}
|
||||
phoneNumber={phoneNumber}
|
||||
profileName={profileName}
|
||||
title={title}
|
||||
size={52}
|
||||
/>
|
||||
</div>
|
||||
</CallBackgroundBlur>
|
||||
</div>
|
||||
);
|
||||
return <NoVideo activeCall={activeCall} i18n={i18n} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -74,6 +84,10 @@ export const CallingPipRemoteVideo = ({
|
|||
const { groupCallParticipants } = activeCall;
|
||||
const speaker = groupCallParticipants[0];
|
||||
|
||||
if (!speaker) {
|
||||
return <NoVideo activeCall={activeCall} i18n={i18n} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="module-calling-pip__video--remote">
|
||||
<GroupCallRemoteParticipant
|
||||
|
|
54
ts/components/GroupCallRemoteParticipant.stories.tsx
Normal file
54
ts/components/GroupCallRemoteParticipant.stories.tsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import { noop } from 'lodash';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
|
||||
import {
|
||||
GroupCallRemoteParticipant,
|
||||
PropsType,
|
||||
} from './GroupCallRemoteParticipant';
|
||||
import { setup as setupI18n } from '../../js/modules/i18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const createProps = (overrideProps: Partial<PropsType> = {}): any => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getGroupCallVideoFrameSource: noop as any,
|
||||
i18n,
|
||||
remoteParticipant: {
|
||||
demuxId: 123,
|
||||
hasRemoteAudio: false,
|
||||
hasRemoteVideo: true,
|
||||
isSelf: false,
|
||||
title:
|
||||
'Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso',
|
||||
videoAspectRatio: 1.3,
|
||||
},
|
||||
...overrideProps,
|
||||
});
|
||||
|
||||
const story = storiesOf('Components/GroupCallRemoteParticipant', module);
|
||||
|
||||
story.add('Default', () => (
|
||||
<GroupCallRemoteParticipant
|
||||
{...createProps({
|
||||
isInPip: false,
|
||||
height: 120,
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 120,
|
||||
})}
|
||||
/>
|
||||
));
|
||||
|
||||
story.add('isInPip', () => (
|
||||
<GroupCallRemoteParticipant
|
||||
{...createProps({
|
||||
isInPip: true,
|
||||
})}
|
||||
/>
|
||||
));
|
|
@ -18,6 +18,7 @@ import {
|
|||
import { LocalizerType } from '../types/Util';
|
||||
import { CallBackgroundBlur } from './CallBackgroundBlur';
|
||||
import { Avatar, AvatarSize } from './Avatar';
|
||||
import { ContactName } from './conversation/ContactName';
|
||||
|
||||
// The max size video frame we'll support (in RGBA)
|
||||
const FRAME_BUFFER_SIZE = 1920 * 1080 * 4;
|
||||
|
@ -40,7 +41,7 @@ interface NotInPipPropsType {
|
|||
width: number;
|
||||
}
|
||||
|
||||
type PropsType = BasePropsType & (InPipPropsType | NotInPipPropsType);
|
||||
export type PropsType = BasePropsType & (InPipPropsType | NotInPipPropsType);
|
||||
|
||||
export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
||||
props => {
|
||||
|
@ -57,6 +58,7 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
|||
} = props.remoteParticipant;
|
||||
|
||||
const [isWide, setIsWide] = useState(true);
|
||||
const [hasHover, setHover] = useState(false);
|
||||
|
||||
const remoteVideoRef = useRef<HTMLCanvasElement | null>(null);
|
||||
const canvasContextRef = useRef<CanvasRenderingContext2D | null>(null);
|
||||
|
@ -172,14 +174,28 @@ export const GroupCallRemoteParticipant: React.FC<PropsType> = React.memo(
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'module-ongoing-call__group-call-remote-participant',
|
||||
{
|
||||
'module-ongoing-call__group-call-remote-participant--audio-muted': !hasRemoteAudio,
|
||||
}
|
||||
)}
|
||||
className="module-ongoing-call__group-call-remote-participant"
|
||||
onMouseEnter={() => setHover(true)}
|
||||
onMouseLeave={() => setHover(false)}
|
||||
style={containerStyles}
|
||||
>
|
||||
{hasHover && (
|
||||
<div
|
||||
className={classNames(
|
||||
'module-ongoing-call__group-call-remote-participant--title',
|
||||
{
|
||||
'module-ongoing-call__group-call-remote-participant--audio-muted': !hasRemoteAudio,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ContactName
|
||||
module="module-ongoing-call__group-call-remote-participant--contact-name"
|
||||
profileName={profileName}
|
||||
title={title}
|
||||
i18n={props.i18n}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{hasRemoteVideo ? (
|
||||
<canvas
|
||||
className="module-ongoing-call__group-call-remote-participant__remote-video"
|
||||
|
|
|
@ -14571,7 +14571,7 @@
|
|||
"rule": "React-useRef",
|
||||
"path": "ts/components/GroupCallRemoteParticipant.js",
|
||||
"line": " const remoteVideoRef = react_1.useRef(null);",
|
||||
"lineNumber": 26,
|
||||
"lineNumber": 28,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-11-11T21:56:04.179Z",
|
||||
"reasonDetail": "Needed to render the remote video element."
|
||||
|
@ -14580,7 +14580,7 @@
|
|||
"rule": "React-useRef",
|
||||
"path": "ts/components/GroupCallRemoteParticipant.js",
|
||||
"line": " const canvasContextRef = react_1.useRef(null);",
|
||||
"lineNumber": 27,
|
||||
"lineNumber": 29,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-11-17T23:29:38.698Z",
|
||||
"reasonDetail": "Doesn't touch the DOM."
|
||||
|
@ -14589,7 +14589,7 @@
|
|||
"rule": "React-useRef",
|
||||
"path": "ts/components/GroupCallRemoteParticipant.js",
|
||||
"line": " const frameBufferRef = react_1.useRef(new ArrayBuffer(FRAME_BUFFER_SIZE));",
|
||||
"lineNumber": 28,
|
||||
"lineNumber": 30,
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2020-11-17T16:24:25.480Z",
|
||||
"reasonDetail": "Doesn't touch the DOM."
|
||||
|
|
Loading…
Reference in a new issue