Merge pull request #6102 from tsiegleauq/hide-conf-bar-sometimes

Hide conference bar without interaction
This commit is contained in:
Emanuel Schütze 2021-06-03 20:50:24 +02:00 committed by GitHub
commit 4938c34d50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 116 deletions

View File

@ -72,15 +72,17 @@
</div> </div>
<div class="exit"> <div class="exit">
<!-- Exit jitsi, view stream --> <!-- Exit jitsi, view stream -->
<button <ng-container *osPerms="permission.coreCanSeeLiveStream">
mat-icon-button <button
color="primary" mat-icon-button
matTooltip="{{ 'Continue livestream' | translate }}" color="primary"
(click)="viewStream()" matTooltip="{{ 'Continue livestream' | translate }}"
*ngIf="!!(liveStreamUrl | async)?.trim()" (click)="viewStream()"
> *ngIf="hasLiveStreamUrl | async"
<mat-icon>live_tv</mat-icon> >
</button> <mat-icon>live_tv</mat-icon>
</button>
</ng-container>
</div> </div>
</div> </div>
</div> </div>

View File

@ -38,6 +38,8 @@ export class CallComponent extends BaseViewComponentDirective implements OnInit,
public isJitsiActiveInAnotherTab: Observable<boolean> = this.rtcService.inOtherTab; public isJitsiActiveInAnotherTab: Observable<boolean> = this.rtcService.inOtherTab;
public canEnterCall: Observable<boolean> = this.callRestrictionService.canEnterCallObservable; public canEnterCall: Observable<boolean> = this.callRestrictionService.canEnterCallObservable;
public isJitsiDialogOpen: Observable<boolean> = this.rtcService.showCallDialogObservable; public isJitsiDialogOpen: Observable<boolean> = this.rtcService.showCallDialogObservable;
public showParticles: Observable<boolean> = this.applauseService.showParticles;
public hasLiveStreamUrl: Observable<boolean> = this.streamService.hasLiveStreamUrlObvervable;
public isJitsiActive: boolean; public isJitsiActive: boolean;
public isJoined: boolean; public isJoined: boolean;
@ -64,18 +66,6 @@ export class CallComponent extends BaseViewComponentDirective implements OnInit,
return this.isJitsiActive && this.isJoined; return this.isJitsiActive && this.isJoined;
} }
public get showParticles(): Observable<boolean> {
return this.applauseService.showParticles;
}
public get canSeeLiveStream(): Observable<boolean> {
return this.streamService.canSeeLiveStreamObservable;
}
public get liveStreamUrl(): Observable<string> {
return this.streamService.liveStreamUrlObservable;
}
private autoConnect: boolean; private autoConnect: boolean;
@Output() @Output()

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -18,7 +18,7 @@ import { StreamService } from '../../services/stream.service';
styleUrls: ['./interaction-container.component.scss'], styleUrls: ['./interaction-container.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class InteractionContainerComponent extends BaseViewComponentDirective { export class InteractionContainerComponent extends BaseViewComponentDirective implements OnInit {
public showBody = false; public showBody = false;
private streamRunning = false; private streamRunning = false;
@ -63,11 +63,6 @@ export class InteractionContainerComponent extends BaseViewComponentDirective {
) { ) {
super(titleService, translate, matSnackBar); super(titleService, translate, matSnackBar);
this.subscriptions.push( this.subscriptions.push(
interactionService.conferenceStateObservable.pipe(distinctUntilChanged()).subscribe(state => {
if (state) {
this.clearTitles();
}
}),
rtcService.showCallDialogObservable.subscribe(show => { rtcService.showCallDialogObservable.subscribe(show => {
if (show) { if (show) {
this.showBody = false; this.showBody = false;
@ -91,9 +86,20 @@ export class InteractionContainerComponent extends BaseViewComponentDirective {
); );
} }
public ngOnInit(): void {
this.subscriptions.push(
this.interactionService.conferenceStateObservable.pipe(distinctUntilChanged()).subscribe(state => {
if (state) {
this.clearTitles();
}
})
);
}
private clearTitles(): void { private clearTitles(): void {
this.containerHeadTitle = ''; this.containerHeadTitle = '';
this.containerHeadSubtitle = ''; this.containerHeadSubtitle = '';
this.cd.markForCheck();
this.cd.detectChanges(); this.cd.detectChanges();
} }
@ -104,14 +110,14 @@ export class InteractionContainerComponent extends BaseViewComponentDirective {
public updateTitle(title: string): void { public updateTitle(title: string): void {
if (title !== this.containerHeadTitle) { if (title !== this.containerHeadTitle) {
this.containerHeadTitle = title ?? ''; this.containerHeadTitle = title ?? '';
this.cd.detectChanges(); this.cd.markForCheck();
} }
} }
public updateSubtitle(title: string): void { public updateSubtitle(title: string): void {
if (title !== this.containerHeadSubtitle) { if (title !== this.containerHeadSubtitle) {
this.containerHeadSubtitle = title ?? ''; this.containerHeadSubtitle = title ?? '';
this.cd.detectChanges(); this.cd.markForCheck();
} }
} }
} }

View File

@ -88,7 +88,7 @@ export class CallRestrictionService {
) { ) {
this.hasToEnterCallSubject.next(); this.hasToEnterCallSubject.next();
} }
} else if (operatorClosIndex === UserListIndexType.NotOnList && this.restricted) { } else if (operatorClosIndex === UserListIndexType.NotOnList && this.restricted && !this.canManageSpeaker) {
this.hasToLeaveCallSubject.next(); this.hasToLeaveCallSubject.next();
} }
} }

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { distinctUntilChanged, map } from 'rxjs/operators';
import { ConfigService } from 'app/core/ui-services/config.service'; import { ConfigService } from 'app/core/ui-services/config.service';
import { CallRestrictionService } from './call-restriction.service'; import { CallRestrictionService } from './call-restriction.service';
@ -9,9 +9,9 @@ import { RtcService } from './rtc.service';
import { StreamService } from './stream.service'; import { StreamService } from './stream.service';
export enum ConferenceState { export enum ConferenceState {
none, none = 1,
stream, stream = 2,
jitsi jitsi = 3
} }
@Injectable({ @Injectable({
@ -20,17 +20,14 @@ export enum ConferenceState {
export class InteractionService { export class InteractionService {
private conferenceStateSubject = new BehaviorSubject<ConferenceState>(ConferenceState.none); private conferenceStateSubject = new BehaviorSubject<ConferenceState>(ConferenceState.none);
public conferenceStateObservable = this.conferenceStateSubject.asObservable(); public conferenceStateObservable = this.conferenceStateSubject.asObservable();
public showLiveConfObservable: Observable<boolean>; public showLiveConfObservable: Observable<boolean> = this.configService.get<boolean>(
'general_system_conference_show'
);
private get conferenceState(): ConferenceState { private get conferenceState(): ConferenceState {
return this.conferenceStateSubject.value; return this.conferenceStateSubject.value;
} }
private isJitsiEnabled: boolean;
private isInCall: boolean; private isInCall: boolean;
private isJitsiActive: boolean;
private hasLiveStreamUrl: boolean;
private canSeeLiveStream: boolean;
private showLiveConf: boolean;
public get isConfStateStream(): Observable<boolean> { public get isConfStateStream(): Observable<boolean> {
return this.conferenceStateObservable.pipe(map(state => state === ConferenceState.stream)); return this.conferenceStateObservable.pipe(map(state => state === ConferenceState.stream));
@ -50,36 +47,38 @@ export class InteractionService {
private rtcService: RtcService, private rtcService: RtcService,
private callRestrictionService: CallRestrictionService private callRestrictionService: CallRestrictionService
) { ) {
this.showLiveConfObservable = this.configService.get<boolean>('general_system_conference_show'); combineLatest(
this.showLiveConfObservable,
this.streamService.hasLiveStreamUrlObvervable,
this.streamService.canSeeLiveStreamObservable,
this.rtcService.isJitsiEnabledObservable,
this.rtcService.isJoinedObservable,
this.rtcService.isJitsiActiveObservable,
this.callRestrictionService.canEnterCallObservable,
(showConf, hasStreamUrl, canSeeStream, jitsiEnabled, inCall, jitsiActive, canEnterCall) => {
this.isInCall = inCall;
/** /**
* If you want to somehow simplify this using rxjs merge-map magic or something * most importantly, if there is a call, to not change the state here
* be my guest. */
*/ if (inCall || jitsiActive) {
this.streamService.liveStreamUrlObservable.subscribe(url => { return;
this.hasLiveStreamUrl = !!url?.trim() ?? false; }
this.detectDeadState(); if (hasStreamUrl && canSeeStream) {
}); return ConferenceState.stream;
} else if (showConf && jitsiEnabled && canEnterCall && (!hasStreamUrl || !canSeeStream)) {
this.streamService.canSeeLiveStreamObservable.subscribe(canSee => { return ConferenceState.jitsi;
this.canSeeLiveStream = canSee; } else {
this.detectDeadState(); return ConferenceState.none;
}); }
}
this.rtcService.isJitsiEnabledObservable.subscribe(enabled => { )
this.isJitsiEnabled = enabled; .pipe(distinctUntilChanged())
this.detectDeadState(); .subscribe(state => {
}); if (state) {
this.setConferenceState(state);
this.rtcService.isJoinedObservable.subscribe(joined => { }
this.isInCall = joined; });
this.detectDeadState();
});
this.rtcService.isJitsiActiveObservable.subscribe(isActive => {
this.isJitsiActive = isActive;
this.detectDeadState();
});
this.callRestrictionService.hasToEnterCallObservable.subscribe(() => { this.callRestrictionService.hasToEnterCallObservable.subscribe(() => {
if (!this.isInCall) { if (!this.isInCall) {
@ -91,13 +90,6 @@ export class InteractionService {
this.callRestrictionService.hasToLeaveCallObservable.subscribe(() => { this.callRestrictionService.hasToLeaveCallObservable.subscribe(() => {
this.viewStream(); this.viewStream();
}); });
this.showLiveConfObservable.subscribe(showConf => {
this.showLiveConf = showConf;
this.detectDeadState();
});
this.detectDeadState();
} }
public async enterCall(): Promise<void> { public async enterCall(): Promise<void> {
@ -117,37 +109,4 @@ export class InteractionService {
this.conferenceStateSubject.next(newState); this.conferenceStateSubject.next(newState);
} }
} }
/**
* this is the "dead" state; you would see the jitsi state; but are not connected
* or the connection is prohibited. If this occurs and a live stream
* becomes available, switch to the stream state
*/
private detectDeadState(): void {
if (
this.isInCall === undefined ||
this.isJitsiActive === undefined ||
this.hasLiveStreamUrl === undefined ||
this.conferenceState === undefined ||
this.canSeeLiveStream === undefined ||
this.isJitsiEnabled === undefined
) {
return;
}
/**
* most importantly, if there is a call, to not change the state!
*/
if (this.isInCall || this.isJitsiActive) {
return;
}
if (this.hasLiveStreamUrl && this.canSeeLiveStream) {
this.viewStream();
} else if (this.showLiveConf && (!this.hasLiveStreamUrl || !this.canSeeLiveStream) && this.isJitsiEnabled) {
this.enterCall();
} else {
this.setConferenceState(ConferenceState.none);
}
}
} }

View File

@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { StorageMap } from '@ngx-pwa/local-storage'; import { StorageMap } from '@ngx-pwa/local-storage';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators'; import { distinctUntilChanged, map } from 'rxjs/operators';
import { OperatorService, Permission } from 'app/core/core-services/operator.service'; import { OperatorService, Permission } from 'app/core/core-services/operator.service';
import { ConfigService } from 'app/core/ui-services/config.service'; import { ConfigService } from 'app/core/ui-services/config.service';
@ -13,7 +13,10 @@ const STREAM_RUNNING_STORAGE_KEY = 'streamIsRunning';
providedIn: 'root' providedIn: 'root'
}) })
export class StreamService { export class StreamService {
public liveStreamUrlObservable: Observable<string>; public liveStreamUrlObservable: Observable<string> = this.configService.get<string>('general_system_stream_url');
public hasLiveStreamUrlObvervable: Observable<boolean> = this.liveStreamUrlObservable.pipe(
map(url => !!url?.trim() || false)
);
/** /**
* undefined is controlled behavior, meaning, this property was not * undefined is controlled behavior, meaning, this property was not
@ -28,9 +31,11 @@ export class StreamService {
private canSeeLiveStreamSubject = new Subject<boolean>(); private canSeeLiveStreamSubject = new Subject<boolean>();
public canSeeLiveStreamObservable = this.canSeeLiveStreamSubject.asObservable(); public canSeeLiveStreamObservable = this.canSeeLiveStreamSubject.asObservable();
public constructor(private storageMap: StorageMap, operator: OperatorService, configService: ConfigService) { public constructor(
this.liveStreamUrlObservable = configService.get<string>('general_system_stream_url'); private storageMap: StorageMap,
operator: OperatorService,
private configService: ConfigService
) {
this.streamLoadedOnceObservable = this.storageMap this.streamLoadedOnceObservable = this.storageMap
.watch(STREAM_RUNNING_STORAGE_KEY, { type: 'boolean' }) .watch(STREAM_RUNNING_STORAGE_KEY, { type: 'boolean' })
.pipe(distinctUntilChanged()); .pipe(distinctUntilChanged());