2019-12-17 10:00:57 +01:00
|
|
|
import { ApplicationRef, Component } from '@angular/core';
|
2019-07-26 11:46:59 +02:00
|
|
|
import { Router } from '@angular/router';
|
2019-01-19 21:55:06 +01:00
|
|
|
|
2019-07-26 11:46:59 +02:00
|
|
|
import { TranslateService } from '@ngx-translate/core';
|
2019-12-17 10:00:57 +01:00
|
|
|
import { filter, take } from 'rxjs/operators';
|
2019-03-06 07:38:43 +01:00
|
|
|
|
2019-01-31 13:40:27 +01:00
|
|
|
import { ConfigService } from './core/ui-services/config.service';
|
2019-04-15 13:30:18 +02:00
|
|
|
import { ConstantsService } from './core/core-services/constants.service';
|
2019-02-26 11:38:29 +01:00
|
|
|
import { CountUsersService } from './core/ui-services/count-users.service';
|
2019-07-26 11:46:59 +02:00
|
|
|
import { DataStoreUpgradeService } from './core/core-services/data-store-upgrade.service';
|
2019-02-26 11:38:29 +01:00
|
|
|
import { LoadFontService } from './core/ui-services/load-font.service';
|
|
|
|
import { LoginDataService } from './core/ui-services/login-data.service';
|
|
|
|
import { OperatorService } from './core/core-services/operator.service';
|
2019-07-11 14:06:01 +02:00
|
|
|
import { OverlayService } from './core/ui-services/overlay.service';
|
2019-04-15 14:19:40 +02:00
|
|
|
import { PingService } from './core/core-services/ping.service';
|
2019-07-26 11:46:59 +02:00
|
|
|
import { PrioritizeService } from './core/core-services/prioritize.service';
|
|
|
|
import { RoutingStateService } from './core/ui-services/routing-state.service';
|
|
|
|
import { ServertimeService } from './core/core-services/servertime.service';
|
|
|
|
import { ThemeService } from './core/ui-services/theme.service';
|
2019-11-12 18:30:26 +01:00
|
|
|
import { VotingBannerService } from './core/ui-services/voting-banner.service';
|
2018-06-13 18:34:10 +02:00
|
|
|
|
2019-05-09 12:52:10 +02:00
|
|
|
declare global {
|
2019-07-11 14:06:01 +02:00
|
|
|
/**
|
|
|
|
* Enhance array with own functions
|
|
|
|
* TODO: Remove once flatMap made its way into official JS/TS (ES 2019?)
|
|
|
|
*/
|
2019-05-09 12:52:10 +02:00
|
|
|
interface Array<T> {
|
2019-07-26 11:46:59 +02:00
|
|
|
flatMap(o: any): any[];
|
2019-11-12 18:30:26 +01:00
|
|
|
intersect(a: T[]): T[];
|
|
|
|
mapToObject(f: (item: T) => { [key: string]: any }): { [key: string]: any };
|
2019-05-09 12:52:10 +02:00
|
|
|
}
|
2019-07-11 14:06:01 +02:00
|
|
|
|
2020-01-30 16:59:46 +01:00
|
|
|
interface Set<T> {
|
|
|
|
equals(other: Set<T>): boolean;
|
|
|
|
}
|
|
|
|
|
2019-07-11 14:06:01 +02:00
|
|
|
/**
|
|
|
|
* Enhances the number object to calculate real modulo operations.
|
|
|
|
* (not remainder)
|
|
|
|
*/
|
|
|
|
interface Number {
|
|
|
|
modulo(n: number): number;
|
|
|
|
}
|
2019-05-09 12:52:10 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 14:11:31 +02:00
|
|
|
/**
|
|
|
|
* Angular's global App Component
|
|
|
|
*/
|
2018-06-13 18:34:10 +02:00
|
|
|
@Component({
|
2018-09-03 17:57:20 +02:00
|
|
|
selector: 'os-root',
|
2018-06-19 16:55:50 +02:00
|
|
|
templateUrl: './app.component.html',
|
2018-08-28 09:33:50 +02:00
|
|
|
styleUrls: ['./app.component.scss']
|
2018-06-13 18:34:10 +02:00
|
|
|
})
|
2018-07-06 09:38:25 +02:00
|
|
|
export class AppComponent {
|
2018-08-28 11:07:10 +02:00
|
|
|
/**
|
2018-09-18 18:27:14 +02:00
|
|
|
* Master-component of all apps.
|
|
|
|
*
|
|
|
|
* Inits the translation service, the operator, the login data and the constants.
|
|
|
|
*
|
|
|
|
* Handles the altering of Array.toString()
|
|
|
|
*
|
2019-02-26 11:38:29 +01:00
|
|
|
* @param translate To set the default language
|
|
|
|
* @param operator To call the constructor of the OperatorService
|
|
|
|
* @param loginDataService to call the constructor of the LoginDataService
|
|
|
|
* @param constantService to call the constructor of the ConstantService
|
|
|
|
* @param servertimeService executes the scheduler early on
|
2019-01-29 15:20:00 +01:00
|
|
|
* @param themeService used to listen to theme-changes
|
2019-02-26 11:38:29 +01:00
|
|
|
* @param countUsersService to call the constructor of the CountUserService
|
|
|
|
* @param configService to call the constructor of the ConfigService
|
|
|
|
* @param loadFontService to call the constructor of the LoadFontService
|
2019-05-03 17:39:48 +02:00
|
|
|
* @param dataStoreUpgradeService
|
2018-07-12 14:11:31 +02:00
|
|
|
*/
|
2018-08-29 13:21:25 +02:00
|
|
|
public constructor(
|
|
|
|
translate: TranslateService,
|
2019-12-17 10:00:57 +01:00
|
|
|
appRef: ApplicationRef,
|
2019-03-04 14:40:02 +01:00
|
|
|
servertimeService: ServertimeService,
|
2019-04-08 10:57:43 +02:00
|
|
|
router: Router,
|
2019-09-12 12:35:46 +02:00
|
|
|
operator: OperatorService,
|
2018-09-10 08:15:31 +02:00
|
|
|
loginDataService: LoginDataService,
|
2019-01-24 16:25:50 +01:00
|
|
|
constantsService: ConstantsService, // Needs to be started, so it can register itself to the WebsocketService
|
2019-01-19 21:55:06 +01:00
|
|
|
themeService: ThemeService,
|
2019-09-12 12:35:46 +02:00
|
|
|
overlayService: OverlayService,
|
2019-02-26 11:38:29 +01:00
|
|
|
countUsersService: CountUsersService, // Needed to register itself.
|
|
|
|
configService: ConfigService,
|
2019-04-15 13:30:18 +02:00
|
|
|
loadFontService: LoadFontService,
|
2019-05-03 17:39:48 +02:00
|
|
|
dataStoreUpgradeService: DataStoreUpgradeService, // to start it.
|
2019-04-15 14:19:40 +02:00
|
|
|
prioritizeService: PrioritizeService,
|
2019-06-25 10:45:24 +02:00
|
|
|
pingService: PingService,
|
2019-11-12 18:30:26 +01:00
|
|
|
routingState: RoutingStateService,
|
|
|
|
votingBannerService: VotingBannerService // needed for initialisation
|
2018-08-23 15:28:57 +02:00
|
|
|
) {
|
2018-06-29 17:24:44 +02:00
|
|
|
// manually add the supported languages
|
2019-09-04 09:34:55 +02:00
|
|
|
translate.addLangs(['en', 'de', 'cs', 'ru']);
|
2018-06-29 17:24:44 +02:00
|
|
|
// this language will be used as a fallback when a translation isn't found in the current language
|
|
|
|
translate.setDefaultLang('en');
|
|
|
|
// get the browsers default language
|
|
|
|
const browserLang = translate.getBrowserLang();
|
|
|
|
// try to use the browser language if it is available. If not, uses english.
|
|
|
|
translate.use(translate.getLangs().includes(browserLang) ? browserLang : 'en');
|
2019-08-06 14:37:41 +02:00
|
|
|
|
2018-09-18 18:27:14 +02:00
|
|
|
// change default JS functions
|
2019-11-12 18:30:26 +01:00
|
|
|
this.overloadArrayFunctions();
|
2020-01-30 16:59:46 +01:00
|
|
|
this.overloadSetFunctions();
|
2019-07-11 14:06:01 +02:00
|
|
|
this.overloadModulo();
|
|
|
|
|
2019-12-17 10:00:57 +01:00
|
|
|
// Wait until the App reaches a stable state.
|
|
|
|
// Required for the Service Worker.
|
|
|
|
appRef.isStable
|
|
|
|
.pipe(
|
|
|
|
// take only the stable state
|
|
|
|
filter(s => s),
|
|
|
|
take(1)
|
|
|
|
)
|
|
|
|
.subscribe(() => servertimeService.startScheduler());
|
2018-09-18 18:27:14 +02:00
|
|
|
}
|
|
|
|
|
2020-01-22 17:39:10 +01:00
|
|
|
private overloadArrayFunctions(): void {
|
2020-01-23 12:38:46 +01:00
|
|
|
Object.defineProperty(Array.prototype, 'toString', {
|
2020-04-01 12:46:06 +02:00
|
|
|
value: function (): string {
|
2020-01-23 12:38:46 +01:00
|
|
|
let string = '';
|
|
|
|
const iterations = Math.min(this.length, 3);
|
2018-09-18 18:27:14 +02:00
|
|
|
|
2020-01-23 12:38:46 +01:00
|
|
|
for (let i = 0; i <= iterations; i++) {
|
|
|
|
if (i < iterations) {
|
|
|
|
string += this[i];
|
|
|
|
}
|
2018-09-18 18:27:14 +02:00
|
|
|
|
2020-01-23 12:38:46 +01:00
|
|
|
if (i < iterations - 1) {
|
|
|
|
string += ', ';
|
|
|
|
} else if (i === iterations && this.length > iterations) {
|
|
|
|
string += ', ...';
|
|
|
|
}
|
2018-09-18 18:27:14 +02:00
|
|
|
}
|
2020-01-23 12:38:46 +01:00
|
|
|
return string;
|
|
|
|
},
|
|
|
|
enumerable: false
|
|
|
|
});
|
2019-05-27 17:58:43 +02:00
|
|
|
|
2020-01-23 12:38:46 +01:00
|
|
|
Object.defineProperty(Array.prototype, 'flatMap', {
|
2020-04-01 12:46:06 +02:00
|
|
|
value: function (o: any): any[] {
|
2020-01-29 12:47:42 +01:00
|
|
|
const concatFunction = (x: any, y: any[]) => x.concat(y);
|
|
|
|
const flatMapLogic = (f: any, xs: any) => xs.map(f).reduce(concatFunction, []);
|
|
|
|
return flatMapLogic(o, this);
|
|
|
|
},
|
2020-01-23 12:38:46 +01:00
|
|
|
enumerable: false
|
|
|
|
});
|
2019-11-12 18:30:26 +01:00
|
|
|
|
|
|
|
Object.defineProperty(Array.prototype, 'intersect', {
|
2020-04-01 12:46:06 +02:00
|
|
|
value: function <T>(other: T[]): T[] {
|
2020-01-22 17:39:10 +01:00
|
|
|
let a = this;
|
|
|
|
let b = other;
|
2019-11-12 18:30:26 +01:00
|
|
|
// indexOf to loop over shorter
|
|
|
|
if (b.length > a.length) {
|
|
|
|
[a, b] = [b, a];
|
|
|
|
}
|
|
|
|
return a.filter(e => b.indexOf(e) > -1);
|
|
|
|
},
|
|
|
|
enumerable: false
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.defineProperty(Array.prototype, 'mapToObject', {
|
2020-04-01 12:46:06 +02:00
|
|
|
value: function <T>(f: (item: T) => { [key: string]: any }): { [key: string]: any } {
|
2019-11-12 18:30:26 +01:00
|
|
|
return this.reduce((aggr, item) => {
|
|
|
|
const res = f(item);
|
|
|
|
for (const key in res) {
|
|
|
|
if (res.hasOwnProperty(key)) {
|
|
|
|
aggr[key] = res[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aggr;
|
|
|
|
}, {});
|
|
|
|
},
|
|
|
|
enumerable: false
|
|
|
|
});
|
2019-05-09 12:52:10 +02:00
|
|
|
}
|
|
|
|
|
2020-01-30 16:59:46 +01:00
|
|
|
/**
|
|
|
|
* Adds some functions to Set.
|
|
|
|
*/
|
|
|
|
private overloadSetFunctions(): void {
|
|
|
|
Object.defineProperty(Set.prototype, 'equals', {
|
2020-04-01 12:46:06 +02:00
|
|
|
value: function <T>(other: Set<T>): boolean {
|
2020-03-16 09:29:22 +01:00
|
|
|
const difference = new Set(this);
|
2020-01-30 16:59:46 +01:00
|
|
|
for (const elem of other) {
|
2020-03-16 09:29:22 +01:00
|
|
|
if (difference.has(elem)) {
|
|
|
|
difference.delete(elem);
|
2020-01-30 16:59:46 +01:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2020-03-16 09:29:22 +01:00
|
|
|
return !difference.size;
|
2020-01-30 16:59:46 +01:00
|
|
|
},
|
|
|
|
enumerable: false
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-07-11 14:06:01 +02:00
|
|
|
/**
|
|
|
|
* Enhances the number object with a real modulo operation (not remainder).
|
|
|
|
* TODO: Remove this, if the remainder operation is changed to modulo.
|
|
|
|
*/
|
|
|
|
private overloadModulo(): void {
|
2020-01-23 12:38:46 +01:00
|
|
|
Object.defineProperty(Number.prototype, 'modulo', {
|
2020-04-01 12:46:06 +02:00
|
|
|
value: function (n: number): number {
|
2020-01-23 12:38:46 +01:00
|
|
|
return ((this % n) + n) % n;
|
|
|
|
},
|
|
|
|
enumerable: false
|
|
|
|
});
|
2019-07-11 14:06:01 +02:00
|
|
|
}
|
2018-06-13 18:34:10 +02:00
|
|
|
}
|