Replaces the snackbar for offline-mode with a banner.

This commit is contained in:
GabrielMeyer 2019-08-20 14:57:20 +02:00
parent bbe294a1ad
commit c5f90b0972
9 changed files with 95 additions and 55 deletions

View File

@ -1,56 +1,51 @@
import { Injectable } from '@angular/core';
import { WebsocketService } from './websocket.service';
import { BehaviorSubject, Observable } from 'rxjs';
/**
* This service handles everything connected with being offline.
*
* TODO: This is just a stub. Needs to be done in the future; Maybe we cancel this whole concept
* of this service. We'll see whats happens here..
* of this service. We'll see what happens here..
*/
@Injectable({
providedIn: 'root'
})
export class OfflineService {
private _offline = false;
public get offline(): boolean {
return this._offline;
}
/**
* BehaviorSubject to receive further status values.
*/
public constructor(private socketService: WebsocketService) {}
private offline = new BehaviorSubject<boolean>(false);
/**
* Determines of you are either in Offline mode or not connected via websocket
*
* @returns whether the client is offline or not connected
*/
public isOffline(): boolean {
return this.offline || !this.socketService.isConnected;
public isOffline(): Observable<boolean> {
return this.offline;
}
/**
* Sets the offline flag. Restores the DataStoreService to the last known configuration.
*/
public goOfflineBecauseFailedWhoAmI(): void {
this._offline = true;
this.offline.next(true);
console.log('offline because whoami failed.');
}
/**
* TODO: Should be somehow connected to the websocket service.
* Sets the offline flag, because there is no connection to the server.
*/
public goOfflineBecauseConnectionLost(): void {
this._offline = true;
this.offline.next(true);
console.log('offline because connection lost.');
}
/**
* TODO: Should be somehow connected to the websocket service.
* Function to return to online-status.
*/
public goOnline(): void {
this._offline = false;
this.offline.next(false);
}
}

View File

@ -1,13 +1,13 @@
import { EventEmitter, Injectable, NgZone } from '@angular/core';
import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar';
import { MatSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { compress, decompress } from 'lz4js';
import { Observable, Subject } from 'rxjs';
import { take } from 'rxjs/operators';
import { TextDecoder, TextEncoder } from 'text-encoding';
import { OfflineService } from './offline.service';
import { OpenSlidesStatusService } from './openslides-status.service';
import { formatQueryParams, QueryParams } from '../definitions/query-params';
@ -189,17 +189,17 @@ export class WebsocketService {
/**
* Constructor that handles the router
* @param matSnackBar
*
* @param zone
* @param translate
* @param router
* @param openSlidesStatusService
* @param offlineService
*/
public constructor(
private matSnackBar: MatSnackBar,
private zone: NgZone,
private translate: TranslateService,
private router: Router,
private openSlidesStatusService: OpenSlidesStatusService
private openSlidesStatusService: OpenSlidesStatusService,
private offlineService: OfflineService
) {}
/**
@ -380,12 +380,7 @@ export class WebsocketService {
}
if (!this.connectionErrorNotice && !onProjector && this.retryCounter > 3) {
// So here we have a connection failure that wasn't intendet.
this.connectionErrorNotice = this.matSnackBar.open(
this.translate.instant('Offline mode: You can use OpenSlides but changes are not saved.'),
'',
{ duration: 0 }
);
this.offlineService.goOfflineBecauseConnectionLost();
}
// A random retry timeout between 2000 and 5000 ms.
@ -405,10 +400,7 @@ export class WebsocketService {
}
private dismissConnectionErrorNotice(): void {
if (this.connectionErrorNotice) {
this.connectionErrorNotice.dismiss();
this.connectionErrorNotice = null;
}
this.offlineService.goOnline();
}
/**

View File

@ -1,6 +1,6 @@
<div id="container" class="projector-container" [osResized]="resizeSubject" #container>
<div id="projector" class="projector">
<div id="offline-indicator" *ngIf="isOffline()">
<div id="offline-indicator" *ngIf="isOffline">
<mat-icon>
fiber_manual_record
</mat-icon>

View File

@ -148,11 +148,21 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
*/
public scale = 0;
/**
* Info about if the user is offline.
*/
public isOffline = false;
/**
* The subscription to the projector.
*/
private projectorSubscription: Subscription;
/**
* Holds the subscription to the offline-service.
*/
private offlineSubscription: Subscription;
/**
* A subject that fires, if the container is resized.
*/
@ -226,15 +236,8 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
this.updateScaling();
}
});
}
/**
* determine if the server is offline
*
* @returns whether the client is offlien
*/
public isOffline(): boolean {
return this.offlineService.isOffline();
this.offlineSubscription = this.offlineService.isOffline().subscribe(isOffline => (this.isOffline = isOffline));
}
/**
@ -327,5 +330,9 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
}
document.head.removeChild(this.styleElement);
this.styleElement = null;
if (this.offlineSubscription) {
this.offlineSubscription.unsubscribe();
this.offlineSubscription = null;
}
}
}

View File

@ -1,3 +1,4 @@
<div class="offline-banner" *ngIf="isOffline"><mat-icon>cloud_off</mat-icon><span translate>Offline mode</span></div>
<div class="history-mode-indicator" *ngIf="OSStatus.isInHistoryMode">
<span translate>You are using the history mode of OpenSlides. Changes will not be saved.</span>
<span>({{ getHistoryTimestamp() }})</span>
@ -133,7 +134,6 @@
<div class="os-footer-logo-container">
<os-logo [footer]="true"></os-logo>
</div>
</mat-nav-list>
<!-- Toggle-button -->
<div class="nav-toggle-button-container" *ngIf="!vp.isMobile">

View File

@ -48,5 +48,30 @@
color: mat-color($primary);
}
}
/** style for the offline-banner */
.offline-banner {
display: flex;
top: 0;
z-index: 2;
width: 100%;
height: 20px;
background: mat-color($primary, 900);
align-items: center;
justify-content: center;
color: white;
mat-icon {
$font-size: 16px;
width: $font-size;
height: $font-size;
font-size: $font-size;
}
span {
font-size: 90%;
margin: 0 5px;
}
}
}
}

View File

@ -10,6 +10,7 @@ import { TranslateService } from '@ngx-translate/core';
import { filter } from 'rxjs/operators';
import { navItemAnim, pageTransition } from '../shared/animations';
import { OfflineService } from 'app/core/core-services/offline.service';
import { ConfigService } from 'app/core/ui-services/config.service';
import { UpdateService } from 'app/core/ui-services/update.service';
import { langToLocale } from 'app/shared/utils/lang-to-locale';
@ -52,6 +53,11 @@ export class SiteComponent extends BaseComponent implements OnInit {
*/
public isLoggedIn: boolean;
/**
* Indicates, whether the user is offline or not.
*/
public isOffline: boolean;
/**
* Holds the typed search query.
*/
@ -84,6 +90,7 @@ export class SiteComponent extends BaseComponent implements OnInit {
title: Title,
protected translate: TranslateService,
configService: ConfigService,
offlineService: OfflineService,
private updateService: UpdateService,
private authService: AuthService,
private router: Router,
@ -106,6 +113,10 @@ export class SiteComponent extends BaseComponent implements OnInit {
this.isLoggedIn = !!user;
});
offlineService.isOffline().subscribe(offline => {
this.isOffline = offline;
});
this.searchform = new FormGroup({ query: new FormControl([]) });
// detect routing data such as base perm and noInterruption

View File

@ -6,9 +6,9 @@ $openslides-green: (
400: #62a64b,
500: #46962b,
600: #3f8e26,
700: #0a321e,
800: #092d1a,
900: #072616,
700: #378320,
800: #2f791a,
900: #206810,
A100: #acff9d,
A200: #80ff6a,
A400: #55ff37,

View File

@ -7,18 +7,18 @@ $openslides-blue: (
400: #508ba6,
500: #317796,
600: #2c6f8e,
700: #002a42,
800: #00253c,
900: #001f33,
700: #256483,
800: #1f5a79,
900: #134768,
A100: #9fd7ff,
A200: #6cc2ff,
A400: #39acff,
A700: #1fa2ff,
contrast: (
50: #ffffff,
100: #ffffff,
200: #ffffff,
300: #ffffff,
50: #000000,
100: #000000,
200: #000000,
300: #000000,
400: #ffffff,
500: #ffffff,
600: #ffffff,
@ -57,9 +57,19 @@ $os-background: mat-color($mat-grey, 100);
* The components will get a value from this map.
*/
$background: map-get($openslides-theme, background);
$background: map_merge($background, (background: $os-background));
$background: map_merge(
$background,
(
background: $os-background
)
);
/**
* Merge the theme with the custom-background.
*/
$openslides-theme: map_merge($openslides-theme, (background: $background));
$openslides-theme: map_merge(
$openslides-theme,
(
background: $background
)
);