Hide conference bar without interaction
Hide the conference bar if there is no stream and no entering permission. Hides the "see stream" button if use user has no permission to see the stream (call list window) Use rxjs combineLatest for easier "dead state" detection with less change pushing
This commit is contained in:
parent
7dcdbb4ee1
commit
8b22f5ff0e
@ -72,15 +72,17 @@
|
||||
</div>
|
||||
<div class="exit">
|
||||
<!-- Exit jitsi, view stream -->
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
matTooltip="{{ 'Continue livestream' | translate }}"
|
||||
(click)="viewStream()"
|
||||
*ngIf="!!(liveStreamUrl | async)?.trim()"
|
||||
>
|
||||
<mat-icon>live_tv</mat-icon>
|
||||
</button>
|
||||
<ng-container *osPerms="permission.coreCanSeeLiveStream">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
matTooltip="{{ 'Continue livestream' | translate }}"
|
||||
(click)="viewStream()"
|
||||
*ngIf="hasLiveStreamUrl | async"
|
||||
>
|
||||
<mat-icon>live_tv</mat-icon>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -38,6 +38,8 @@ export class CallComponent extends BaseViewComponentDirective implements OnInit,
|
||||
public isJitsiActiveInAnotherTab: Observable<boolean> = this.rtcService.inOtherTab;
|
||||
public canEnterCall: Observable<boolean> = this.callRestrictionService.canEnterCallObservable;
|
||||
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 isJoined: boolean;
|
||||
@ -64,18 +66,6 @@ export class CallComponent extends BaseViewComponentDirective implements OnInit,
|
||||
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;
|
||||
|
||||
@Output()
|
||||
|
@ -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 { Title } from '@angular/platform-browser';
|
||||
|
||||
@ -18,7 +18,7 @@ import { StreamService } from '../../services/stream.service';
|
||||
styleUrls: ['./interaction-container.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class InteractionContainerComponent extends BaseViewComponentDirective {
|
||||
export class InteractionContainerComponent extends BaseViewComponentDirective implements OnInit {
|
||||
public showBody = false;
|
||||
|
||||
private streamRunning = false;
|
||||
@ -63,11 +63,6 @@ export class InteractionContainerComponent extends BaseViewComponentDirective {
|
||||
) {
|
||||
super(titleService, translate, matSnackBar);
|
||||
this.subscriptions.push(
|
||||
interactionService.conferenceStateObservable.pipe(distinctUntilChanged()).subscribe(state => {
|
||||
if (state) {
|
||||
this.clearTitles();
|
||||
}
|
||||
}),
|
||||
rtcService.showCallDialogObservable.subscribe(show => {
|
||||
if (show) {
|
||||
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 {
|
||||
this.containerHeadTitle = '';
|
||||
this.containerHeadSubtitle = '';
|
||||
this.cd.markForCheck();
|
||||
this.cd.detectChanges();
|
||||
}
|
||||
|
||||
@ -104,14 +110,14 @@ export class InteractionContainerComponent extends BaseViewComponentDirective {
|
||||
public updateTitle(title: string): void {
|
||||
if (title !== this.containerHeadTitle) {
|
||||
this.containerHeadTitle = title ?? '';
|
||||
this.cd.detectChanges();
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
}
|
||||
|
||||
public updateSubtitle(title: string): void {
|
||||
if (title !== this.containerHeadSubtitle) {
|
||||
this.containerHeadSubtitle = title ?? '';
|
||||
this.cd.detectChanges();
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ export class CallRestrictionService {
|
||||
) {
|
||||
this.hasToEnterCallSubject.next();
|
||||
}
|
||||
} else if (operatorClosIndex === UserListIndexType.NotOnList && this.restricted) {
|
||||
} else if (operatorClosIndex === UserListIndexType.NotOnList && this.restricted && !this.canManageSpeaker) {
|
||||
this.hasToLeaveCallSubject.next();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { CallRestrictionService } from './call-restriction.service';
|
||||
@ -9,9 +9,9 @@ import { RtcService } from './rtc.service';
|
||||
import { StreamService } from './stream.service';
|
||||
|
||||
export enum ConferenceState {
|
||||
none,
|
||||
stream,
|
||||
jitsi
|
||||
none = 1,
|
||||
stream = 2,
|
||||
jitsi = 3
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
@ -20,17 +20,14 @@ export enum ConferenceState {
|
||||
export class InteractionService {
|
||||
private conferenceStateSubject = new BehaviorSubject<ConferenceState>(ConferenceState.none);
|
||||
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 {
|
||||
return this.conferenceStateSubject.value;
|
||||
}
|
||||
|
||||
private isJitsiEnabled: boolean;
|
||||
private isInCall: boolean;
|
||||
private isJitsiActive: boolean;
|
||||
private hasLiveStreamUrl: boolean;
|
||||
private canSeeLiveStream: boolean;
|
||||
private showLiveConf: boolean;
|
||||
|
||||
public get isConfStateStream(): Observable<boolean> {
|
||||
return this.conferenceStateObservable.pipe(map(state => state === ConferenceState.stream));
|
||||
@ -50,36 +47,38 @@ export class InteractionService {
|
||||
private rtcService: RtcService,
|
||||
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
|
||||
* be my guest.
|
||||
*/
|
||||
this.streamService.liveStreamUrlObservable.subscribe(url => {
|
||||
this.hasLiveStreamUrl = !!url?.trim() ?? false;
|
||||
this.detectDeadState();
|
||||
});
|
||||
|
||||
this.streamService.canSeeLiveStreamObservable.subscribe(canSee => {
|
||||
this.canSeeLiveStream = canSee;
|
||||
this.detectDeadState();
|
||||
});
|
||||
|
||||
this.rtcService.isJitsiEnabledObservable.subscribe(enabled => {
|
||||
this.isJitsiEnabled = enabled;
|
||||
this.detectDeadState();
|
||||
});
|
||||
|
||||
this.rtcService.isJoinedObservable.subscribe(joined => {
|
||||
this.isInCall = joined;
|
||||
this.detectDeadState();
|
||||
});
|
||||
|
||||
this.rtcService.isJitsiActiveObservable.subscribe(isActive => {
|
||||
this.isJitsiActive = isActive;
|
||||
this.detectDeadState();
|
||||
});
|
||||
/**
|
||||
* most importantly, if there is a call, to not change the state here
|
||||
*/
|
||||
if (inCall || jitsiActive) {
|
||||
return;
|
||||
}
|
||||
if (hasStreamUrl && canSeeStream) {
|
||||
return ConferenceState.stream;
|
||||
} else if (showConf && jitsiEnabled && canEnterCall && (!hasStreamUrl || !canSeeStream)) {
|
||||
return ConferenceState.jitsi;
|
||||
} else {
|
||||
return ConferenceState.none;
|
||||
}
|
||||
}
|
||||
)
|
||||
.pipe(distinctUntilChanged())
|
||||
.subscribe(state => {
|
||||
if (state) {
|
||||
this.setConferenceState(state);
|
||||
}
|
||||
});
|
||||
|
||||
this.callRestrictionService.hasToEnterCallObservable.subscribe(() => {
|
||||
if (!this.isInCall) {
|
||||
@ -91,13 +90,6 @@ export class InteractionService {
|
||||
this.callRestrictionService.hasToLeaveCallObservable.subscribe(() => {
|
||||
this.viewStream();
|
||||
});
|
||||
|
||||
this.showLiveConfObservable.subscribe(showConf => {
|
||||
this.showLiveConf = showConf;
|
||||
this.detectDeadState();
|
||||
});
|
||||
|
||||
this.detectDeadState();
|
||||
}
|
||||
|
||||
public async enterCall(): Promise<void> {
|
||||
@ -117,37 +109,4 @@ export class InteractionService {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
|
||||
import { StorageMap } from '@ngx-pwa/local-storage';
|
||||
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 { ConfigService } from 'app/core/ui-services/config.service';
|
||||
@ -13,7 +13,10 @@ const STREAM_RUNNING_STORAGE_KEY = 'streamIsRunning';
|
||||
providedIn: 'root'
|
||||
})
|
||||
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
|
||||
@ -28,9 +31,11 @@ export class StreamService {
|
||||
private canSeeLiveStreamSubject = new Subject<boolean>();
|
||||
public canSeeLiveStreamObservable = this.canSeeLiveStreamSubject.asObservable();
|
||||
|
||||
public constructor(private storageMap: StorageMap, operator: OperatorService, configService: ConfigService) {
|
||||
this.liveStreamUrlObservable = configService.get<string>('general_system_stream_url');
|
||||
|
||||
public constructor(
|
||||
private storageMap: StorageMap,
|
||||
operator: OperatorService,
|
||||
private configService: ConfigService
|
||||
) {
|
||||
this.streamLoadedOnceObservable = this.storageMap
|
||||
.watch(STREAM_RUNNING_STORAGE_KEY, { type: 'boolean' })
|
||||
.pipe(distinctUntilChanged());
|
||||
|
Loading…
Reference in New Issue
Block a user