import { Component, HostListener, ViewChild } from '@angular/core'; import { DateAdapter } from '@angular/material/core'; import { Router } from '@angular/router'; import { fromEvent } from 'rxjs'; import { AuthService } from '../../services/auth.service'; import { I18nService } from '../../services/i18n.service'; import { UserService } from '../../services/user.service'; import { MatSidenav } from '@angular/material/sidenav'; import { SwUpdate } from '@angular/service-worker'; import { DebugService } from 'src/app/services/debug.service'; import packageJson from '../../../../package.json'; @Component({ standalone: false, selector: 'ui-main', templateUrl: './main.ui.html', styleUrls: ['./main.ui.scss'] }) export class UiMain { opened: boolean = true; darkTheme: boolean = false; title = 'buntspecht'; currentLocale: string; datetimeformat: string; locales; authenticated: boolean = false; username: string = ""; admin: boolean = false; debug: boolean = false; hasUpdate: boolean = false; isBiggerScreen: boolean = false; touchThresh: number = 150; touchStartX: number; touchX: number; version = packageJson.version; @ViewChild('sidenav') sidenav: MatSidenav; constructor( private i18n: I18nService, private authService: AuthService, private userService: UserService, private debugService: DebugService, private router: Router, private _adapter: DateAdapter, private swUpdate: SwUpdate) { this.swUpdate.versionUpdates.subscribe({ next: (evt) => { if (evt.type == 'VERSION_READY') { this.hasUpdate = true; } else if (evt.type == 'VERSION_INSTALLATION_FAILED') { console.error(`Failed to install version '${evt.version.hash}': ${evt.error}`); } } }) if (this.swUpdate.isEnabled) { // check for PWA update every 30s setInterval(() => { this.swUpdate.checkForUpdate(); }, 30000); } } async ngOnInit() { this.datetimeformat = this.i18n.get('format.datetime', []); this.currentLocale = this.i18n.getLocale(); this.locales = this.i18n.getLocales(); this.authService.auth.subscribe({ next: (auth) => { this.authenticated = true; this.username = auth.username; this.admin = auth.authorities && auth.authorities.find((role) => role.authority == 'ROLE_ADMIN') != undefined; this.debug = auth.authorities && auth.authorities.find((role) => role.authority == 'ROLE_DEBUG') != undefined; }, error: (error) => { this.authenticated = false; this.opened = false; } }) this._adapter.setLocale(this.currentLocale); const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; if (width < 768) { this.opened = false; this.isBiggerScreen = false; } else { this.opened = true; this.isBiggerScreen = true; } if (localStorage.getItem("buntspecht.darkTheme") == "true") { this.darkTheme = true; window.document.body.classList.add("dark-theme"); } this.touchEvents(); } setLocale(locale) { localStorage.setItem("buntspecht.locale", locale); if (this.authenticated) { this.userService.get().subscribe({ next: (user: any) => { user.locale = locale; this.userService.update(user).subscribe({ next: () => { window.location.reload(); } }) } }); } else { window.location.reload(); } } close() { this.opened = false; this.sidenav.close(); } preventClose(event) { event.preventDefault(); event.stopPropagation(); } toggleDarkTheme() { this.darkTheme = !this.darkTheme; localStorage.setItem("buntspecht.darkTheme", this.darkTheme ? "true" : "false"); if (this.authenticated) { this.userService.get().subscribe({ next: (user: any) => { user.darkTheme = this.darkTheme; this.userService.update(user).subscribe({ next: () => { window.location.reload(); } }) } }); } else { window.location.reload(); } } logout() { localStorage.removeItem("buntspecht.autologin"); this.authService.logout().subscribe({ next: () => { this.router.navigate([""]).then(() => { window.location.reload(); }); } }) } openExternal(event, url, target = '_self') { window.open(url, target); this.preventClose(event); } @HostListener('window:resize', ['$event']) onResize(event) { if (event.target.innerWidth < 768) { this.opened = false; this.isBiggerScreen = false; } else { this.opened = true; this.isBiggerScreen = true; } } touchEvents(): void { fromEvent(document, 'touchstart').subscribe({ next: (event: TouchEvent) => { if (event.touches[0]) { this.touchStartX = event.touches[0].screenX; } } }) fromEvent(document, 'touchmove').subscribe({ next: (event: TouchEvent) => { if (event.touches[0]) { this.touchX = event.touches[0].screenX; } } }) fromEvent(document, 'touchend').subscribe({ next: () => { if (this.touchX != 0) { const touchDiff = this.touchStartX - this.touchX; this.touchStartX = 0; this.touchX = 0; if (touchDiff < 0 && touchDiff < (this.touchThresh * -1) && !this.opened) { this.opened = true; } else if (touchDiff > 0 && touchDiff > this.touchThresh && this.opened) { this.opened = false; } } } }) } updateSw(force: boolean = false): void { if (this.hasUpdate || force) { if (this.swUpdate.isEnabled) { this.swUpdate.activateUpdate().then(() => { this.clearAndRefresh(); }); } else { this.clearAndRefresh(); } } } clearAndRefresh() { if ('caches' in window) { caches.keys() .then(function (keyList) { return Promise.all(keyList.map(function (key) { return caches.delete(key); })); }) } window.location.reload(); } random() { this.debugService.random().subscribe({ next: () => { window.location.reload(); } }); } }