Merge pull request #5841 from tsiegleauq/clean-some-applause
Cleanup some applause code
This commit is contained in:
commit
bd65b5d41c
@ -17,12 +17,13 @@ export enum ApplauseType {
|
||||
bar = 'applause-type-bar'
|
||||
}
|
||||
|
||||
const applausePath = '/system/applause';
|
||||
const applauseNotifyMessageName = 'applause';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ApplauseService {
|
||||
private applausePath = '/system/applause';
|
||||
private applauseNotifyPath = 'applause';
|
||||
private minApplauseLevel: number;
|
||||
private maxApplauseLevel: number;
|
||||
private presentApplauseUsers: number;
|
||||
@ -51,7 +52,7 @@ export class ApplauseService {
|
||||
this.applauseType = type;
|
||||
});
|
||||
this.notifyService
|
||||
.getMessageObservable<Applause>(this.applauseNotifyPath)
|
||||
.getMessageObservable<Applause>(applauseNotifyMessageName)
|
||||
.pipe(
|
||||
map(notify => notify.message as Applause),
|
||||
/**
|
||||
@ -71,7 +72,7 @@ export class ApplauseService {
|
||||
}
|
||||
|
||||
public async sendApplause(): Promise<void> {
|
||||
await this.httpService.post(this.applausePath);
|
||||
await this.httpService.post(applausePath);
|
||||
}
|
||||
|
||||
public getApplauseQuote(applauseLevel: number): number {
|
||||
|
@ -2,11 +2,11 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { E2EImportsModule } from 'e2e-imports.module';
|
||||
|
||||
import { ApplauseDisplayComponent } from './applause-display.component';
|
||||
import { ApplauseBarDisplayComponent } from './applause-bar-display.component';
|
||||
|
||||
describe('ApplauseDisplayComponent', () => {
|
||||
let component: ApplauseDisplayComponent;
|
||||
let fixture: ComponentFixture<ApplauseDisplayComponent>;
|
||||
let component: ApplauseBarDisplayComponent;
|
||||
let fixture: ComponentFixture<ApplauseBarDisplayComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@ -15,7 +15,7 @@ describe('ApplauseDisplayComponent', () => {
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ApplauseDisplayComponent);
|
||||
fixture = TestBed.createComponent(ApplauseBarDisplayComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
@ -10,14 +10,14 @@ import { fadeAnimation } from 'app/shared/animations';
|
||||
import { BaseViewComponentDirective } from 'app/site/base/base-view';
|
||||
|
||||
@Component({
|
||||
selector: 'os-applause-display',
|
||||
templateUrl: './applause-display.component.html',
|
||||
styleUrls: ['./applause-display.component.scss'],
|
||||
selector: 'os-applause-bar-display',
|
||||
templateUrl: './applause-bar-display.component.html',
|
||||
styleUrls: ['./applause-bar-display.component.scss'],
|
||||
animations: [fadeAnimation],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ApplauseDisplayComponent extends BaseViewComponentDirective {
|
||||
export class ApplauseBarDisplayComponent extends BaseViewComponentDirective {
|
||||
public level = 0;
|
||||
public showLevel: boolean;
|
||||
public percent = 0;
|
@ -0,0 +1,3 @@
|
||||
<div [osResized]="resizeSubject" class="particle-wrapper">
|
||||
<Particles id="particles" [options]="options" (particlesLoaded)="particlesLoaded($event)"> </Particles>
|
||||
</div>
|
@ -2,11 +2,11 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { E2EImportsModule } from 'e2e-imports.module';
|
||||
|
||||
import { ParticleDisplayComponent } from './particle-display.component';
|
||||
import { ApplauseParticleDisplayComponent } from './applause-particle-display.component';
|
||||
|
||||
describe('ParticleDisplayComponent', () => {
|
||||
let component: ParticleDisplayComponent;
|
||||
let fixture: ComponentFixture<ParticleDisplayComponent>;
|
||||
describe('ApplauseParticleDisplayComponent', () => {
|
||||
let component: ApplauseParticleDisplayComponent;
|
||||
let fixture: ComponentFixture<ApplauseParticleDisplayComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@ -15,7 +15,7 @@ describe('ParticleDisplayComponent', () => {
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ParticleDisplayComponent);
|
||||
fixture = TestBed.createComponent(ApplauseParticleDisplayComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
@ -0,0 +1,109 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { auditTime } from 'rxjs/operators';
|
||||
import { Container } from 'tsparticles';
|
||||
import { Emitters } from 'tsparticles/dist/Plugins/Emitters/Emitters';
|
||||
|
||||
import { ApplauseService } from 'app/core/ui-services/applause.service';
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { ElementSize } from 'app/shared/directives/resized.directive';
|
||||
import { BaseViewComponentDirective } from 'app/site/base/base-view';
|
||||
import { particleConfig, particleOptions } from './particle-options';
|
||||
|
||||
@Component({
|
||||
selector: 'os-applause-particle-display',
|
||||
templateUrl: './applause-particle-display.component.html',
|
||||
styleUrls: ['./applause-particle-display.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ApplauseParticleDisplayComponent extends BaseViewComponentDirective {
|
||||
public options = particleOptions;
|
||||
public resizeSubject = new Subject<ElementSize>();
|
||||
private resizeAuditTime = 200;
|
||||
private particleContainer: Container;
|
||||
|
||||
public set particleImage(imageUrl: string) {
|
||||
this.setParticleImage(imageUrl);
|
||||
}
|
||||
|
||||
public set particleLevel(level: number) {
|
||||
this.setParticleLevel(level);
|
||||
}
|
||||
|
||||
public constructor(
|
||||
title: Title,
|
||||
translate: TranslateService,
|
||||
matSnackBar: MatSnackBar,
|
||||
configService: ConfigService,
|
||||
private applauseService: ApplauseService
|
||||
) {
|
||||
super(title, translate, matSnackBar);
|
||||
this.subscriptions.push(
|
||||
this.resizeSubject.pipe(auditTime(this.resizeAuditTime)).subscribe(size => {
|
||||
this.updateParticleContainer(size);
|
||||
}),
|
||||
applauseService.applauseLevelObservable.subscribe(applauseLevel => {
|
||||
this.particleLevel = this.calcEmitterLevel(applauseLevel || 0);
|
||||
}),
|
||||
configService.get<string>('general_system_applause_particle_image').subscribe(particleImage => {
|
||||
this.particleImage = particleImage || undefined;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private setParticleImage(particleImage: string): void {
|
||||
if (particleImage) {
|
||||
particleConfig.customImageShape.image.src = particleImage;
|
||||
(this.options.particles.shape as any) = particleConfig.customImageShape;
|
||||
} else {
|
||||
(this.options.particles.shape as any) = particleConfig.charShapeHearth;
|
||||
}
|
||||
if (this.particleContainer) {
|
||||
this.particleContainer.options.particles.load(this.options.particles as any);
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private calcEmitterLevel(applauseLevel: number): number {
|
||||
if (!applauseLevel) {
|
||||
return 0;
|
||||
}
|
||||
let emitterLevel = this.applauseService.getApplauseQuote(applauseLevel);
|
||||
emitterLevel = Math.ceil(emitterLevel * 10);
|
||||
return emitterLevel;
|
||||
}
|
||||
|
||||
private setParticleLevel(level: number): void {
|
||||
if (this.particleContainer) {
|
||||
const emitters = this.particleContainer.plugins.get('emitters') as Emitters;
|
||||
if (emitters) {
|
||||
emitters.array[0].emitterOptions.rate.quantity = level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateParticleContainer(size: ElementSize): void {
|
||||
if (!size.height || !size.width) {
|
||||
this.stop();
|
||||
} else {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private stop(): void {
|
||||
this.particleContainer?.stop();
|
||||
}
|
||||
|
||||
private refresh(): void {
|
||||
this.particleContainer?.refresh();
|
||||
}
|
||||
|
||||
public particlesLoaded(container: Container): void {
|
||||
this.particleContainer = container;
|
||||
this.refresh();
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
import { SizeMode } from 'tsparticles';
|
||||
|
||||
export const particleConfig = {
|
||||
noAutomaticParticles: {
|
||||
value: 0
|
||||
},
|
||||
slowBlinkingOpacity: {
|
||||
value: 0.8,
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 1,
|
||||
sync: false,
|
||||
minimumValue: 0.3
|
||||
},
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 0.8
|
||||
}
|
||||
},
|
||||
customImageShape: {
|
||||
type: 'image',
|
||||
image: {
|
||||
replace_color: false,
|
||||
replaceColor: false,
|
||||
src: '',
|
||||
width: 24,
|
||||
height: 24
|
||||
}
|
||||
},
|
||||
charShapeHearth: {
|
||||
type: 'char',
|
||||
options: {
|
||||
char: {
|
||||
fill: true,
|
||||
value: ['❤'],
|
||||
/**
|
||||
* has to be here due to a bug
|
||||
* TRACK: https://github.com/matteobruni/tsparticles/issues/1087
|
||||
* ---
|
||||
*/
|
||||
font: 'Verdana',
|
||||
weight: '200',
|
||||
style: ''
|
||||
/** --- */
|
||||
}
|
||||
}
|
||||
},
|
||||
slightlyRandomSize: {
|
||||
value: 16,
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 10
|
||||
}
|
||||
},
|
||||
moveUpOptions: {
|
||||
enable: true,
|
||||
direction: 'top',
|
||||
speed: 1.0,
|
||||
angle: {
|
||||
offset: 45,
|
||||
value: 90
|
||||
},
|
||||
gravity: {
|
||||
enable: true,
|
||||
maxSpeed: 1.5,
|
||||
acceleration: -3
|
||||
},
|
||||
outModes: {
|
||||
left: 'bounce',
|
||||
right: 'bounce',
|
||||
top: 'destroy'
|
||||
}
|
||||
},
|
||||
slowRandomRotation: {
|
||||
value: 0,
|
||||
enable: true,
|
||||
direction: 'random',
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 9
|
||||
},
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 0
|
||||
}
|
||||
},
|
||||
randomColor: {
|
||||
value: 'random'
|
||||
},
|
||||
singleBottomEmitter: [
|
||||
{
|
||||
direction: 'top',
|
||||
rate: {
|
||||
quantity: 0,
|
||||
delay: 0.33
|
||||
},
|
||||
position: {
|
||||
x: 50,
|
||||
y: 100
|
||||
},
|
||||
size: {
|
||||
mode: SizeMode.percent,
|
||||
width: 100
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const particleOptions = {
|
||||
fpsLimit: 30,
|
||||
particles: {
|
||||
number: particleConfig.noAutomaticParticles,
|
||||
opacity: particleConfig.slowBlinkingOpacity,
|
||||
rotate: particleConfig.slowRandomRotation,
|
||||
move: particleConfig.moveUpOptions,
|
||||
color: particleConfig.randomColor,
|
||||
shape: particleConfig.charShapeHearth,
|
||||
size: particleConfig.slightlyRandomSize
|
||||
},
|
||||
emitters: particleConfig.singleBottomEmitter,
|
||||
detectRetina: true
|
||||
};
|
@ -132,7 +132,7 @@
|
||||
'cast-shadow': showJitsiWindow
|
||||
}"
|
||||
>
|
||||
<os-applause-display *ngIf="showApplause && isApplauseTypeBar" class="applause"></os-applause-display>
|
||||
<os-applause-bar-display *ngIf="showApplause && isApplauseTypeBar" class="applause"></os-applause-bar-display>
|
||||
|
||||
<!-- open-window button -->
|
||||
<button class="toggle-list-button" mat-button (click)="toggleShowJitsi()">
|
||||
@ -191,10 +191,10 @@
|
||||
|
||||
<!-- user list -->
|
||||
<div class="room-members" *ngIf="isJitsiActive && isJoined">
|
||||
<os-particle-display
|
||||
<os-applause-particle-display
|
||||
*ngIf="isApplauseTypeParticles"
|
||||
class="room-list-applause-particles"
|
||||
></os-particle-display>
|
||||
></os-applause-particle-display>
|
||||
<div class="member-list">
|
||||
<ol>
|
||||
<li
|
||||
|
@ -1,3 +0,0 @@
|
||||
<div [osResized]="resizeSubject" class="particle-wrapper">
|
||||
<Particles id="particles" [options]="particlesOptions" (particlesLoaded)="particlesLoaded($event)"> </Particles>
|
||||
</div>
|
@ -1,233 +0,0 @@
|
||||
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { auditTime } from 'rxjs/operators';
|
||||
import { Container, SizeMode } from 'tsparticles';
|
||||
import { Shape } from 'tsparticles/dist/Options/Classes/Particles/Shape/Shape';
|
||||
import { IImageShape } from 'tsparticles/dist/Options/Interfaces/Particles/Shape/IImageShape';
|
||||
import { Emitters } from 'tsparticles/dist/Plugins/Emitters/Emitters';
|
||||
|
||||
import { ApplauseService } from 'app/core/ui-services/applause.service';
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { ElementSize } from 'app/shared/directives/resized.directive';
|
||||
import { BaseViewComponentDirective } from 'app/site/base/base-view';
|
||||
|
||||
@Component({
|
||||
selector: 'os-particle-display',
|
||||
templateUrl: './particle-display.component.html',
|
||||
styleUrls: ['./particle-display.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ParticleDisplayComponent extends BaseViewComponentDirective {
|
||||
public resizeSubject = new Subject<ElementSize>();
|
||||
private resizeAuditTime = 200;
|
||||
|
||||
private particleContainer: Container;
|
||||
|
||||
public set particleImage(imageUrl: string) {
|
||||
this.setParticleImage(imageUrl);
|
||||
}
|
||||
|
||||
public set particleLevel(level: number) {
|
||||
this.setParticleLevel(level);
|
||||
}
|
||||
|
||||
private noAutomaticParticles = {
|
||||
value: 0
|
||||
};
|
||||
|
||||
private slowBlinkingOpacity = {
|
||||
value: 0.8,
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 1,
|
||||
sync: false,
|
||||
minimumValue: 0.3
|
||||
},
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 0.8
|
||||
}
|
||||
};
|
||||
|
||||
private imageOptions: IImageShape = {
|
||||
replace_color: false,
|
||||
replaceColor: false,
|
||||
src: '',
|
||||
width: 24,
|
||||
height: 24
|
||||
};
|
||||
|
||||
private customImageShape = {
|
||||
type: 'image',
|
||||
image: this.imageOptions
|
||||
};
|
||||
|
||||
private charShapeHearth = {
|
||||
type: 'char',
|
||||
options: {
|
||||
char: {
|
||||
fill: true,
|
||||
font: 'Verdana',
|
||||
weight: '200',
|
||||
style: '',
|
||||
value: ['❤']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private slightlyRandomSize: any = {
|
||||
value: 16,
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 10
|
||||
}
|
||||
};
|
||||
|
||||
private moveUpOptions = {
|
||||
enable: true,
|
||||
direction: 'top',
|
||||
speed: 1.0,
|
||||
angle: {
|
||||
offset: 45,
|
||||
value: 90
|
||||
},
|
||||
gravity: {
|
||||
enable: true,
|
||||
maxSpeed: 1.5,
|
||||
acceleration: -3
|
||||
},
|
||||
outModes: {
|
||||
left: 'bounce',
|
||||
right: 'bounce',
|
||||
top: 'destroy'
|
||||
}
|
||||
};
|
||||
|
||||
private slowRandomRotation = {
|
||||
value: 0,
|
||||
enable: true,
|
||||
direction: 'random',
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 9
|
||||
},
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 0
|
||||
}
|
||||
};
|
||||
|
||||
private randomColor = {
|
||||
value: 'random'
|
||||
};
|
||||
|
||||
private singleBottomEmitter = [
|
||||
{
|
||||
direction: 'top',
|
||||
rate: {
|
||||
quantity: 0,
|
||||
delay: 0.33
|
||||
},
|
||||
position: {
|
||||
x: 50,
|
||||
y: 100
|
||||
},
|
||||
size: {
|
||||
mode: SizeMode.percent,
|
||||
width: 100
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
public particlesOptions = {
|
||||
fpsLimit: 30,
|
||||
particles: {
|
||||
number: this.noAutomaticParticles,
|
||||
opacity: this.slowBlinkingOpacity,
|
||||
rotate: this.slowRandomRotation,
|
||||
move: this.moveUpOptions,
|
||||
color: this.randomColor,
|
||||
shape: this.charShapeHearth,
|
||||
size: this.slightlyRandomSize
|
||||
},
|
||||
emitters: this.singleBottomEmitter,
|
||||
detectRetina: true
|
||||
};
|
||||
|
||||
public constructor(
|
||||
title: Title,
|
||||
translate: TranslateService,
|
||||
matSnackBar: MatSnackBar,
|
||||
configService: ConfigService,
|
||||
private applauseService: ApplauseService
|
||||
) {
|
||||
super(title, translate, matSnackBar);
|
||||
this.subscriptions.push(
|
||||
this.resizeSubject.pipe(auditTime(this.resizeAuditTime)).subscribe(size => {
|
||||
this.updateParticleContainer(size);
|
||||
}),
|
||||
applauseService.applauseLevelObservable.subscribe(applause => {
|
||||
this.particleLevel = this.calcEmitterLevel(applause || 0);
|
||||
}),
|
||||
configService.get<string>('general_system_applause_particle_image').subscribe(particleImage => {
|
||||
this.particleImage = particleImage || undefined;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private setParticleImage(particleImage: string): void {
|
||||
if (particleImage) {
|
||||
this.imageOptions.src = particleImage;
|
||||
(this.particlesOptions.particles.shape as any) = this.customImageShape;
|
||||
} else {
|
||||
(this.particlesOptions.particles.shape as any) = this.charShapeHearth;
|
||||
}
|
||||
if (this.particleContainer) {
|
||||
this.particleContainer.options.particles.load(this.particlesOptions.particles as any);
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private calcEmitterLevel(applauseLevel: number): number {
|
||||
if (!applauseLevel) {
|
||||
return 0;
|
||||
}
|
||||
let emitterLevel = this.applauseService.getApplauseQuote(applauseLevel);
|
||||
emitterLevel = Math.ceil(emitterLevel * 10);
|
||||
return emitterLevel;
|
||||
}
|
||||
|
||||
private setParticleLevel(level: number): void {
|
||||
if (this.particleContainer) {
|
||||
const emitters = this.particleContainer.plugins.get('emitters') as Emitters;
|
||||
if (emitters) {
|
||||
emitters.array[0].emitterOptions.rate.quantity = level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateParticleContainer(size: ElementSize): void {
|
||||
if (!size.height || !size.width) {
|
||||
this.stop();
|
||||
} else {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private stop(): void {
|
||||
this.particleContainer?.stop();
|
||||
}
|
||||
|
||||
private refresh(): void {
|
||||
this.particleContainer?.refresh();
|
||||
}
|
||||
|
||||
public particlesLoaded(container: Container): void {
|
||||
this.particleContainer = container;
|
||||
this.refresh();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<div class="video-wrapper">
|
||||
<os-particle-display *ngIf="showParticles" class="applause-particles"></os-particle-display>
|
||||
<os-applause-particle-display *ngIf="showParticles" class="applause-particles"></os-applause-particle-display>
|
||||
<div class="player-container" [ngClass]="{ hide: !isUrlOnline }">
|
||||
<video #videoPlayer class="video-js" controls preload="none"></video>
|
||||
</div>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
|
||||
|
||||
import { ResizeSensor } from 'css-element-queries';
|
||||
import { Interface } from 'readline';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export interface ElementSize {
|
||||
|
@ -130,10 +130,10 @@ import { JitsiComponent } from './components/jitsi/jitsi.component';
|
||||
import { VjsPlayerComponent } from './components/vjs-player/vjs-player.component';
|
||||
import { LiveStreamComponent } from './components/live-stream/live-stream.component';
|
||||
import { ListOfSpeakersContentComponent } from './components/list-of-speakers-content/list-of-speakers-content.component';
|
||||
import { ApplauseDisplayComponent } from './components/applause-display/applause-display.component';
|
||||
import { ApplauseBarDisplayComponent } from './components/applause-bar-display/applause-bar-display.component';
|
||||
import { ProgressComponent } from './components/progress/progress.component';
|
||||
import { NgParticlesModule } from 'ng-particles';
|
||||
import { ParticleDisplayComponent } from './components/particle-display/particle-display.component';
|
||||
import { ApplauseParticleDisplayComponent } from './components/applause-particle-display/applause-particle-display.component';
|
||||
|
||||
/**
|
||||
* Share Module for all "dumb" components and pipes.
|
||||
@ -370,9 +370,9 @@ import { ParticleDisplayComponent } from './components/particle-display/particle
|
||||
VjsPlayerComponent,
|
||||
LiveStreamComponent,
|
||||
ListOfSpeakersContentComponent,
|
||||
ApplauseDisplayComponent,
|
||||
ApplauseBarDisplayComponent,
|
||||
ProgressComponent,
|
||||
ParticleDisplayComponent
|
||||
ApplauseParticleDisplayComponent
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user