openvidu-components: Updated layout elements transitons

pull/743/head
csantosm 2022-07-05 17:48:25 +02:00
parent 4fd2fc8595
commit 25972260ac
11 changed files with 49 additions and 58 deletions

View File

@ -1,6 +1,6 @@
<div class="container" [class.withSubtitles]="subtitlesEnabled">
<div id="layout" class="layout">
<div class="OT_root OT_publisher" *ngFor="let stream of localParticipant | streams" [ngClass]="{ OV_big: stream.videoEnlarged }">
<div id="layout" class="layout" #layout>
<div *ngFor="let stream of localParticipant | streams" [ngClass]="{ OV_big: stream.videoEnlarged }" class="OT_root OT_publisher">
<ng-container *ngTemplateOutlet="streamTemplate; context: { $implicit: stream }"></ng-container>
</div>

View File

@ -6,7 +6,9 @@ import {
ContentChild,
OnDestroy,
OnInit,
TemplateRef
TemplateRef,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { Subscription } from 'rxjs';
import { ParticipantService } from '../../services/participant/participant.service';
@ -59,6 +61,10 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
*/
@ContentChild('stream', { read: TemplateRef }) streamTemplate: TemplateRef<any>;
/**
* @ignore
*/
@ViewChild('layout', { static: false, read: ViewContainerRef }) layoutContainer: ViewContainerRef;
/**
* @ignore
*/
@ -93,9 +99,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
}
ngAfterViewInit() {
let timeout: number = 100;
this.layoutService.initialize(timeout);
this.layoutService.update(timeout);
this.layoutService.initialize(this.layoutContainer.element.nativeElement);
}
ngOnDestroy() {

View File

@ -107,7 +107,7 @@
height: 100%;
position: relative;
overflow: hidden;
background-color: #000000;
background-color: transparent;
border-radius: var(--ov-video-radius);
}

View File

@ -1,6 +1,7 @@
<div
*ngIf="this._stream"
class="OV_stream no-size"
class="OV_stream"
[ngClass]="{'no-size': !showVideo}"
[id]="'container-' + this._stream.streamManager?.stream?.streamId"
#streamContainer
>
@ -65,14 +66,6 @@
<mat-icon *ngIf="_stream.participant.isMutedForcibly">volume_off</mat-icon>
<span *ngIf="_stream.participant.isMutedForcibly">{{ 'STREAM.UNMUTE_SOUND' | translate }}</span>
</button>
<!-- <button mat-menu-item *ngIf="this._stream.streamManager?.stream?.videoActive" id="fullscreenButton" (click)="toggleFullscreen()">
<mat-icon *ngIf="!isFullscreenEnabled">fullscreen</mat-icon>
<span *ngIf="!isFullscreenEnabled">Fullscreen</span>
<mat-icon *ngIf="isFullscreenEnabled">fullscreen_exit</mat-icon>
<span *ngIf="isFullscreenEnabled">Exit fullscreen</span>
</button> -->
<button
mat-menu-item
(click)="replaceScreenTrack()"

View File

@ -3,7 +3,6 @@ import { Subscription } from 'rxjs';
import { MatMenuPanel, MatMenuTrigger } from '@angular/material/menu';
import { VideoSizeIcon } from '../../models/icon.model';
import { ScreenType, VideoType } from '../../models/video-type.model';
import { DocumentService } from '../../services/document/document.service';
import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service';
import { OpenViduService } from '../../services/openvidu/openvidu.service';
import { LayoutService } from '../../services/layout/layout.service';
@ -109,6 +108,7 @@ export class StreamComponent implements OnInit {
* @ignore
*/
showSettingsButton: boolean = true;
showVideo: boolean;
/**
* @ignore
@ -118,9 +118,10 @@ export class StreamComponent implements OnInit {
setTimeout(() => {
if (streamContainer) {
this._streamContainer = streamContainer;
// Remove 'no-size' css class for showing the element in the view.
// This is a workaround for fixing a layout bug which provide a bad UX with each new elements created.
this.documentService.removeNoSizeElementClass(this._streamContainer.nativeElement);
setTimeout(() => {
this.showVideo = true;
}, 100);
}
}, 0);
}
@ -154,7 +155,6 @@ export class StreamComponent implements OnInit {
* @ignore
*/
constructor(
protected documentService: DocumentService,
protected openviduService: OpenViduService,
protected layoutService: LayoutService,
protected participantService: ParticipantService,

View File

@ -1,6 +1,9 @@
#call-container, #session-container {
height: 100%;
}
#session-container {
background-color: var(--ov-primary-color);
}
#pre-join-container {
height: inherit;

View File

@ -1,20 +1,20 @@
<div id="call-container">
<div id="pre-join-container" *ngIf="showPrejoin && tokensReceived && participantReady">
<ov-pre-join (onJoinButtonClicked)="_onJoinButtonClicked()"></ov-pre-join>
</div>
<div id="spinner" *ngIf="!participantReady && !streamPlaying && !error">
<div id="spinner" *ngIf="loading" >
<mat-spinner [diameter]="50"></mat-spinner>
<span>{{ 'PREJOIN.PREPARING' | translate }}</span>
</div>
<div id="spinner" *ngIf="!participantReady && error">
<div [@inOutAnimation] id="pre-join-container" *ngIf="showPrejoin && participantReady && !loading">
<ov-pre-join (onJoinButtonClicked)="_onJoinButtonClicked()"></ov-pre-join>
</div>
<div id="spinner" *ngIf="!loading && error">
<mat-icon class="error-icon">error</mat-icon>
<span>{{ errorMessage }}</span>
</div>
<div id="session-container" *ngIf="showVideoconference || (!showPrejoin && participantReady && tokensReceived && !error)">
<div [@inOutAnimation] id="session-container" *ngIf="showVideoconference || (!showPrejoin && !loading && !error)">
<ov-session (onSessionCreated)="_onSessionCreated($event)">
<ng-template #toolbar>
<ng-container *ngIf="openviduAngularToolbarTemplate">

View File

@ -1,3 +1,4 @@
import { trigger, state, style, transition, animate } from '@angular/animations';
import {
AfterViewInit,
Component,
@ -110,7 +111,13 @@ import { TranslateService } from '../../services/translate/translate.service';
@Component({
selector: 'ov-videoconference',
templateUrl: './videoconference.component.html',
styleUrls: ['./videoconference.component.css']
styleUrls: ['./videoconference.component.css'],
animations: [
trigger('inOutAnimation', [
transition(':enter', [style({ opacity: 0 }), animate('300ms ease-out', style({ opacity: 1 }))]),
// transition(':leave', [style({ opacity: 1 }), animate('50ms ease-in', style({ opacity: 0.9 }))])
])
]
})
export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewInit {
// *** Toolbar ***
@ -186,7 +193,6 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
*/
@ViewChild('defaultParticipantsPanel', { static: false, read: TemplateRef }) defaultParticipantsPanelTemplate: TemplateRef<any>;
/**
* TODO: WIP
* @internal
*/
@ViewChild('defaultActivitiesPanel', { static: false, read: TemplateRef })
@ -214,7 +220,6 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
*/
openviduAngularToolbarAdditionalButtonsTemplate: TemplateRef<any>;
/**
* TODO: WIP
* @internal
*/
openviduAngularActivitiesPanelTemplate: TemplateRef<any>;
@ -281,7 +286,7 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
} else {
this.log.w('No screen token found. Screenshare feature will be disabled');
}
this.tokensReceived = true;
this.loading = false;
}
}
@ -382,10 +387,7 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
* @internal
*/
participantReady: boolean = false;
/**
* @internal
*/
tokensReceived: boolean = false;
/**
* @internal
*/
@ -399,7 +401,10 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
*/
showPrejoin: boolean = true;
streamPlaying = false;
/**
* @internal
*/
loading = true;
private externalParticipantName: string;
private prejoinSub: Subscription;
private participantNameSub: Subscription;
@ -449,7 +454,7 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
await this.handlePublisherSuccess();
this.participantReady = true;
});
publisher.once('streamPlaying', () => (this.streamPlaying = true));
// publisher.once('streamPlaying', () => (this.streamPlaying = true));
}
} catch (error) {
this.actionService.openDialog(error.name.replace(/_/g, ' '), error.message, true);

View File

@ -233,6 +233,7 @@ export class OpenViduLayout {
// });
this.opts = opts;
this.layoutContainer = container;
this.updateLayout(container, opts);
}
getLayoutContainer(): HTMLElement {
@ -243,9 +244,9 @@ export class OpenViduLayout {
* Set the layout configuration
* @param options
*/
private setLayoutOptions(options: OpenViduLayoutOptions) {
this.opts = options;
}
// private setLayoutOptions(options: OpenViduLayoutOptions) {
// this.opts = options;
// }
private css(el: HTMLVideoElement | HTMLElement, propertyName: any, value?: string) {
if (!!value) {

View File

@ -58,10 +58,6 @@ export class DocumentService {
}
}
removeNoSizeElementClass(element: HTMLElement | Element) {
element?.classList.remove(LayoutClass.NO_SIZE_ELEMENT);
}
isSmallElement(element: HTMLElement | Element): boolean {
return element?.className.includes(LayoutClass.SMALL_ELEMENT);
}

View File

@ -25,25 +25,14 @@ export class LayoutService {
this.subtitlesTogglingObs = this.subtitlesToggling.asObservable();
}
initialize(timeout: number = null) {
if (typeof timeout === 'number' && timeout >= 0) {
setTimeout(() => {
this._initialize();
this.sendLayoutWidthEvent();
}, timeout);
} else {
this._initialize();
this.sendLayoutWidthEvent();
}
}
private _initialize() {
initialize(container: HTMLElement) {
this.layoutContainer = container;
this.openviduLayout = new OpenViduLayout();
this.openviduLayoutOptions = this.getOptions();
this.layoutContainer = document.getElementById('layout');
if(this.layoutContainer){
this.openviduLayout.initLayoutContainer(this.layoutContainer, this.openviduLayoutOptions);
}
this.sendLayoutWidthEvent();
}
private getOptions(): OpenViduLayoutOptions {