Browse Source

Calls fixes

master
Eduard Kuzmenko 2 years ago
parent
commit
17713f26b2
  1. 92
      src/components/call/index.ts
  2. 4
      src/components/groupCall/participants.ts
  3. 4
      src/components/popups/index.ts
  4. 7
      src/components/stackedAvatars.ts
  5. 6
      src/components/topbarCall.ts
  6. 5
      src/scss/partials/popups/_call.scss

92
src/components/call/index.ts

@ -10,6 +10,7 @@ import { attachClickEvent } from "../../helpers/dom/clickEvent"; @@ -10,6 +10,7 @@ import { attachClickEvent } from "../../helpers/dom/clickEvent";
import ControlsHover from "../../helpers/dom/controlsHover";
import findUpClassName from "../../helpers/dom/findUpClassName";
import { addFullScreenListener, cancelFullScreen, isFullScreen, requestFullScreen } from "../../helpers/dom/fullScreen";
import { onMediaLoad } from "../../helpers/files";
import { MediaSize } from "../../helpers/mediaSizes";
import MovablePanel from "../../helpers/movablePanel";
import safeAssign from "../../helpers/object/safeAssign";
@ -36,11 +37,16 @@ import callVideoCanvasBlur from "./videoCanvasBlur"; @@ -36,11 +37,16 @@ import callVideoCanvasBlur from "./videoCanvasBlur";
const className = 'call';
let previousState: MovableState = {
width: 400,
height: 580
const MIN_WIDTH = 400;
const MIN_HEIGHT = 580;
const INIT_STATE: MovableState = {
width: MIN_WIDTH,
height: MIN_HEIGHT
};
let previousState: MovableState = {...INIT_STATE};
export default class PopupCall extends PopupElement {
private instance: CallInstance;
private appCallsManager: AppCallsManager;
@ -169,8 +175,8 @@ export default class PopupCall extends PopupElement { @@ -169,8 +175,8 @@ export default class PopupCall extends PopupElement {
this.movablePanel = new MovablePanel({
listenerSetter,
movableOptions: {
minWidth: 400,
minHeight: 580,
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
element: this.element,
verifyTouchTarget: (e) => {
const target = e.target;
@ -184,7 +190,11 @@ export default class PopupCall extends PopupElement { @@ -184,7 +190,11 @@ export default class PopupCall extends PopupElement {
}
},
// onResize: () => this.toggleBigLayout(),
previousState
previousState: !this.instance.wasTryingToJoin && !this.instance.isOutgoing ? {...INIT_STATE} : previousState
});
this.listenerSetter.add(this.movablePanel.movable)('resize', () => {
this.resizeVideoContainers();
});
const controlsHover = this.controlsHover = new ControlsHover();
@ -308,6 +318,8 @@ export default class PopupCall extends PopupElement { @@ -308,6 +318,8 @@ export default class PopupCall extends PopupElement {
animationIntersector.checkAnimations(isFull);
rootScope.setThemeColor(isFull ? '#000000' : undefined);
this.resizeVideoContainers();
}
};
@ -331,6 +343,8 @@ export default class PopupCall extends PopupElement { @@ -331,6 +343,8 @@ export default class PopupCall extends PopupElement {
big.style.cssText = container.style.cssText;
container.classList.remove('small');
container.style.cssText = '';
this.resizeVideoContainers();
});
const canvas = callVideoCanvasBlur(video);
@ -389,10 +403,24 @@ export default class PopupCall extends PopupElement { @@ -389,10 +403,24 @@ export default class PopupCall extends PopupElement {
SetTransition(this.partyMutedState, 'is-visible', !!outputState?.muted, 300);
const containers = this.videoContainers;
const oldContainers = {...containers};
['input' as const, 'output' as const].forEach(type => {
const mediaState = instance.getMediaState(type);
const video = instance.getVideoElement(type) as HTMLVideoElement;
const isActive = !!video && !!(mediaState && (mediaState.videoState === 'active' || mediaState.screencastState === 'active'));
const hasFrame = !!(video && video.videoWidth && video.videoHeight);
if(video && !hasFrame && !video.dataset.hasPromise) {
video.dataset.hasPromise = '1';
// container.classList.add('hide');
onMediaLoad(video).then(() => {
delete video.dataset.hasPromise;
this.updateInstance();
// this.resizeVideoContainers();
// container.classList.remove('hide');
});
}
const isActive = !!video && hasFrame && !!(mediaState && (mediaState.videoState === 'active' || mediaState.screencastState === 'active'));
let videoContainer = containers[type];
if(isActive && video && !videoContainer) {
@ -406,25 +434,20 @@ export default class PopupCall extends PopupElement { @@ -406,25 +434,20 @@ export default class PopupCall extends PopupElement {
}
});
const inputVideoContainer = containers.input;
if(inputVideoContainer) {
const isSmall = !!containers.output;
inputVideoContainer.classList.toggle('small', isSmall);
{
const input = containers.input;
const output = containers.output;
if(Object.keys(oldContainers).length !== Object.keys(containers).length && input) {
input.classList.toggle('small', !!output);
}
const video = instance.getVideoElement('input') as HTMLVideoElement;
if(isSmall) {
const mediaSize = new MediaSize(120, 80);
const aspected = mediaSize.aspectFitted(new MediaSize(video.videoWidth, video.videoHeight));
// inputVideoContainer.style.width = aspected.width + 'px';
// inputVideoContainer.style.height = aspected.height + 'px';
// const ratio = 120 / 80;
inputVideoContainer.style.width = '120px';
inputVideoContainer.style.height = '80px';
} else {
inputVideoContainer.style.cssText = '';
if(output && !input) {
output.classList.remove('small');
}
}
this.resizeVideoContainers();
this.container.classList.toggle('no-video', !Object.keys(containers).length);
if(!this.emojisSubtitle.textContent && connectionState < CALL_STATE.EXCHANGING_KEYS) {
@ -436,6 +459,31 @@ export default class PopupCall extends PopupElement { @@ -436,6 +459,31 @@ export default class PopupCall extends PopupElement {
this.setDescription();
}
private resizeVideoContainers() {
Object.values(this.videoContainers).forEach(container => {
const isSmall = container.classList.contains('small');
if(isSmall) {
const video = container.querySelector('video');
const popupWidth = this.movablePanel.state;
const MAX_WIDTH_PX = 240;
const MAX_HEIGHT_PX = 240;
const isVertical = video.videoHeight > video.videoWidth;
const MAX_SIZE = isVertical ? MAX_HEIGHT_PX : MAX_WIDTH_PX;
const biggestSideSize = 1 / 3 * (isFullScreen() ? 0xFFFF : (isVertical ? popupWidth.height : popupWidth.width));
const widthRatio = isVertical ? video.videoWidth / video.videoHeight : 1;
const heightRatio = isVertical ? 1 : video.videoHeight / video.videoWidth;
container.style.width = biggestSideSize * widthRatio + 'px';
container.style.height = biggestSideSize * heightRatio + 'px';
container.style.maxWidth = MAX_SIZE * widthRatio + 'px';
container.style.maxHeight = MAX_SIZE * heightRatio + 'px';
} else {
container.style.cssText = '';
}
});
}
private setDescription() {
this.description.update(this.instance);
}

4
src/components/groupCall/participants.ts

@ -141,7 +141,7 @@ export class GroupCallParticipantContextMenu { @@ -141,7 +141,7 @@ export class GroupCallParticipantContextMenu {
let appendTo: HTMLElement = document.body;
addFullScreenListener(document.body, () => {
const isFull = isFullScreen();
appendTo = isFull ? (PopupElement.getPopup(PopupGroupCall) as PopupGroupCall).getContainer(): document.body;
appendTo = isFull ? (PopupElement.getPopups(PopupGroupCall) as PopupGroupCall[])[0].getContainer(): document.body;
if(!isFull) {
closeBtnMenu();
@ -150,7 +150,7 @@ export class GroupCallParticipantContextMenu { @@ -150,7 +150,7 @@ export class GroupCallParticipantContextMenu {
}
private onOpenProfileClick = () => {
const popup = PopupElement.getPopup(PopupGroupCall);
const popup = PopupElement.getPopups(PopupGroupCall)[0];
if(popup) {
popup.hide();
}

4
src/components/popups/index.ts

@ -255,8 +255,8 @@ export default class PopupElement<T extends EventListenerListeners = {}> extends @@ -255,8 +255,8 @@ export default class PopupElement<T extends EventListenerListeners = {}> extends
});
}
public static getPopup(popupConstructor: PopupElementConstructable) {
return this.POPUPS.find(element => element instanceof popupConstructor);
public static getPopups(popupConstructor: PopupElementConstructable) {
return this.POPUPS.filter(element => element instanceof popupConstructor);
}
}

7
src/components/stackedAvatars.ts

@ -31,7 +31,12 @@ export default class StackedAvatars { @@ -31,7 +31,12 @@ export default class StackedAvatars {
public render(peerIds: PeerId[], loadPromises?: Promise<any>[]) {
const children = this.container.children;
peerIds.slice().reverse().forEach((peerId, idx) => {
peerIds = peerIds.slice().reverse();
if(peerIds.length > 3) {
peerIds = peerIds.slice(-3);
}
peerIds.forEach((peerId, idx) => {
let avatarContainer = children[idx] as HTMLElement;
if(!avatarContainer) {
avatarContainer = document.createElement('div');

6
src/components/topbarCall.ts

@ -258,7 +258,7 @@ export default class TopbarCall { @@ -258,7 +258,7 @@ export default class TopbarCall {
attachClickEvent(container, () => {
if(this.instance instanceof GroupCallInstance) {
if(PopupElement.getPopup(PopupGroupCall)) {
if(PopupElement.getPopups(PopupGroupCall).length) {
return;
}
@ -268,8 +268,8 @@ export default class TopbarCall { @@ -268,8 +268,8 @@ export default class TopbarCall {
appChatsManager: this.appChatsManager
}).show();
} else if(this.instance instanceof CallInstance) {
const hasPopup = PopupElement.getPopup(PopupCall) as PopupCall;
if(hasPopup && hasPopup.getCallInstance() === this.instance) {
const popups = PopupElement.getPopups(PopupCall) as PopupCall[];
if(popups.find(popup => popup.getCallInstance() === this.instance)) {
return;
}

5
src/scss/partials/popups/_call.scss

@ -244,6 +244,10 @@ @@ -244,6 +244,10 @@
// html.emoji-supported & {
.call-emojis {
transform: scale(1.125);
.emoji {
margin: 0 .125rem;
}
}
// }
@ -262,6 +266,7 @@ @@ -262,6 +266,7 @@
width: 100%;
align-items: center;
padding: 0 1rem;
pointer-events: none;
}
&-party-state {

Loading…
Cancel
Save