|
|
|
/*
|
|
|
|
* https://github.com/morethanwords/tweb
|
|
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
|
|
*/
|
|
|
|
|
|
|
|
import PopupElement from "../popups";
|
|
|
|
import { hexToRgb } from "../../helpers/color";
|
|
|
|
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
|
|
|
import customProperties from "../../helpers/dom/customProperties";
|
|
|
|
import { GroupCall, GroupCallParticipant } from "../../layer";
|
|
|
|
import type { AppChatsManager } from "../../lib/appManagers/appChatsManager";
|
|
|
|
import type { AppGroupCallsManager } from "../../lib/appManagers/appGroupCallsManager";
|
|
|
|
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
|
|
|
import GROUP_CALL_STATE from "../../lib/calls/groupCallState";
|
|
|
|
import { RLottieColor } from "../../lib/rlottie/rlottiePlayer";
|
|
|
|
import rootScope from "../../lib/rootScope";
|
|
|
|
import ButtonIcon from "../buttonIcon";
|
|
|
|
import GroupCallMicrophoneIcon from "./microphoneIcon";
|
|
|
|
import GroupCallParticipantsElement from "./participants";
|
|
|
|
import GroupCallParticipantsVideoElement from "./participantVideos";
|
|
|
|
import PopupPeer from "../popups/peer";
|
|
|
|
import GroupCallDescriptionElement from "./description";
|
|
|
|
import GroupCallTitleElement from "./title";
|
|
|
|
import { addFullScreenListener, cancelFullScreen, isFullScreen, requestFullScreen } from "../../helpers/dom/fullScreen";
|
|
|
|
import Scrollable from "../scrollable";
|
|
|
|
import { MovableState } from "../movableElement";
|
|
|
|
import animationIntersector from "../animationIntersector";
|
|
|
|
import { IS_APPLE_MOBILE } from "../../environment/userAgent";
|
|
|
|
import throttle from "../../helpers/schedulers/throttle";
|
|
|
|
import IS_SCREEN_SHARING_SUPPORTED from "../../environment/screenSharingSupport";
|
|
|
|
import GroupCallInstance from "../../lib/calls/groupCallInstance";
|
|
|
|
import makeButton from "../call/button";
|
|
|
|
import MovablePanel from "../../helpers/movablePanel";
|
|
|
|
import findUpClassName from "../../helpers/dom/findUpClassName";
|
|
|
|
import safeAssign from "../../helpers/object/safeAssign";
|
|
|
|
import toggleClassName from "../../helpers/toggleClassName";
|
|
|
|
import { AppManagers } from "../../lib/appManagers/managers";
|
|
|
|
import themeController from "../../helpers/themeController";
|
|
|
|
import groupCallsController from "../../lib/calls/groupCallsController";
|
|
|
|
|
|
|
|
export enum GROUP_CALL_PARTICIPANT_MUTED_STATE {
|
|
|
|
UNMUTED,
|
|
|
|
MUTED,
|
|
|
|
MUTED_FOR_ME,
|
|
|
|
MUTED_BY_ADMIN,
|
|
|
|
HAND
|
|
|
|
}
|
|
|
|
|
|
|
|
export type GROUP_CALL_PARTICIPANT_CLEARED_MUTED_STATE = Exclude<GROUP_CALL_PARTICIPANT_MUTED_STATE, GROUP_CALL_PARTICIPANT_MUTED_STATE.MUTED_BY_ADMIN | GROUP_CALL_PARTICIPANT_MUTED_STATE.MUTED_FOR_ME>;
|
|
|
|
|
|
|
|
export function getGroupCallParticipantMutedState(participant: GroupCallParticipant) {
|
|
|
|
const states = GROUP_CALL_PARTICIPANT_MUTED_STATE;
|
|
|
|
if(participant.pFlags.muted_by_you) {
|
|
|
|
return states.MUTED_FOR_ME;
|
|
|
|
} else if(participant.raise_hand_rating !== undefined) {
|
|
|
|
return states.HAND;
|
|
|
|
} else if(participant.pFlags.muted) {
|
|
|
|
return participant.pFlags.can_self_unmute ? states.MUTED : states.MUTED_BY_ADMIN;
|
|
|
|
} else {
|
|
|
|
return states.UNMUTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function clearMutedStateModifier(state: GROUP_CALL_PARTICIPANT_MUTED_STATE): GROUP_CALL_PARTICIPANT_CLEARED_MUTED_STATE {
|
|
|
|
const states = GROUP_CALL_PARTICIPANT_MUTED_STATE;
|
|
|
|
switch(state) {
|
|
|
|
case states.MUTED_BY_ADMIN:
|
|
|
|
case states.MUTED_FOR_ME:
|
|
|
|
return states.MUTED;
|
|
|
|
default:
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getColorByMutedState(state: GROUP_CALL_PARTICIPANT_MUTED_STATE) {
|
|
|
|
const states = GROUP_CALL_PARTICIPANT_MUTED_STATE;
|
|
|
|
let color: RLottieColor, colorStr: 'blue' | 'green' | 'secondary' | 'red';
|
|
|
|
switch(state) {
|
|
|
|
case states.HAND:
|
|
|
|
colorStr = 'blue';
|
|
|
|
break;
|
|
|
|
case states.MUTED:
|
|
|
|
case states.MUTED_FOR_ME:
|
|
|
|
case states.MUTED_BY_ADMIN:
|
|
|
|
colorStr = state === states.MUTED ? 'secondary' : 'red';
|
|
|
|
break;
|
|
|
|
case states.UNMUTED:
|
|
|
|
colorStr = 'green';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
const propertyValue = customProperties.getProperty('gc-' + colorStr + '-text-color');
|
|
|
|
color = hexToRgb(propertyValue);
|
|
|
|
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum GROUP_CALL_MICROPHONE_BUTTON_STATE {
|
|
|
|
HAND,
|
|
|
|
MUTED,
|
|
|
|
UNMUTED,
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getGroupCallMicrophoneButtonState(groupCall: GroupCall.groupCall, participant: GroupCallParticipant) {
|
|
|
|
const states = GROUP_CALL_MICROPHONE_BUTTON_STATE;
|
|
|
|
if(!participant.pFlags.can_self_unmute) {
|
|
|
|
return states.HAND;
|
|
|
|
} else if(participant.pFlags.muted) {
|
|
|
|
return states.MUTED
|
|
|
|
} else {
|
|
|
|
return states.UNMUTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let previousState: MovableState = {
|
|
|
|
width: 420,
|
|
|
|
height: 640
|
|
|
|
};
|
|
|
|
|
|
|
|
const className = 'group-call';
|
|
|
|
|
|
|
|
export default class PopupGroupCall extends PopupElement {
|
|
|
|
private instance: GroupCallInstance;
|
|
|
|
private groupCallTitle: GroupCallTitleElement;
|
|
|
|
private groupCallDescription: GroupCallDescriptionElement;
|
|
|
|
private groupCallBodyHeaderDescription: GroupCallDescriptionElement;
|
|
|
|
private groupCallParticipants: GroupCallParticipantsElement;
|
|
|
|
private groupCallParticipantsVideo: GroupCallParticipantsVideoElement;
|
|
|
|
private groupCallMicrophoneIcon: GroupCallMicrophoneIcon;
|
|
|
|
private videosCount: number;
|
|
|
|
private btnFullScreen: HTMLButtonElement;
|
|
|
|
private btnExitFullScreen: HTMLButtonElement;
|
|
|
|
private btnInvite: HTMLButtonElement;
|
|
|
|
private btnShowColumn: HTMLButtonElement;
|
|
|
|
private movablePanel: MovablePanel;
|
|
|
|
private buttonsContainer: HTMLDivElement;
|
|
|
|
private btnFullScreen2: HTMLButtonElement;
|
|
|
|
private btnVideo: HTMLDivElement;
|
|
|
|
private btnScreen: HTMLDivElement;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super('popup-group-call', {
|
|
|
|
body: true,
|
|
|
|
withoutOverlay: true,
|
|
|
|
closable: true,
|
|
|
|
title: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.videosCount = 0;
|
|
|
|
this.container.classList.add(className, 'night');
|
|
|
|
|
|
|
|
const instance = this.instance = groupCallsController.groupCall;
|
|
|
|
const {listenerSetter} = this;
|
|
|
|
|
|
|
|
if(!IS_APPLE_MOBILE) {
|
|
|
|
const btnFullScreen = this.btnFullScreen = ButtonIcon('fullscreen');
|
|
|
|
const btnFullScreen2 = this.btnFullScreen2 = ButtonIcon('fullscreen ' + className + '-cfs');
|
|
|
|
const btnExitFullScreen = this.btnExitFullScreen = ButtonIcon('smallscreen');
|
|
|
|
|
|
|
|
attachClickEvent(btnFullScreen, this.onFullScreenClick, {listenerSetter});
|
|
|
|
attachClickEvent(btnFullScreen2, this.onFullScreenClick, {listenerSetter});
|
|
|
|
|
|
|
|
attachClickEvent(btnExitFullScreen, () => {
|
|
|
|
cancelFullScreen();
|
|
|
|
}, {listenerSetter});
|
|
|
|
|
|
|
|
addFullScreenListener(this.container, this.onFullScreenChange, listenerSetter);
|
|
|
|
}
|
|
|
|
|
|
|
|
const btnInvite = this.btnInvite = ButtonIcon('adduser');
|
|
|
|
const btnShowColumn = this.btnShowColumn = ButtonIcon('rightpanel ' + className + '-only-big');
|
|
|
|
|
|
|
|
attachClickEvent(btnShowColumn, this.toggleRightColumn, {listenerSetter});
|
|
|
|
|
|
|
|
const headerInfo = document.createElement('div');
|
|
|
|
headerInfo.classList.add(className + '-header-info');
|
|
|
|
|
|
|
|
this.title.classList.add(className + '-header-title');
|
|
|
|
|
|
|
|
const subtitle = document.createElement('div');
|
|
|
|
subtitle.classList.add(className + '-header-subtitle');
|
|
|
|
|
|
|
|
headerInfo.append(this.title, subtitle);
|
|
|
|
|
|
|
|
this.header.classList.add(className + '-header');
|
|
|
|
this.header.append(...[this.btnExitFullScreen, headerInfo/* , btnInvite */, this.btnFullScreen, btnShowColumn].filter(Boolean));
|
|
|
|
|
|
|
|
const newHeader = this.header.cloneNode(false) as HTMLElement;
|
|
|
|
const newHeaderInfo = headerInfo.cloneNode(false) as HTMLElement;
|
|
|
|
const newHeaderTitle = this.title.cloneNode(false) as HTMLElement;
|
|
|
|
|
|
|
|
newHeaderInfo.append(newHeaderTitle);
|
|
|
|
|
|
|
|
const btnHideColumn = ButtonIcon('rightpanel');
|
|
|
|
newHeader.append(...[btnHideColumn, newHeaderInfo, this.btnFullScreen2].filter(Boolean));
|
|
|
|
|
|
|
|
attachClickEvent(btnHideColumn, this.toggleRightColumn, {listenerSetter});
|
|
|
|
|
|
|
|
this.body.prepend(newHeader);
|
|
|
|
|
|
|
|
const videosScrollable = new Scrollable(undefined);
|
|
|
|
videosScrollable.container.classList.add('group-call-big-video-container');
|
|
|
|
this.container.append(videosScrollable.container);
|
|
|
|
|
|
|
|
this.groupCallTitle = new GroupCallTitleElement(this.title);
|
|
|
|
this.groupCallDescription = new GroupCallDescriptionElement(subtitle);
|
|
|
|
this.groupCallBodyHeaderDescription = new GroupCallDescriptionElement(newHeaderTitle);
|
|
|
|
this.constructButtons();
|
|
|
|
|
|
|
|
this.groupCallParticipantsVideo = new GroupCallParticipantsVideoElement({
|
|
|
|
appendTo: videosScrollable.container,
|
|
|
|
instance,
|
|
|
|
listenerSetter,
|
|
|
|
displayPinned: true,
|
|
|
|
onLengthChange: (length) => {
|
|
|
|
this.videosCount = length;
|
|
|
|
this.toggleBigLayout();
|
|
|
|
},
|
|
|
|
managers: this.managers
|
|
|
|
});
|
|
|
|
this.groupCallParticipants = new GroupCallParticipantsElement({
|
|
|
|
appendTo: this.body,
|
|
|
|
instance,
|
|
|
|
listenerSetter,
|
|
|
|
managers: this.managers
|
|
|
|
});
|
|
|
|
|
|
|
|
this.movablePanel = new MovablePanel({
|
|
|
|
listenerSetter,
|
|
|
|
movableOptions: {
|
|
|
|
minWidth: 400,
|
|
|
|
minHeight: 480,
|
|
|
|
element: this.element,
|
|
|
|
verifyTouchTarget: (e) => {
|
|
|
|
const target = e.target;
|
|
|
|
if(findUpClassName(target, 'chatlist') ||
|
|
|
|
findUpClassName(target, 'group-call-button') ||
|
|
|
|
findUpClassName(target, 'btn-icon') ||
|
|
|
|
findUpClassName(target, 'group-call-participants-video-container') ||
|
|
|
|
isFullScreen()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onResize: () => this.toggleBigLayout(),
|
|
|
|
previousState
|
|
|
|
});
|
|
|
|
|
|
|
|
listenerSetter.add(instance)('state', () => {
|
|
|
|
this.updateInstance();
|
|
|
|
});
|
|
|
|
|
|
|
|
listenerSetter.add(rootScope)('group_call_update', (groupCall) => {
|
|
|
|
if(this.instance?.id === groupCall.id) {
|
|
|
|
this.updateInstance();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
listenerSetter.add(instance)('pinned', () => {
|
|
|
|
this.setHasPinned();
|
|
|
|
});
|
|
|
|
|
|
|
|
listenerSetter.add(this.groupCallParticipantsVideo)('toggleControls', this.onToggleControls);
|
|
|
|
|
|
|
|
this.addEventListener('close', () => {
|
|
|
|
const {movablePanel} = this;
|
|
|
|
previousState = movablePanel.state;
|
|
|
|
|
|
|
|
this.groupCallParticipantsVideo.destroy();
|
|
|
|
this.groupCallParticipants.destroy();
|
|
|
|
this.groupCallMicrophoneIcon.destroy();
|
|
|
|
|
|
|
|
movablePanel.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
this.toggleRightColumn();
|
|
|
|
this.onFullScreenChange();
|
|
|
|
|
|
|
|
this.updateInstance();
|
|
|
|
}
|
|
|
|
|
|
|
|
private constructButtons() {
|
|
|
|
const buttons = this.buttonsContainer = document.createElement('div');
|
|
|
|
buttons.classList.add(className + '-buttons');
|
|
|
|
|
|
|
|
const _makeButton = makeButton.bind(null, className, this.listenerSetter);
|
|
|
|
|
|
|
|
const btnVideo = this.btnVideo = _makeButton({
|
|
|
|
// text: 'VoiceChat.Video.Stream.Video',
|
|
|
|
callback: this.onVideoClick,
|
|
|
|
icon: 'videocamera_filled'
|
|
|
|
});
|
|
|
|
|
|
|
|
const btnScreen = this.btnScreen = _makeButton({
|
|
|
|
// text: 'VoiceChat.Video.Stream.Screencast',
|
|
|
|
callback: this.onScreenClick,
|
|
|
|
icon: 'sharescreen_filled'
|
|
|
|
});
|
|
|
|
|
|
|
|
btnScreen.classList.toggle('hide', !IS_SCREEN_SHARING_SUPPORTED);
|
|
|
|
|
|
|
|
const btnMute = _makeButton({
|
|
|
|
noRipple: true,
|
|
|
|
callback: throttle(this.onMuteClick, 600, true)
|
|
|
|
});
|
|
|
|
btnMute.classList.add(className + '-microphone-button');
|
|
|
|
|
|
|
|
const microphoneIcon = this.groupCallMicrophoneIcon = new GroupCallMicrophoneIcon();
|
|
|
|
btnMute.append(microphoneIcon.container);
|
|
|
|
|
|
|
|
const btnMore = _makeButton({
|
|
|
|
// text: 'VoiceChat.Video.Stream.More'
|
|
|
|
icon: 'settings_filled'
|
|
|
|
});
|
|
|
|
|
|
|
|
btnMore.classList.add('btn-disabled');
|
|
|
|
btnMore.classList.toggle('hide', !IS_SCREEN_SHARING_SUPPORTED);
|
|
|
|
|
|
|
|
const btnLeave = _makeButton({
|
|
|
|
// text: 'VoiceChat.Leave',
|
|
|
|
isDanger: true,
|
|
|
|
callback: this.onLeaveClick,
|
|
|
|
icon: 'close'
|
|
|
|
});
|
|
|
|
|
|
|
|
buttons.append(btnVideo, btnScreen, btnMute, btnMore, btnLeave);
|
|
|
|
|
|
|
|
this.container.append(buttons);
|
|
|
|
}
|
|
|
|
|
|
|
|
private onFullScreenClick = () => {
|
|
|
|
requestFullScreen(this.container);
|
|
|
|
};
|
|
|
|
|
|
|
|
private onToggleControls = (show: boolean) => {
|
|
|
|
this.container.classList.toggle('show-controls', show);
|
|
|
|
this.buttonsContainer.classList.toggle('show-controls', show);
|
|
|
|
};
|
|
|
|
|
|
|
|
private toggleDisability = toggleClassName.bind(null, 'btn-disabled');
|
|
|
|
|
|
|
|
private onVideoClick = () => {
|
|
|
|
const toggle = this.toggleDisability([this.btnVideo], true);
|
|
|
|
this.instance.toggleVideoSharing().finally(() => {
|
|
|
|
toggle();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
private onScreenClick = () => {
|
|
|
|
const toggle = this.toggleDisability([this.btnScreen], true);
|
|
|
|
this.instance.toggleScreenSharing().finally(() => {
|
|
|
|
toggle();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
private onMuteClick = () => {
|
|
|
|
const participant = this.instance.participant;
|
|
|
|
if(!participant.pFlags.can_self_unmute) {
|
|
|
|
if(participant.raise_hand_rating === undefined) {
|
|
|
|
this.instance.changeRaiseHand(true);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.instance.toggleMuted();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private onLeaveClick = async() => {
|
|
|
|
const hangUp = (discard: boolean) => {
|
|
|
|
this.instance.hangUp(discard);
|
|
|
|
};
|
|
|
|
|
|
|
|
if(await this.managers.appChatsManager.hasRights(this.instance.chatId, 'manage_call')) {
|
|
|
|
new PopupPeer('popup-end-video-chat', {
|
|
|
|
titleLangKey: 'VoiceChat.End.Title',
|
|
|
|
descriptionLangKey: 'VoiceChat.End.Text',
|
|
|
|
checkboxes: [{
|
|
|
|
text: 'VoiceChat.End.Third'
|
|
|
|
}],
|
|
|
|
buttons: [{
|
|
|
|
langKey: 'VoiceChat.End.OK',
|
|
|
|
callback: (checkboxes) => {
|
|
|
|
hangUp(!!checkboxes.size);
|
|
|
|
},
|
|
|
|
isDanger: true,
|
|
|
|
}]
|
|
|
|
}).show();
|
|
|
|
} else {
|
|
|
|
hangUp(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public getContainer() {
|
|
|
|
return this.container;
|
|
|
|
}
|
|
|
|
|
|
|
|
private onFullScreenChange = () => {
|
|
|
|
this.toggleBigLayout();
|
|
|
|
const isFull = isFullScreen();
|
|
|
|
|
|
|
|
const {btnFullScreen, btnExitFullScreen} = this;
|
|
|
|
|
|
|
|
const wasFullScreen = this.container.classList.contains('is-full-screen');
|
|
|
|
this.container.classList.toggle('is-full-screen', isFull);
|
|
|
|
btnFullScreen && btnFullScreen.classList.toggle('hide', isFull);
|
|
|
|
btnExitFullScreen && btnExitFullScreen.classList.toggle('hide', !isFull);
|
|
|
|
this.btnClose.classList.toggle('hide', isFull);
|
|
|
|
|
|
|
|
if(isFull !== wasFullScreen) {
|
|
|
|
animationIntersector.checkAnimations(isFull);
|
|
|
|
|
|
|
|
themeController.setThemeColor(isFull ? '#000000' : undefined);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private toggleBigLayout = () => {
|
|
|
|
const isFull = isFullScreen();
|
|
|
|
const movable = this.movablePanel?.movable;
|
|
|
|
const isBig = (isFull || !!(movable && movable.width >= 680)) && !!this.videosCount;
|
|
|
|
|
|
|
|
/* if(!isBig && isFull) {
|
|
|
|
cancelFullScreen();
|
|
|
|
return;
|
|
|
|
} */
|
|
|
|
|
|
|
|
const wasBig = this.container.classList.contains('is-big-layout');
|
|
|
|
let buttons: HTMLElement[];
|
|
|
|
if(isBig && !wasBig) { // fix buttons transition to 0 opacity
|
|
|
|
buttons = Array.from(this.buttonsContainer.children) as HTMLElement[];
|
|
|
|
buttons.forEach((element) => {
|
|
|
|
element.style.opacity = '0';
|
|
|
|
});
|
|
|
|
|
|
|
|
void this.buttonsContainer.offsetLeft;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.container.classList.toggle('is-big-layout', isBig);
|
|
|
|
this.btnInvite.classList.toggle('hide', isBig);
|
|
|
|
this.btnShowColumn.classList.toggle('hide', !isBig);
|
|
|
|
|
|
|
|
if(buttons) {
|
|
|
|
// window.requestAnimationFrame(() => {
|
|
|
|
buttons.forEach((element) => {
|
|
|
|
element.style.opacity = '';
|
|
|
|
});
|
|
|
|
// });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private toggleRightColumn = () => {
|
|
|
|
this.container.classList.toggle('is-right-column-shown');
|
|
|
|
};
|
|
|
|
|
|
|
|
private setHasPinned() {
|
|
|
|
this.container.classList.toggle('has-pinned', !!this.instance.pinnedSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
private updateInstance() {
|
|
|
|
if(this.instance.state === GROUP_CALL_STATE.CLOSED) {
|
|
|
|
if(this.container.classList.contains('is-full-screen')) {
|
|
|
|
cancelFullScreen();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.hide();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const {participant, groupCall} = this.instance;
|
|
|
|
if(!participant) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.setTitle();
|
|
|
|
this.setDescription();
|
|
|
|
this.setHasPinned();
|
|
|
|
|
|
|
|
const microphoneButtonState = getGroupCallMicrophoneButtonState(groupCall as any, participant);
|
|
|
|
this.container.dataset.micState = microphoneButtonState === GROUP_CALL_MICROPHONE_BUTTON_STATE.HAND ? 'hand' : (microphoneButtonState === GROUP_CALL_MICROPHONE_BUTTON_STATE.MUTED ? 'muted' : 'unmuted');
|
|
|
|
this.groupCallMicrophoneIcon.setState(microphoneButtonState);
|
|
|
|
}
|
|
|
|
|
|
|
|
private setTitle() {
|
|
|
|
this.groupCallTitle.update(this.instance);
|
|
|
|
}
|
|
|
|
|
|
|
|
private setDescription() {
|
|
|
|
this.groupCallDescription.update(this.instance);
|
|
|
|
this.groupCallBodyHeaderDescription.update(this.instance);
|
|
|
|
}
|
|
|
|
}
|