mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-23 15:30:34 -04:00
165 lines
6.1 KiB
TypeScript
165 lines
6.1 KiB
TypeScript
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
DestroyRef,
|
|
HostListener,
|
|
inject,
|
|
OnInit
|
|
} from '@angular/core';
|
|
import {NavigationStart, Router, RouterOutlet} from '@angular/router';
|
|
import {map, shareReplay, take, tap} from 'rxjs/operators';
|
|
import {AccountService} from './_services/account.service';
|
|
import {LibraryService} from './_services/library.service';
|
|
import {NavService} from './_services/nav.service';
|
|
import {NgbModal, NgbModalConfig, NgbOffcanvas, NgbRatingConfig} from '@ng-bootstrap/ng-bootstrap';
|
|
import {AsyncPipe, DOCUMENT, NgClass} from '@angular/common';
|
|
import {filter, interval, Observable, switchMap} from 'rxjs';
|
|
import {ThemeService} from "./_services/theme.service";
|
|
import {SideNavComponent} from './sidenav/_components/side-nav/side-nav.component';
|
|
import {NavHeaderComponent} from "./nav/_components/nav-header/nav-header.component";
|
|
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
|
import {ServerService} from "./_services/server.service";
|
|
import {OutOfDateModalComponent} from "./announcements/_components/out-of-date-modal/out-of-date-modal.component";
|
|
import {PreferenceNavComponent} from "./sidenav/preference-nav/preference-nav.component";
|
|
import {Breakpoint, UtilityService} from "./shared/_services/utility.service";
|
|
import {TranslocoService} from "@jsverse/transloco";
|
|
|
|
@Component({
|
|
selector: 'app-root',
|
|
templateUrl: './app.component.html',
|
|
styleUrls: ['./app.component.scss'],
|
|
standalone: true,
|
|
imports: [NgClass, SideNavComponent, RouterOutlet, AsyncPipe, NavHeaderComponent, PreferenceNavComponent],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class AppComponent implements OnInit {
|
|
|
|
transitionState$!: Observable<boolean>;
|
|
|
|
private readonly destroyRef = inject(DestroyRef);
|
|
private readonly offcanvas = inject(NgbOffcanvas);
|
|
protected readonly navService = inject(NavService);
|
|
protected readonly utilityService = inject(UtilityService);
|
|
protected readonly serverService = inject(ServerService);
|
|
protected readonly accountService = inject(AccountService);
|
|
private readonly libraryService = inject(LibraryService);
|
|
private readonly ngbModal = inject(NgbModal);
|
|
private readonly router = inject(Router);
|
|
private readonly themeService = inject(ThemeService);
|
|
private readonly document = inject(DOCUMENT);
|
|
private readonly translocoService = inject(TranslocoService);
|
|
|
|
protected readonly Breakpoint = Breakpoint;
|
|
|
|
|
|
constructor(ratingConfig: NgbRatingConfig, modalConfig: NgbModalConfig) {
|
|
|
|
modalConfig.fullscreen = 'md';
|
|
|
|
// Setup default rating config
|
|
ratingConfig.max = 5;
|
|
ratingConfig.resettable = true;
|
|
|
|
// Close any open modals when a route change occurs
|
|
this.router.events
|
|
.pipe(
|
|
filter(event => event instanceof NavigationStart),
|
|
takeUntilDestroyed(this.destroyRef)
|
|
)
|
|
.subscribe(async (event) => {
|
|
|
|
if (!this.ngbModal.hasOpenModals() && !this.offcanvas.hasOpenOffcanvas()) return;
|
|
|
|
if (this.ngbModal.hasOpenModals()) {
|
|
this.ngbModal.dismissAll();
|
|
}
|
|
|
|
if (this.offcanvas.hasOpenOffcanvas()) {
|
|
this.offcanvas.dismiss();
|
|
}
|
|
|
|
if ((event as any).navigationTrigger === 'popstate') {
|
|
const currentRoute = this.router.routerState;
|
|
await this.router.navigateByUrl(currentRoute.snapshot.url, { skipLocationChange: true });
|
|
}
|
|
});
|
|
|
|
|
|
this.transitionState$ = this.accountService.currentUser$.pipe(
|
|
map((user) => {
|
|
if (!user) return false;
|
|
return user.preferences.noTransitions;
|
|
}), takeUntilDestroyed(this.destroyRef));
|
|
|
|
|
|
}
|
|
|
|
@HostListener('window:resize', ['$event'])
|
|
@HostListener('window:orientationchange', ['$event'])
|
|
setDocHeight() {
|
|
// Sets a CSS variable for the actual device viewport height. Needed for mobile dev.
|
|
const vh = window.innerHeight * 0.01;
|
|
this.document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
this.utilityService.activeBreakpointSource.next(this.utilityService.getActiveBreakpoint());
|
|
}
|
|
|
|
ngOnInit(): void {
|
|
this.setDocHeight();
|
|
this.setCurrentUser();
|
|
this.themeService.setColorScape('');
|
|
}
|
|
|
|
|
|
setCurrentUser() {
|
|
const user = this.accountService.getUserFromLocalStorage();
|
|
this.accountService.setCurrentUser(user);
|
|
|
|
if (!user) return;
|
|
|
|
// Bootstrap anything that's needed
|
|
this.themeService.getThemes().subscribe();
|
|
this.libraryService.getLibraryNames().pipe(take(1), shareReplay({refCount: true, bufferSize: 1})).subscribe();
|
|
|
|
// Get the server version, compare vs localStorage, and if different bust locale cache
|
|
const versionKey = 'kavita--version';
|
|
this.serverService.getVersion(user.apiKey).subscribe(version => {
|
|
const cachedVersion = localStorage.getItem(versionKey);
|
|
console.log('Kavita version: ', version, ' Running version: ', cachedVersion);
|
|
|
|
if (cachedVersion == null || cachedVersion != version) {
|
|
// Bust locale cache
|
|
this.bustLocaleCache();
|
|
localStorage.setItem(versionKey, version);
|
|
location.reload();
|
|
}
|
|
localStorage.setItem(versionKey, version);
|
|
});
|
|
|
|
// Every hour, have the UI check for an update. People seriously stay out of date
|
|
interval(2* 60 * 60 * 1000) // 2 hours in milliseconds
|
|
.pipe(
|
|
switchMap(() => this.accountService.currentUser$),
|
|
filter(u => u !== undefined && this.accountService.hasAdminRole(u)),
|
|
switchMap(_ => this.serverService.checkHowOutOfDate()),
|
|
filter(versionOutOfDate => {
|
|
return !isNaN(versionOutOfDate) && versionOutOfDate > 2;
|
|
}),
|
|
tap(versionOutOfDate => {
|
|
if (!this.ngbModal.hasOpenModals()) {
|
|
const ref = this.ngbModal.open(OutOfDateModalComponent, {size: 'xl', fullscreen: 'md'});
|
|
ref.componentInstance.versionsOutOfDate = versionOutOfDate;
|
|
}
|
|
})
|
|
)
|
|
.subscribe();
|
|
}
|
|
|
|
private bustLocaleCache() {
|
|
localStorage.removeItem('@transloco/translations/timestamp');
|
|
localStorage.removeItem('@transloco/translations');
|
|
localStorage.removeItem('translocoLang');
|
|
(this.translocoService as any).cache.delete(localStorage.getItem('kavita-locale') || 'en');
|
|
(this.translocoService as any).cache.clear();
|
|
}
|
|
}
|