diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 4b0e7780a7f..9872ff320bd 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1031,7 +1031,7 @@ "description": "Label for back button in a conversation" }, "moreInfo": { - "message": "More Info...", + "message": "More Info", "description": "Shown on the drop-down menu for an individual message, takes you to message detail screen" }, "retrySend": { @@ -1280,6 +1280,20 @@ } } }, + "calling__you-have-blocked": { + "message": "You have blocked $name$", + "description": "when you block someone and cannot view their video", + "placeholders": { + "name": { + "content": "$1", + "example": "Henry Richard" + } + } + }, + "calling__block-info": { + "message": "You won't receive their audio or video and they won't receive yours.", + "description": "Shown in the modal dialog to describe how blocking works in a gorup call" + }, "alwaysRelayCallsDescription": { "message": "Always relay calls", "description": "Description of the always relay calls setting" diff --git a/images/icons/v2/block-24.svg b/images/icons/v2/block-24.svg new file mode 100644 index 00000000000..ad2f5e5459b --- /dev/null +++ b/images/icons/v2/block-24.svg @@ -0,0 +1 @@ +block-24 \ No newline at end of file diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 022db0ed9e8..6b2dc916e94 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -6301,6 +6301,30 @@ button.module-image__border-overlay:focus { background-color: $color-gray-75; } + &__blocked { + @include color-svg('../images/icons/v2/block-24.svg', $color-white); + height: 24px; + margin-bottom: 16px; + width: 24px; + + &--info { + @include button-reset; + background-color: $color-gray-75; + border-radius: 16px; + color: $color-white; + line-height: 16px; + padding: 3px 10px; + } + + &--modal-title { + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + } + } + &--title { @include font-caption; background: linear-gradient( diff --git a/ts/components/CallScreen.stories.tsx b/ts/components/CallScreen.stories.tsx index 8490c43a2ec..e8f9f05b1d6 100644 --- a/ts/components/CallScreen.stories.tsx +++ b/ts/components/CallScreen.stories.tsx @@ -191,6 +191,7 @@ story.add('Group call - 1', () => ( demuxId: 0, hasRemoteAudio: true, hasRemoteVideo: true, + isBlocked: false, isSelf: false, title: 'Tyler', videoAspectRatio: 1.3, @@ -209,6 +210,7 @@ story.add('Group call - Many', () => ( demuxId: 0, hasRemoteAudio: true, hasRemoteVideo: true, + isBlocked: false, isSelf: false, title: 'Amy', videoAspectRatio: 1.3, @@ -217,6 +219,7 @@ story.add('Group call - Many', () => ( demuxId: 1, hasRemoteAudio: true, hasRemoteVideo: true, + isBlocked: false, isSelf: true, title: 'Bob', videoAspectRatio: 1.3, @@ -225,6 +228,7 @@ story.add('Group call - Many', () => ( demuxId: 2, hasRemoteAudio: true, hasRemoteVideo: true, + isBlocked: true, isSelf: false, title: 'Alice', videoAspectRatio: 1.3, @@ -246,6 +250,7 @@ story.add('Group call - reconnecting', () => ( demuxId: 0, hasRemoteAudio: true, hasRemoteVideo: true, + isBlocked: false, isSelf: false, title: 'Tyler', videoAspectRatio: 1.3, diff --git a/ts/components/CallingParticipantsList.stories.tsx b/ts/components/CallingParticipantsList.stories.tsx index 8a962c162be..6626d82d866 100644 --- a/ts/components/CallingParticipantsList.stories.tsx +++ b/ts/components/CallingParticipantsList.stories.tsx @@ -23,6 +23,7 @@ function createParticipant( demuxId: 2, hasRemoteAudio: Boolean(participantProps.hasRemoteAudio), hasRemoteVideo: Boolean(participantProps.hasRemoteVideo), + isBlocked: Boolean(participantProps.isBlocked), isSelf: Boolean(participantProps.isSelf), name: participantProps.name, profileName: participantProps.title, diff --git a/ts/components/GroupCallRemoteParticipant.stories.tsx b/ts/components/GroupCallRemoteParticipant.stories.tsx index 572f1c21be0..6d6b364fa2b 100644 --- a/ts/components/GroupCallRemoteParticipant.stories.tsx +++ b/ts/components/GroupCallRemoteParticipant.stories.tsx @@ -15,7 +15,10 @@ 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 = {}): any => ({ +const createProps = ( + overrideProps: Partial = {}, + isBlocked?: boolean +): any => ({ // eslint-disable-next-line @typescript-eslint/no-explicit-any getGroupCallVideoFrameSource: noop as any, i18n, @@ -23,6 +26,7 @@ const createProps = (overrideProps: Partial = {}): any => ({ demuxId: 123, hasRemoteAudio: false, hasRemoteVideo: true, + isBlocked: Boolean(isBlocked), 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', @@ -52,3 +56,18 @@ story.add('isInPip', () => ( })} /> )); + +story.add('Blocked', () => ( + +)); diff --git a/ts/components/GroupCallRemoteParticipant.tsx b/ts/components/GroupCallRemoteParticipant.tsx index 5e8e76a3611..5da870595cd 100644 --- a/ts/components/GroupCallRemoteParticipant.tsx +++ b/ts/components/GroupCallRemoteParticipant.tsx @@ -18,6 +18,8 @@ import { import { LocalizerType } from '../types/Util'; import { CallBackgroundBlur } from './CallBackgroundBlur'; import { Avatar, AvatarSize } from './Avatar'; +import { ConfirmationModal } from './ConfirmationModal'; +import { Intl } from './Intl'; import { ContactName } from './conversation/ContactName'; // The max size video frame we'll support (in RGBA) @@ -45,20 +47,22 @@ export type PropsType = BasePropsType & (InPipPropsType | NotInPipPropsType); export const GroupCallRemoteParticipant: React.FC = React.memo( props => { - const { getGroupCallVideoFrameSource } = props; + const { getGroupCallVideoFrameSource, i18n } = props; const { avatarPath, color, - profileName, - title, demuxId, hasRemoteAudio, hasRemoteVideo, + isBlocked, + profileName, + title, } = props.remoteParticipant; const [isWide, setIsWide] = useState(true); const [hasHover, setHover] = useState(false); + const [showBlockInfo, setShowBlockInfo] = useState(false); const remoteVideoRef = useRef(null); const canvasContextRef = useRef(null); @@ -173,6 +177,45 @@ export const GroupCallRemoteParticipant: React.FC = React.memo( } const showHover = hasHover && !props.isInPip; + const canShowVideo = hasRemoteVideo && !isBlocked; + + if (showBlockInfo) { + return ( + { + setShowBlockInfo(false); + }} + title={ +
+ , + ]} + /> +
+ } + actions={[ + { + text: i18n('ok'), + action: () => { + setShowBlockInfo(false); + }, + style: 'affirmative', + }, + ]} + > + {i18n('calling__block-info')} +
+ ); + } return (
= React.memo( module="module-ongoing-call__group-call-remote-participant--contact-name" profileName={profileName} title={title} - i18n={props.i18n} + i18n={i18n} />
)} - {hasRemoteVideo ? ( + {canShowVideo ? ( = React.memo( /> ) : ( - + {isBlocked ? ( + <> + + + + ) : ( + + )} )} diff --git a/ts/state/smart/CallManager.tsx b/ts/state/smart/CallManager.tsx index f75f2ce58d0..b43b4e360dc 100644 --- a/ts/state/smart/CallManager.tsx +++ b/ts/state/smart/CallManager.tsx @@ -99,6 +99,7 @@ const mapStateToActiveCallProp = (state: StateType) => { firstName: remoteConversation.firstName, hasRemoteAudio: remoteParticipant.hasRemoteAudio, hasRemoteVideo: remoteParticipant.hasRemoteVideo, + isBlocked: Boolean(remoteConversation.isBlocked), isSelf: remoteParticipant.isSelf, name: remoteConversation.name, profileName: remoteConversation.profileName, @@ -108,6 +109,8 @@ const mapStateToActiveCallProp = (state: StateType) => { }); } ); + + groupCallParticipants.sort((a, b) => a.title.localeCompare(b.title)); } return { diff --git a/ts/types/Calling.ts b/ts/types/Calling.ts index 0269d0b00a7..f0ea4d8426e 100644 --- a/ts/types/Calling.ts +++ b/ts/types/Calling.ts @@ -75,6 +75,7 @@ export interface GroupCallRemoteParticipantType { firstName?: string; hasRemoteAudio: boolean; hasRemoteVideo: boolean; + isBlocked: boolean; isSelf: boolean; name?: string; profileName?: string; diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 46d19220fa3..82d62c848f7 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -14562,7 +14562,7 @@ "rule": "React-useRef", "path": "ts/components/GroupCallRemoteParticipant.js", "line": " const remoteVideoRef = react_1.useRef(null);", - "lineNumber": 28, + "lineNumber": 31, "reasonCategory": "usageTrusted", "updated": "2020-11-11T21:56:04.179Z", "reasonDetail": "Needed to render the remote video element." @@ -14571,7 +14571,7 @@ "rule": "React-useRef", "path": "ts/components/GroupCallRemoteParticipant.js", "line": " const canvasContextRef = react_1.useRef(null);", - "lineNumber": 29, + "lineNumber": 32, "reasonCategory": "usageTrusted", "updated": "2020-11-17T23:29:38.698Z", "reasonDetail": "Doesn't touch the DOM." @@ -14580,7 +14580,7 @@ "rule": "React-useRef", "path": "ts/components/GroupCallRemoteParticipant.js", "line": " const frameBufferRef = react_1.useRef(new ArrayBuffer(FRAME_BUFFER_SIZE));", - "lineNumber": 30, + "lineNumber": 33, "reasonCategory": "usageTrusted", "updated": "2020-11-17T16:24:25.480Z", "reasonDetail": "Doesn't touch the DOM."