Merge pull request #5841 from tsiegleauq/clean-some-applause

Cleanup some applause code
This commit is contained in:
Sean 2021-02-03 10:02:39 +01:00 committed by GitHub
commit bd65b5d41c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 260 additions and 262 deletions

View File

@ -17,12 +17,13 @@ export enum ApplauseType {
bar = 'applause-type-bar' bar = 'applause-type-bar'
} }
const applausePath = '/system/applause';
const applauseNotifyMessageName = 'applause';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ApplauseService { export class ApplauseService {
private applausePath = '/system/applause';
private applauseNotifyPath = 'applause';
private minApplauseLevel: number; private minApplauseLevel: number;
private maxApplauseLevel: number; private maxApplauseLevel: number;
private presentApplauseUsers: number; private presentApplauseUsers: number;
@ -51,7 +52,7 @@ export class ApplauseService {
this.applauseType = type; this.applauseType = type;
}); });
this.notifyService this.notifyService
.getMessageObservable<Applause>(this.applauseNotifyPath) .getMessageObservable<Applause>(applauseNotifyMessageName)
.pipe( .pipe(
map(notify => notify.message as Applause), map(notify => notify.message as Applause),
/** /**
@ -71,7 +72,7 @@ export class ApplauseService {
} }
public async sendApplause(): Promise<void> { public async sendApplause(): Promise<void> {
await this.httpService.post(this.applausePath); await this.httpService.post(applausePath);
} }
public getApplauseQuote(applauseLevel: number): number { public getApplauseQuote(applauseLevel: number): number {

View File

@ -2,11 +2,11 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { E2EImportsModule } from 'e2e-imports.module'; import { E2EImportsModule } from 'e2e-imports.module';
import { ApplauseDisplayComponent } from './applause-display.component'; import { ApplauseBarDisplayComponent } from './applause-bar-display.component';
describe('ApplauseDisplayComponent', () => { describe('ApplauseDisplayComponent', () => {
let component: ApplauseDisplayComponent; let component: ApplauseBarDisplayComponent;
let fixture: ComponentFixture<ApplauseDisplayComponent>; let fixture: ComponentFixture<ApplauseBarDisplayComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -15,7 +15,7 @@ describe('ApplauseDisplayComponent', () => {
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ApplauseDisplayComponent); fixture = TestBed.createComponent(ApplauseBarDisplayComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -10,14 +10,14 @@ import { fadeAnimation } from 'app/shared/animations';
import { BaseViewComponentDirective } from 'app/site/base/base-view'; import { BaseViewComponentDirective } from 'app/site/base/base-view';
@Component({ @Component({
selector: 'os-applause-display', selector: 'os-applause-bar-display',
templateUrl: './applause-display.component.html', templateUrl: './applause-bar-display.component.html',
styleUrls: ['./applause-display.component.scss'], styleUrls: ['./applause-bar-display.component.scss'],
animations: [fadeAnimation], animations: [fadeAnimation],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class ApplauseDisplayComponent extends BaseViewComponentDirective { export class ApplauseBarDisplayComponent extends BaseViewComponentDirective {
public level = 0; public level = 0;
public showLevel: boolean; public showLevel: boolean;
public percent = 0; public percent = 0;

View File

@ -0,0 +1,3 @@
<div [osResized]="resizeSubject" class="particle-wrapper">
<Particles id="particles" [options]="options" (particlesLoaded)="particlesLoaded($event)"> </Particles>
</div>

View File

@ -2,11 +2,11 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { E2EImportsModule } from 'e2e-imports.module'; import { E2EImportsModule } from 'e2e-imports.module';
import { ParticleDisplayComponent } from './particle-display.component'; import { ApplauseParticleDisplayComponent } from './applause-particle-display.component';
describe('ParticleDisplayComponent', () => { describe('ApplauseParticleDisplayComponent', () => {
let component: ParticleDisplayComponent; let component: ApplauseParticleDisplayComponent;
let fixture: ComponentFixture<ParticleDisplayComponent>; let fixture: ComponentFixture<ApplauseParticleDisplayComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -15,7 +15,7 @@ describe('ParticleDisplayComponent', () => {
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ParticleDisplayComponent); fixture = TestBed.createComponent(ApplauseParticleDisplayComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -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();
}
}

View File

@ -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
};

View File

@ -132,7 +132,7 @@
'cast-shadow': showJitsiWindow '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 --> <!-- open-window button -->
<button class="toggle-list-button" mat-button (click)="toggleShowJitsi()"> <button class="toggle-list-button" mat-button (click)="toggleShowJitsi()">
@ -191,10 +191,10 @@
<!-- user list --> <!-- user list -->
<div class="room-members" *ngIf="isJitsiActive && isJoined"> <div class="room-members" *ngIf="isJitsiActive && isJoined">
<os-particle-display <os-applause-particle-display
*ngIf="isApplauseTypeParticles" *ngIf="isApplauseTypeParticles"
class="room-list-applause-particles" class="room-list-applause-particles"
></os-particle-display> ></os-applause-particle-display>
<div class="member-list"> <div class="member-list">
<ol> <ol>
<li <li

View File

@ -1,3 +0,0 @@
<div [osResized]="resizeSubject" class="particle-wrapper">
<Particles id="particles" [options]="particlesOptions" (particlesLoaded)="particlesLoaded($event)"> </Particles>
</div>

View File

@ -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();
}
}

View File

@ -1,5 +1,5 @@
<div class="video-wrapper"> <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 }"> <div class="player-container" [ngClass]="{ hide: !isUrlOnline }">
<video #videoPlayer class="video-js" controls preload="none"></video> <video #videoPlayer class="video-js" controls preload="none"></video>
</div> </div>

View File

@ -1,7 +1,6 @@
import { Directive, ElementRef, Input, OnInit } from '@angular/core'; import { Directive, ElementRef, Input, OnInit } from '@angular/core';
import { ResizeSensor } from 'css-element-queries'; import { ResizeSensor } from 'css-element-queries';
import { Interface } from 'readline';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
export interface ElementSize { export interface ElementSize {

View File

@ -130,10 +130,10 @@ import { JitsiComponent } from './components/jitsi/jitsi.component';
import { VjsPlayerComponent } from './components/vjs-player/vjs-player.component'; import { VjsPlayerComponent } from './components/vjs-player/vjs-player.component';
import { LiveStreamComponent } from './components/live-stream/live-stream.component'; import { LiveStreamComponent } from './components/live-stream/live-stream.component';
import { ListOfSpeakersContentComponent } from './components/list-of-speakers-content/list-of-speakers-content.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 { ProgressComponent } from './components/progress/progress.component';
import { NgParticlesModule } from 'ng-particles'; 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. * Share Module for all "dumb" components and pipes.
@ -370,9 +370,9 @@ import { ParticleDisplayComponent } from './components/particle-display/particle
VjsPlayerComponent, VjsPlayerComponent,
LiveStreamComponent, LiveStreamComponent,
ListOfSpeakersContentComponent, ListOfSpeakersContentComponent,
ApplauseDisplayComponent, ApplauseBarDisplayComponent,
ProgressComponent, ProgressComponent,
ParticleDisplayComponent ApplauseParticleDisplayComponent
], ],
providers: [ providers: [
{ {