Replace jitsi mat dialog
Replace Jitsis Mat Dialog with an div container Fixes an issue where observables in jitsi would register multiple times Clear the IndexedDB on logout
This commit is contained in:
parent
bb10c25974
commit
c2a1b62c8b
@ -8,6 +8,7 @@ import { DEFAULT_AUTH_TYPE, UserAuthType } from 'app/shared/models/users/user';
|
|||||||
import { DataStoreService } from './data-store.service';
|
import { DataStoreService } from './data-store.service';
|
||||||
import { HttpService } from './http.service';
|
import { HttpService } from './http.service';
|
||||||
import { OpenSlidesService } from './openslides.service';
|
import { OpenSlidesService } from './openslides.service';
|
||||||
|
import { StorageService } from './storage.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticates an OpenSlides user with username and password
|
* Authenticates an OpenSlides user with username and password
|
||||||
@ -29,7 +30,8 @@ export class AuthService {
|
|||||||
private operator: OperatorService,
|
private operator: OperatorService,
|
||||||
private OpenSlides: OpenSlidesService,
|
private OpenSlides: OpenSlidesService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private DS: DataStoreService
|
private DS: DataStoreService,
|
||||||
|
private storageService: StorageService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,10 +108,12 @@ export class AuthService {
|
|||||||
// We do nothing on failures. Reboot OpenSlides anyway.
|
// We do nothing on failures. Reboot OpenSlides anyway.
|
||||||
}
|
}
|
||||||
this.router.navigate(['/']);
|
this.router.navigate(['/']);
|
||||||
|
await this.storageService.clear();
|
||||||
await this.DS.clear();
|
await this.DS.clear();
|
||||||
await this.operator.setWhoAmI(response);
|
await this.operator.setWhoAmI(response);
|
||||||
await this.OpenSlides.reboot();
|
await this.OpenSlides.reboot();
|
||||||
} else if (authType === 'saml') {
|
} else if (authType === 'saml') {
|
||||||
|
await this.storageService.clear();
|
||||||
await this.DS.clear();
|
await this.DS.clear();
|
||||||
await this.operator.setWhoAmI(null);
|
await this.operator.setWhoAmI(null);
|
||||||
window.location.href = environment.urlPrefix + '/saml/?slo'; // Bye
|
window.location.href = environment.urlPrefix + '/saml/?slo'; // Bye
|
||||||
|
@ -1,29 +1,30 @@
|
|||||||
<!-- iFrame Dialog -->
|
<!-- iFrame Dialog -->
|
||||||
<ng-template #conferenceDialog>
|
<div class="jitsi-fake-dialog-wrapper" [ngClass]="{'jitsi-dialog-hide': !isJitsiDialogOpen}">
|
||||||
<div class="jitsi-iframe-wrapper" #jitsi></div>
|
<mat-card class="jitsi-fake-dialog">
|
||||||
<div mat-dialog-actions>
|
<div class="jitsi-iframe-wrapper" #jitsi></div>
|
||||||
<button
|
<div class="jitsi-dialog-actions">
|
||||||
type="button"
|
<button
|
||||||
mat-button
|
type="button"
|
||||||
color=""
|
mat-button
|
||||||
(click)="openExternal()"
|
color="primary"
|
||||||
matTooltip="{{ 'Open Jitsi in new tab' | translate }}"
|
(click)="openExternal()"
|
||||||
>
|
matTooltip="{{ 'Open Jitsi in new tab' | translate }}"
|
||||||
<mat-icon>open_in_new</mat-icon>
|
>
|
||||||
</button>
|
<mat-icon>open_in_new</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="minimize-jitsi-dialog-button"
|
type="button"
|
||||||
type="button"
|
mat-button
|
||||||
mat-button
|
color="primary"
|
||||||
color="primary"
|
(click)="hideJitsiDialog()"
|
||||||
(click)="hideJitsiDialog()"
|
>
|
||||||
>
|
<span>{{ 'Minimize' | translate }}</span>
|
||||||
<span>{{ 'Minimize' | translate }}</span>
|
<mat-icon>fullscreen_exit</mat-icon>
|
||||||
<mat-icon>fullscreen_exit</mat-icon>
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</mat-card>
|
||||||
</ng-template>
|
</div>
|
||||||
|
|
||||||
<div class="jitsi-integration" *ngIf="enableJitsi || (videoStreamUrl && canSeeLiveStream)">
|
<div class="jitsi-integration" *ngIf="enableJitsi || (videoStreamUrl && canSeeLiveStream)">
|
||||||
<!-- Audio-Conference-bar -->
|
<!-- Audio-Conference-bar -->
|
||||||
@ -172,7 +173,7 @@
|
|||||||
<os-vjs-player
|
<os-vjs-player
|
||||||
[videoUrl]="videoStreamUrl"
|
[videoUrl]="videoStreamUrl"
|
||||||
(started)="onSteamStarted()"
|
(started)="onSteamStarted()"
|
||||||
*ngIf="canSeeLiveStream && !streamActiveInAnotherTab || streamRunning"
|
*ngIf="(canSeeLiveStream && !streamActiveInAnotherTab) || streamRunning"
|
||||||
></os-vjs-player>
|
></os-vjs-player>
|
||||||
<div class="disconnected" *ngIf="streamActiveInAnotherTab && !streamRunning">
|
<div class="disconnected" *ngIf="streamActiveInAnotherTab && !streamRunning">
|
||||||
<span>{{ 'The livestream is already running in your OpenSlides session.' | translate }}</span>
|
<span>{{ 'The livestream is already running in your OpenSlides session.' | translate }}</span>
|
||||||
|
@ -1,19 +1,39 @@
|
|||||||
|
.jitsi-fake-dialog-wrapper {
|
||||||
|
z-index: 98;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
padding: 20px 10% 20px 5%;
|
||||||
|
|
||||||
|
.jitsi-fake-dialog {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
height: 90%;
|
||||||
|
|
||||||
|
.jitsi-iframe-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jitsi-dialog-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.jitsi-dialog-hide {
|
.jitsi-dialog-hide {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jitsi-iframe-wrapper {
|
|
||||||
height: 70vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.minimize-jitsi-dialog-button {
|
|
||||||
margin-left: auto !important;
|
|
||||||
span {
|
|
||||||
line-height: initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.jitsi-integration {
|
.jitsi-integration {
|
||||||
|
z-index: 99;
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
.cast-shadow {
|
.cast-shadow {
|
||||||
box-shadow: -3px -3px 10px 0px rgba(0, 0, 0, 0.2) !important;
|
box-shadow: -3px -3px 10px 0px rgba(0, 0, 0, 0.2) !important;
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,17 @@
|
|||||||
import {
|
import { Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
Component,
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
ElementRef,
|
|
||||||
HostListener,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit,
|
|
||||||
TemplateRef,
|
|
||||||
ViewChild,
|
|
||||||
ViewEncapsulation
|
|
||||||
} from '@angular/core';
|
|
||||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { StorageMap } from '@ngx-pwa/local-storage';
|
import { StorageMap } from '@ngx-pwa/local-storage';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { distinctUntilChanged } from 'rxjs/operators';
|
import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
|
||||||
import { BaseComponent } from 'app/base.component';
|
|
||||||
import { ConstantsService } from 'app/core/core-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
import { Deferred } from 'app/core/promises/deferred';
|
import { Deferred } from 'app/core/promises/deferred';
|
||||||
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
|
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
|
||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
import { largeDialogSettings } from 'app/shared/utils/dialog-settings';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
|
|
||||||
declare var JitsiMeetExternalAPI: any;
|
declare var JitsiMeetExternalAPI: any;
|
||||||
|
|
||||||
@ -66,7 +56,7 @@ enum ConferenceState {
|
|||||||
styleUrls: ['./jitsi.component.scss'],
|
styleUrls: ['./jitsi.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
export class JitsiComponent extends BaseViewComponent implements OnInit, OnDestroy {
|
||||||
public enableJitsi: boolean;
|
public enableJitsi: boolean;
|
||||||
|
|
||||||
private autoconnect: boolean;
|
private autoconnect: boolean;
|
||||||
@ -87,11 +77,6 @@ export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
@ViewChild('jitsi')
|
@ViewChild('jitsi')
|
||||||
private jitsiNode: ElementRef;
|
private jitsiNode: ElementRef;
|
||||||
|
|
||||||
@ViewChild('conferenceDialog', { static: true })
|
|
||||||
public conferenceDialog: TemplateRef<string>;
|
|
||||||
|
|
||||||
private confDialogRef: MatDialogRef<any>;
|
|
||||||
|
|
||||||
// JitsiMeet api object
|
// JitsiMeet api object
|
||||||
private api: any | null;
|
private api: any | null;
|
||||||
|
|
||||||
@ -109,8 +94,8 @@ export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
private configsLoaded: Deferred<void> = new Deferred();
|
private configsLoaded: Deferred<void> = new Deferred();
|
||||||
|
|
||||||
// storage locks
|
// storage locks
|
||||||
public isJitsiActiveInAnotherTab: boolean;
|
public isJitsiActiveInAnotherTab = false;
|
||||||
public streamActiveInAnotherTab: boolean;
|
public streamActiveInAnotherTab = false;
|
||||||
|
|
||||||
private RTC_LOGGED_STORAGE_KEY = 'rtcIsLoggedIn';
|
private RTC_LOGGED_STORAGE_KEY = 'rtcIsLoggedIn';
|
||||||
private STREAM_RUNNING_STORAGE_KEY = 'streamIsRunning';
|
private STREAM_RUNNING_STORAGE_KEY = 'streamIsRunning';
|
||||||
@ -176,26 +161,22 @@ export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
public constructor(
|
public constructor(
|
||||||
titleService: Title,
|
titleService: Title,
|
||||||
translate: TranslateService,
|
translate: TranslateService,
|
||||||
|
snackBar: MatSnackBar,
|
||||||
private operator: OperatorService,
|
private operator: OperatorService,
|
||||||
private storageMap: StorageMap,
|
private storageMap: StorageMap,
|
||||||
private userRepo: UserRepositoryService,
|
private userRepo: UserRepositoryService,
|
||||||
private constantsService: ConstantsService,
|
private constantsService: ConstantsService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService
|
||||||
private dialog: MatDialog
|
|
||||||
) {
|
) {
|
||||||
super(titleService, translate);
|
super(titleService, translate, snackBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
this.confDialogRef = this.dialog.open(this.conferenceDialog, {
|
|
||||||
...largeDialogSettings,
|
|
||||||
panelClass: 'jitsi-dialog-hide',
|
|
||||||
hasBackdrop: false
|
|
||||||
});
|
|
||||||
this.setUp();
|
this.setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ngOnDestroy(): Promise<void> {
|
public async ngOnDestroy(): Promise<void> {
|
||||||
|
super.ngOnDestroy();
|
||||||
this.stopConference();
|
this.stopConference();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,25 +195,29 @@ export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async setUp(): Promise<void> {
|
private async setUp(): Promise<void> {
|
||||||
this.storageMap
|
this.subscriptions.push(
|
||||||
.watch(this.RTC_LOGGED_STORAGE_KEY)
|
this.storageMap
|
||||||
.pipe(distinctUntilChanged())
|
.watch(this.RTC_LOGGED_STORAGE_KEY)
|
||||||
.subscribe((inUse: boolean) => {
|
.pipe(distinctUntilChanged())
|
||||||
this.isJitsiActiveInAnotherTab = inUse;
|
.subscribe((inUse: boolean) => {
|
||||||
this.lockLoaded.resolve();
|
console.log('RTC_LOGGED_STORAGE_KEY is in use: ', inUse);
|
||||||
if (!inUse && !this.isJitsiActive) {
|
|
||||||
this.startJitsi();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.storageMap
|
this.isJitsiActiveInAnotherTab = inUse;
|
||||||
.watch(this.STREAM_RUNNING_STORAGE_KEY)
|
this.lockLoaded.resolve();
|
||||||
.pipe(distinctUntilChanged())
|
if (!inUse && !this.isJitsiActive) {
|
||||||
.subscribe((running: boolean) => {
|
this.startJitsi();
|
||||||
this.streamActiveInAnotherTab = running;
|
}
|
||||||
});
|
}),
|
||||||
|
this.storageMap
|
||||||
|
.watch(this.STREAM_RUNNING_STORAGE_KEY)
|
||||||
|
.pipe(distinctUntilChanged())
|
||||||
|
.subscribe((running: boolean) => {
|
||||||
|
this.streamActiveInAnotherTab = running;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
await this.lockLoaded;
|
await this.lockLoaded;
|
||||||
|
|
||||||
this.constantsService.get<JitsiSettings>('Settings').subscribe(settings => {
|
this.constantsService.get<JitsiSettings>('Settings').subscribe(settings => {
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.jitsiDomain = settings.JITSI_DOMAIN;
|
this.jitsiDomain = settings.JITSI_DOMAIN;
|
||||||
@ -243,63 +228,64 @@ export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await this.constantsLoaded;
|
await this.constantsLoaded;
|
||||||
this.configService
|
|
||||||
.get<boolean>('general_system_conference_auto_connect')
|
|
||||||
.subscribe(autoconnect => (this.autoconnect = autoconnect));
|
|
||||||
|
|
||||||
this.configService.get<boolean>('general_system_conference_show').subscribe(show => {
|
this.subscriptions.push(
|
||||||
this.enableJitsi = show && !!this.jitsiDomain && !!this.roomName;
|
this.configService
|
||||||
if (this.enableJitsi && this.autoconnect) {
|
.get<boolean>('general_system_conference_auto_connect')
|
||||||
this.startJitsi();
|
.subscribe(autoconnect => (this.autoconnect = autoconnect)),
|
||||||
} else {
|
this.configService.get<boolean>('general_system_conference_show').subscribe(show => {
|
||||||
this.stopJitsi();
|
this.enableJitsi = show && !!this.jitsiDomain && !!this.roomName;
|
||||||
}
|
if (this.enableJitsi && this.autoconnect) {
|
||||||
});
|
this.startJitsi();
|
||||||
|
} else {
|
||||||
this.configService.get<boolean>('general_system_conference_los_restriction').subscribe(restricted => {
|
this.stopJitsi();
|
||||||
this.restricted = restricted;
|
}
|
||||||
});
|
}),
|
||||||
|
this.configService.get<boolean>('general_system_conference_los_restriction').subscribe(restricted => {
|
||||||
this.configService.get<string>('general_system_stream_url').subscribe(url => {
|
this.restricted = restricted;
|
||||||
this.videoStreamUrl = url;
|
}),
|
||||||
this.configsLoaded.resolve();
|
this.configService.get<string>('general_system_stream_url').subscribe(url => {
|
||||||
});
|
this.videoStreamUrl = url;
|
||||||
|
this.configsLoaded.resolve();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
await this.configsLoaded;
|
await this.configsLoaded;
|
||||||
// after configs are loaded
|
|
||||||
this.storageMap
|
this.subscriptions.push(
|
||||||
.watch(this.CONFERENCE_STATE_STORAGE_KEY)
|
this.storageMap
|
||||||
.pipe(distinctUntilChanged())
|
.watch(this.CONFERENCE_STATE_STORAGE_KEY)
|
||||||
.subscribe((confState: ConferenceState) => {
|
.pipe(distinctUntilChanged())
|
||||||
if (confState in ConferenceState) {
|
.subscribe((confState: ConferenceState) => {
|
||||||
if (this.enableJitsi && (!this.videoStreamUrl || !this.canSeeLiveStream)) {
|
if (confState in ConferenceState) {
|
||||||
this.currentState = ConferenceState.jitsi;
|
if (this.enableJitsi && (!this.videoStreamUrl || !this.canSeeLiveStream)) {
|
||||||
} else if (!this.enableJitsi && this.videoStreamUrl && this.canSeeLiveStream) {
|
this.currentState = ConferenceState.jitsi;
|
||||||
this.currentState = ConferenceState.stream;
|
} else if (!this.enableJitsi && this.videoStreamUrl && this.canSeeLiveStream) {
|
||||||
|
this.currentState = ConferenceState.stream;
|
||||||
|
} else {
|
||||||
|
this.currentState = confState;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.currentState = confState;
|
this.setDefaultConfState();
|
||||||
}
|
}
|
||||||
} else {
|
// show stream window when the state changes to stream
|
||||||
this.setDefaultConfState();
|
if (this.currentState === ConferenceState.stream && !this.streamActiveInAnotherTab) {
|
||||||
}
|
this.showJitsiWindow = true;
|
||||||
// show stream window when the state changes to stream
|
}
|
||||||
if (this.currentState === ConferenceState.stream && !this.streamActiveInAnotherTab) {
|
}),
|
||||||
this.showJitsiWindow = true;
|
// check if the user is on the clos, remove from room if not permitted
|
||||||
}
|
this.operator
|
||||||
});
|
.isOnCurrentListOfSpeakersObservable()
|
||||||
|
.pipe(distinctUntilChanged())
|
||||||
|
.subscribe(isOnList => {
|
||||||
|
this.isOnCurrentLos = isOnList;
|
||||||
|
console.log('this.isOnCurrentLos: ', this.isOnCurrentLos);
|
||||||
|
|
||||||
// check if the user is on the clos, remove from room if not permitted
|
if (!this.isAccessPermitted) {
|
||||||
this.operator
|
this.viewStream();
|
||||||
.isOnCurrentListOfSpeakersObservable()
|
}
|
||||||
.pipe(distinctUntilChanged())
|
})
|
||||||
.subscribe(isOnList => {
|
);
|
||||||
this.isOnCurrentLos = isOnList;
|
|
||||||
console.log('this.isOnCurrentLos: ', this.isOnCurrentLos);
|
|
||||||
|
|
||||||
if (!this.isAccessPermitted) {
|
|
||||||
this.viewStream();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleMute(): void {
|
public toggleMute(): void {
|
||||||
@ -463,13 +449,12 @@ export class JitsiComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public hideJitsiDialog(): void {
|
public hideJitsiDialog(): void {
|
||||||
this.confDialogRef.addPanelClass('jitsi-dialog-hide');
|
|
||||||
this.isJitsiDialogOpen = false;
|
this.isJitsiDialogOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public showJitsiDialog(): void {
|
public showJitsiDialog(): void {
|
||||||
this.confDialogRef.removePanelClass('jitsi-dialog-hide');
|
|
||||||
this.isJitsiDialogOpen = true;
|
this.isJitsiDialogOpen = true;
|
||||||
|
this.showJitsiWindow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async viewStream(): Promise<void> {
|
public async viewStream(): Promise<void> {
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
{{ assignment.getListTitle() }}
|
{{ assignment.getListTitle() }}
|
||||||
</div>
|
</div>
|
||||||
<mat-chip-list class="ellipsis-overflow" *ngIf="vp.isMobile">
|
<mat-chip-list class="ellipsis-overflow" *ngIf="vp.isMobile">
|
||||||
<mat-chip color="" selected>
|
<mat-chip color="primary" selected>
|
||||||
{{ assignment.phaseString | translate }}
|
{{ assignment.phaseString | translate }}
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
|
@ -136,10 +136,6 @@ mat-sidenav-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toolbars {
|
.toolbars {
|
||||||
z-index: 99;
|
|
||||||
position: fixed;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
Loading…
Reference in New Issue
Block a user