Merge pull request #5437 from tsiegleauq/another-fake-dialog

Replace jitsi mat dialog
This commit is contained in:
Emanuel Schütze 2020-06-25 17:50:39 +02:00 committed by GitHub
commit 6898458695
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 146 additions and 140 deletions

View File

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

View File

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

View File

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

View File

@ -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> {

View File

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

View File

@ -136,10 +136,6 @@ mat-sidenav-container {
} }
.toolbars { .toolbars {
z-index: 99;
position: fixed;
right: 0;
bottom: 0;
display: flex; display: flex;
* { * {