1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

adding browser history support for lightbox

This commit is contained in:
Patrik J. Braun 2018-05-26 20:49:55 -04:00
parent 4afff63415
commit 62ccedcc2f
17 changed files with 221 additions and 70 deletions

View File

@ -7,6 +7,7 @@ import {Title} from '@angular/platform-browser';
import {NotificationService} from './model/notification.service'; import {NotificationService} from './model/notification.service';
import {ShareService} from './gallery/share.service'; import {ShareService} from './gallery/share.service';
import 'hammerjs'; import 'hammerjs';
import {QueryService} from './model/query.service';
@Component({ @Component({
selector: 'app-pi-gallery2', selector: 'app-pi-gallery2',

View File

@ -66,6 +66,7 @@ import {DefaultUrlSerializer, UrlSerializer, UrlTree} from '@angular/router';
import {IndexingSettingsComponent} from './settings/indexing/indexing.settings.component'; import {IndexingSettingsComponent} from './settings/indexing/indexing.settings.component';
import {LanguageComponent} from './language/language.component'; import {LanguageComponent} from './language/language.component';
import {I18n, MISSING_TRANSLATION_STRATEGY} from '@ngx-translate/i18n-polyfill'; import {I18n, MISSING_TRANSLATION_STRATEGY} from '@ngx-translate/i18n-polyfill';
import {QueryService} from './model/query.service';
@Injectable() @Injectable()
export class GoogleMapsConfig { export class GoogleMapsConfig {
@ -173,18 +174,19 @@ export function translationsFactory(locale: string) {
NavigationService, NavigationService,
SettingsService, SettingsService,
OverlayService, OverlayService,
QueryService,
{ {
provide: TRANSLATIONS, provide: TRANSLATIONS,
useFactory: translationsFactory, useFactory: translationsFactory,
deps: [LOCALE_ID] deps: [LOCALE_ID]
}, },
I18n, I18n,
/*
{provide: TRANSLATIONS, useValue: translationsFactory('en')}, {provide: TRANSLATIONS, useValue: translationsFactory('en')},
{provide: TRANSLATIONS_FORMAT, useValue: 'xlf'}, {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
{provide: LOCALE_ID, useValue: 'en'}, {provide: LOCALE_ID, useValue: 'en'},
{provide: MISSING_TRANSLATION_STRATEGY, useValue: MissingTranslationStrategy.Ignore}, {provide: MISSING_TRANSLATION_STRATEGY, useValue: MissingTranslationStrategy.Ignore},
*/
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

View File

@ -1,7 +1,7 @@
<ng2-slim-loading-bar [color]="'#337ab7'" [height]="'3px'"></ng2-slim-loading-bar> <ng2-slim-loading-bar [color]="'#337ab7'" [height]="'3px'"></ng2-slim-loading-bar>
<nav class="navbar navbar-dark bg-dark navbar-expand-md"> <nav class="navbar navbar-dark bg-dark navbar-expand-md">
<a class="navbar-brand" [routerLink]="['/gallery','/']" <a class="navbar-brand" [routerLink]="['/gallery','/']"
[queryParams]="_shareService.isSharing() ? { sk: _shareService.getSharingKey() }:{}"> [queryParams]="queryService.getParams()">
<img src="assets/icon_inv.png" width="30" height="30" class="d-inline-block align-top" alt=""> <img src="assets/icon_inv.png" width="30" height="30" class="d-inline-block align-top" alt="">
<strong>{{title}}</strong> <strong>{{title}}</strong>
</a> </a>

View File

@ -6,6 +6,7 @@ import {Config} from '../../../common/config/public/Config';
import {BehaviorSubject} from 'rxjs'; import {BehaviorSubject} from 'rxjs';
import {NotificationService} from '../model/notification.service'; import {NotificationService} from '../model/notification.service';
import {ShareService} from '../gallery/share.service'; import {ShareService} from '../gallery/share.service';
import {QueryService} from '../model/query.service';
@Component({ @Component({
selector: 'app-frame', selector: 'app-frame',
@ -23,7 +24,7 @@ export class FrameComponent {
constructor(private _authService: AuthenticationService, constructor(private _authService: AuthenticationService,
public notificationService: NotificationService, public notificationService: NotificationService,
public _shareService: ShareService) { public queryService: QueryService) {
this.user = this._authService.user; this.user = this._authService.user;
this.authenticationRequired = Config.Client.authenticationRequired; this.authenticationRequired = Config.Client.authenticationRequired;
this.title = Config.Client.applicationTitle; this.title = Config.Client.applicationTitle;

View File

@ -1,5 +1,6 @@
<a #dirContainer class="button btn btn-default" [routerLink]="['/gallery', getDirectoryPath()]" <a #dirContainer class="button btn btn-default"
[queryParams]="_shareService.isSharing() ? { sk: _shareService.getSharingKey() }:{}" [routerLink]="['/gallery', getDirectoryPath()]"
[queryParams]="queryService.getParams()"
style="display: inline-block;"> style="display: inline-block;">

View File

@ -7,6 +7,7 @@ import {Photo} from '../Photo';
import {Thumbnail, ThumbnailManagerService} from '../thumnailManager.service'; import {Thumbnail, ThumbnailManagerService} from '../thumnailManager.service';
import {ShareService} from '../share.service'; import {ShareService} from '../share.service';
import {PageHelper} from '../../model/page.helper'; import {PageHelper} from '../../model/page.helper';
import {QueryService} from '../../model/query.service';
@Component({ @Component({
selector: 'app-gallery-directory', selector: 'app-gallery-directory',
@ -21,7 +22,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy {
constructor(private thumbnailService: ThumbnailManagerService, constructor(private thumbnailService: ThumbnailManagerService,
private _sanitizer: DomSanitizer, private _sanitizer: DomSanitizer,
public _shareService: ShareService) { public queryService: QueryService) {
} }

View File

@ -1,4 +1,4 @@
<app-gallery-lightbox #lightbox (onLastElement)="onLightboxLastElement()"></app-gallery-lightbox> <app-gallery-lightbox #lightbox></app-gallery-lightbox>
<app-frame> <app-frame>
<ng-container navbar> <ng-container navbar>

View File

@ -14,6 +14,8 @@ import {UserRoles} from '../../../common/entities/UserDTO';
import {interval} from 'rxjs'; import {interval} from 'rxjs';
import {ContentWrapper} from '../../../common/entities/ConentWrapper'; import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {PageHelper} from '../model/page.helper'; import {PageHelper} from '../model/page.helper';
import {QueryService} from '../model/query.service';
import {LightboxStates} from './lightbox/lightbox.gallery.component';
@Component({ @Component({
selector: 'app-gallery', selector: 'app-gallery',
@ -92,6 +94,7 @@ export class GalleryComponent implements OnInit, OnDestroy {
this._galleryService.getDirectory(directoryName); this._galleryService.getDirectory(directoryName);
}; };
ngOnDestroy() { ngOnDestroy() {
@ -150,11 +153,5 @@ export class GalleryComponent implements OnInit, OnDestroy {
} }
onLightboxLastElement() {
this.grid.renderARow();
}
} }

View File

@ -12,6 +12,9 @@ export class GridRowBuilder {
private photoMargin: number, private photoMargin: number,
private containerWidth: number) { private containerWidth: number) {
this.photoIndex = startIndex; this.photoIndex = startIndex;
if (this.containerWidth <= 0) {
throw new Error('container width cant be <=0, got:' + this.containerWidth);
}
} }
public addPhotos(number: number) { public addPhotos(number: number) {

View File

@ -1,7 +1,9 @@
<div #gridContainer> <div #gridContainer>
<app-gallery-grid-photo <app-gallery-grid-photo
*ngFor="let gridPhoto of photosToRender" *ngFor="let gridPhoto of photosToRender"
(click)="lightbox.show(gridPhoto.photo)"
[routerLink]="[]"
[queryParams]="queryService.getParams(gridPhoto.photo)"
[gridPhoto]="gridPhoto" [gridPhoto]="gridPhoto"
[style.width.px]="gridPhoto.renderWidth" [style.width.px]="gridPhoto.renderWidth"
[style.height.px]="gridPhoto.renderHeight" [style.height.px]="gridPhoto.renderHeight"

View File

@ -9,23 +9,28 @@ import {
OnDestroy, OnDestroy,
QueryList, QueryList,
ViewChild, ViewChild,
ViewChildren ViewChildren,
OnInit
} from '@angular/core'; } from '@angular/core';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {GridRowBuilder} from './GridRowBuilder'; import {GridRowBuilder} from './GridRowBuilder';
import {GalleryLightboxComponent} from '../lightbox/lightbox.gallery.component'; import {GalleryLightboxComponent, LightboxStates} from '../lightbox/lightbox.gallery.component';
import {GridPhoto} from './GridPhoto'; import {GridPhoto} from './GridPhoto';
import {GalleryPhotoComponent} from './photo/photo.grid.gallery.component'; import {GalleryPhotoComponent} from './photo/photo.grid.gallery.component';
import {OverlayService} from '../overlay.service'; import {OverlayService} from '../overlay.service';
import {Config} from '../../../../common/config/public/Config'; import {Config} from '../../../../common/config/public/Config';
import {PageHelper} from '../../model/page.helper'; import {PageHelper} from '../../model/page.helper';
import {Subscription} from 'rxjs';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {QueryService} from '../../model/query.service';
import {SimpleChanges} from '@angular/core';
@Component({ @Component({
selector: 'app-gallery-grid', selector: 'app-gallery-grid',
templateUrl: './grid.gallery.component.html', templateUrl: './grid.gallery.component.html',
styleUrls: ['./grid.gallery.component.css'], styleUrls: ['./grid.gallery.component.css'],
}) })
export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy { export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, OnDestroy {
@ViewChild('gridContainer') gridContainer: ElementRef; @ViewChild('gridContainer') gridContainer: ElementRef;
@ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList<GalleryPhotoComponent>; @ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList<GalleryPhotoComponent>;
@ -47,9 +52,27 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
private helperTime = null; private helperTime = null;
isAfterViewInit = false; isAfterViewInit = false;
private renderedPhotoIndex = 0; private renderedPhotoIndex = 0;
routeSubscription: Subscription = null;
delayedRenderUpToPhoto: string = null;
constructor(private overlayService: OverlayService, constructor(private overlayService: OverlayService,
private changeDetector: ChangeDetectorRef) { private changeDetector: ChangeDetectorRef,
public queryService: QueryService,
private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
this.routeSubscription = this.route.queryParams.subscribe((params: Params) => {
if (params[QueryService.PHOTO_PARAM] && params[QueryService.PHOTO_PARAM] !== '') {
this.delayedRenderUpToPhoto = params[QueryService.PHOTO_PARAM];
if (!this.photos || this.photos.length === 0) {
return;
}
this.renderUpToPhoto(params[QueryService.PHOTO_PARAM]);
}
});
} }
ngOnChanges() { ngOnChanges() {
@ -61,6 +84,9 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
this.mergeNewPhotos(); this.mergeNewPhotos();
this.helperTime = setTimeout(() => { this.helperTime = setTimeout(() => {
this.renderPhotos(); this.renderPhotos();
if (this.delayedRenderUpToPhoto) {
this.renderUpToPhoto(this.delayedRenderUpToPhoto);
}
}, 0); }, 0);
} }
@ -105,11 +131,22 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
this.isAfterViewInit = true; this.isAfterViewInit = true;
} }
public renderARow(): number {
if (this.renderedPhotoIndex >= this.photos.length) { private renderUpToPhoto(photoName: string) {
return null; const index = this.photos.findIndex(p => p.name === photoName);
if (index === -1) {
this.router.navigate([], {queryParams: this.queryService.getParams()});
return;
}
while (this.renderedPhotoIndex < index && this.renderARow()) {
}
} }
public renderARow(): number {
if (this.renderedPhotoIndex >= this.photos.length
|| this.containerWidth === 0) {
return null;
}
let maxRowHeight = this.screenHeight / this.MIN_ROW_COUNT; let maxRowHeight = this.screenHeight / this.MIN_ROW_COUNT;
const minRowHeight = this.screenHeight / this.MAX_ROW_COUNT; const minRowHeight = this.screenHeight / this.MAX_ROW_COUNT;
@ -146,7 +183,7 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
} }
private sortPhotos() { private sortPhotos() {
// sort pohots by date // sort photos by date
this.photos.sort((a: PhotoDTO, b: PhotoDTO) => { this.photos.sort((a: PhotoDTO, b: PhotoDTO) => {
return a.metadata.creationDate - b.metadata.creationDate; return a.metadata.creationDate - b.metadata.creationDate;
}); });
@ -168,7 +205,6 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
break; break;
} }
} }
if (lastSameIndex > 0) { if (lastSameIndex > 0) {
this.photosToRender.splice(lastSameIndex, this.photosToRender.length - lastSameIndex); this.photosToRender.splice(lastSameIndex, this.photosToRender.length - lastSameIndex);
this.renderedPhotoIndex = lastSameIndex; this.renderedPhotoIndex = lastSameIndex;
@ -239,6 +275,8 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
return false; return false;
} }
const pre = PageHelper.isScrollYVisible();
PageHelper.showScrollY();
// if the width changed a bit or the height changed a lot // if the width changed a bit or the height changed a lot
if (this.containerWidth !== this.gridContainer.nativeElement.clientWidth if (this.containerWidth !== this.gridContainer.nativeElement.clientWidth
|| this.screenHeight < window.innerHeight * 0.75 || this.screenHeight < window.innerHeight * 0.75
@ -246,9 +284,15 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
this.screenHeight = window.innerHeight; this.screenHeight = window.innerHeight;
this.containerWidth = this.gridContainer.nativeElement.clientWidth; this.containerWidth = this.gridContainer.nativeElement.clientWidth;
this.clearRenderedPhotos(); this.clearRenderedPhotos();
if (!pre) {
PageHelper.hideScrollY();
}
return true; return true;
} }
if (!pre) {
PageHelper.hideScrollY();
}
return false; return false;
} }

View File

@ -1,4 +1,4 @@
<div [hidden]="!visible" #root> <div [hidden]="!isVisible()" #root>
<div class="blackCanvas" <div class="blackCanvas"
[style.opacity]="blackCanvasOpacity"> [style.opacity]="blackCanvasOpacity">

View File

@ -19,6 +19,15 @@ import {animate, AnimationBuilder, AnimationPlayer, style} from '@angular/animat
import {GalleryLightboxPhotoComponent} from './photo/photo.lightbox.gallery.component'; import {GalleryLightboxPhotoComponent} from './photo/photo.lightbox.gallery.component';
import {Observable, Subscription, timer} from 'rxjs'; import {Observable, Subscription, timer} from 'rxjs';
import {filter} from 'rxjs/operators'; import {filter} from 'rxjs/operators';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {PageHelper} from '../../model/page.helper';
import {QueryService} from '../../model/query.service';
export enum LightboxStates {
Open,
Closing,
Closed
}
@Component({ @Component({
selector: 'app-gallery-lightbox', selector: 'app-gallery-lightbox',
@ -27,8 +36,6 @@ import {filter} from 'rxjs/operators';
}) })
export class GalleryLightboxComponent implements OnDestroy, OnInit { export class GalleryLightboxComponent implements OnDestroy, OnInit {
@Output('onLastElement') onLastElement = new EventEmitter();
@ViewChild('photo') photoElement: GalleryLightboxPhotoComponent; @ViewChild('photo') photoElement: GalleryLightboxPhotoComponent;
@ViewChild('lightbox') lightboxElement: ElementRef; @ViewChild('lightbox') lightboxElement: ElementRef;
@ -39,8 +46,14 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
public activePhoto: GalleryPhotoComponent; public activePhoto: GalleryPhotoComponent;
private gridPhotoQL: QueryList<GalleryPhotoComponent>; private gridPhotoQL: QueryList<GalleryPhotoComponent>;
public visible = false; public status: LightboxStates = LightboxStates.Closed;
private changeSubscription: Subscription = null; private subscription: {
photosChange: Subscription,
route: Subscription
} = {
photosChange: null,
route: null
};
private timer: Observable<number>; private timer: Observable<number>;
private timerSub: Subscription; private timerSub: Subscription;
public playBackState = 0; public playBackState = 0;
@ -53,21 +66,41 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0}; startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0};
iPvisibilityTimer = null; iPvisibilityTimer = null;
visibilityTimer = null; visibilityTimer = null;
delayedPhotoShow: string = null;
constructor(public fullScreenService: FullScreenService, constructor(public fullScreenService: FullScreenService,
private changeDetector: ChangeDetectorRef, private overlayService: OverlayService, private changeDetector: ChangeDetectorRef,
private _builder: AnimationBuilder) { private overlayService: OverlayService,
private _builder: AnimationBuilder,
private router: Router,
private queryService: QueryService,
private route: ActivatedRoute) {
} }
ngOnInit(): void { ngOnInit(): void {
this.timer = timer(1000, 2000); this.timer = timer(1000, 2000);
this.subscription.route = this.route.queryParams.subscribe((params: Params) => {
if (params[QueryService.PHOTO_PARAM] && params[QueryService.PHOTO_PARAM] !== '') {
if (!this.gridPhotoQL) {
return this.delayedPhotoShow = params[QueryService.PHOTO_PARAM];
}
this.onNavigateTo(params[QueryService.PHOTO_PARAM]);
} else if (this.status === LightboxStates.Open) {
this.delayedPhotoShow = null;
this.hideLigthbox();
}
});
} }
ngOnDestroy(): void { ngOnDestroy(): void {
console.log('destroy');
this.pause(); this.pause();
if (this.changeSubscription != null) { if (this.subscription.photosChange != null) {
this.changeSubscription.unsubscribe(); this.subscription.photosChange.unsubscribe();
}
if (this.subscription.route != null) {
this.subscription.route.unsubscribe();
} }
if (this.visibilityTimer != null) { if (this.visibilityTimer != null) {
@ -78,6 +111,41 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
} }
} }
onNavigateTo(photoName: string) {
if (this.activePhoto && this.activePhoto.gridPhoto.photo.name === photoName) {
return;
}
const photo = this.gridPhotoQL.find(i => i.gridPhoto.photo.name === photoName);
if (!photo) {
return this.delayedPhotoShow = photoName;
}
if (this.status === LightboxStates.Closed) {
this.showLigthbox(photo.gridPhoto.photo);
} else {
this.showPhoto(this.gridPhotoQL.toArray().indexOf(photo));
}
this.delayedPhotoShow = null;
}
setGridPhotoQL(value: QueryList<GalleryPhotoComponent>) {
if (this.subscription.photosChange != null) {
this.subscription.photosChange.unsubscribe();
}
this.gridPhotoQL = value;
this.subscription.photosChange = this.gridPhotoQL.changes.subscribe(() => {
if (this.activePhotoId != null && this.gridPhotoQL.length > this.activePhotoId) {
this.updateActivePhoto(this.activePhotoId);
}
if (this.delayedPhotoShow) {
this.onNavigateTo(this.delayedPhotoShow);
}
});
if (this.delayedPhotoShow) {
this.onNavigateTo(this.delayedPhotoShow);
}
}
//noinspection JSUnusedGlobalSymbols //noinspection JSUnusedGlobalSymbols
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])
onResize() { onResize() {
@ -89,10 +157,10 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
public nextImage() { public nextImage() {
if (this.activePhotoId + 1 < this.gridPhotoQL.length) { if (this.activePhotoId + 1 < this.gridPhotoQL.length) {
this.showPhoto(this.activePhotoId + 1); this.navigateToPhoto(this.activePhotoId + 1);
if (this.activePhotoId + 3 >= this.gridPhotoQL.length) { /*if (this.activePhotoId + 3 >= this.gridPhotoQL.length) {
this.onLastElement.emit({}); // trigger to render more photos if there are this.onLastElement.emit({}); // trigger to render more photos if there are
} }*/
return; return;
} }
} }
@ -100,29 +168,38 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
public prevImage() { public prevImage() {
this.pause(); this.pause();
if (this.activePhotoId > 0) { if (this.activePhotoId > 0) {
this.showPhoto(this.activePhotoId - 1); this.navigateToPhoto(this.activePhotoId - 1);
return; return;
} }
} }
private navigateToPhoto(photoIndex: number) {
this.router.navigate([],
{queryParams: this.queryService.getParams(this.gridPhotoQL.toArray()[photoIndex].gridPhoto.photo)});
/*
this.activePhoto = null;
this.changeDetector.detectChanges();
this.updateActivePhoto(photoIndex, resize);*/
}
private showPhoto(photoIndex: number, resize: boolean = true) { private showPhoto(photoIndex: number, resize: boolean = true) {
this.activePhoto = null; this.activePhoto = null;
this.changeDetector.detectChanges(); this.changeDetector.detectChanges();
this.updateActivePhoto(photoIndex, resize); this.updateActivePhoto(photoIndex, resize);
} }
public show(photo: PhotoDTO) { public showLigthbox(photo: PhotoDTO) {
this.controllersVisible = true; this.controllersVisible = true;
this.showControls(); this.showControls();
this.visible = true; this.status = LightboxStates.Open;
const selectedPhoto = this.findPhotoComponent(photo); const selectedPhoto = this.findPhotoComponent(photo);
if (selectedPhoto === null) { if (selectedPhoto === null) {
throw new Error('Can\'t find Photo'); throw new Error('Can\'t find Photo');
} }
const lightboxDimension = selectedPhoto.getDimension(); const lightboxDimension = selectedPhoto.getDimension();
lightboxDimension.top -= this.getBodyScrollTop(); lightboxDimension.top -= PageHelper.ScrollY;
this.animating = true; this.animating = true;
this.animatePhoto(selectedPhoto.getDimension(), this.calcLightBoxPhotoDimension(selectedPhoto.gridPhoto.photo)).onDone(() => { this.animatePhoto(selectedPhoto.getDimension(), this.calcLightBoxPhotoDimension(selectedPhoto.gridPhoto.photo)).onDone(() => {
this.animating = false; this.animating = false;
@ -148,7 +225,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
//noinspection JSUnusedGlobalSymbols //noinspection JSUnusedGlobalSymbols
@HostListener('window:keydown', ['$event']) @HostListener('window:keydown', ['$event'])
onKeyPress(e: KeyboardEvent) { onKeyPress(e: KeyboardEvent) {
if (this.visible !== true) { if (this.status !== LightboxStates.Open) {
return; return;
} }
const event: KeyboardEvent = window.event ? <any>window.event : e; const event: KeyboardEvent = window.event ? <any>window.event : e;
@ -170,13 +247,19 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
} }
public hide() { public hide() {
this.router.navigate([],
{queryParams: this.queryService.getParams()});
}
private hideLigthbox() {
this.controllersVisible = false; this.controllersVisible = false;
this.status = LightboxStates.Closing;
this.fullScreenService.exitFullScreen(); this.fullScreenService.exitFullScreen();
this.pause(); this.pause();
this.animating = true; this.animating = true;
const lightboxDimension = this.activePhoto.getDimension(); const lightboxDimension = this.activePhoto.getDimension();
lightboxDimension.top -= this.getBodyScrollTop(); lightboxDimension.top -= PageHelper.ScrollY;
this.blackCanvasOpacity = 0; this.blackCanvasOpacity = 0;
this.animatePhoto(this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo), this.activePhoto.getDimension()); this.animatePhoto(this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo), this.activePhoto.getDimension());
@ -186,8 +269,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
width: this.getPhotoFrameWidth(), width: this.getPhotoFrameWidth(),
height: this.getPhotoFrameHeight() height: this.getPhotoFrameHeight()
}, lightboxDimension).onDone(() => { }, lightboxDimension).onDone(() => {
this.status = LightboxStates.Closed;
this.visible = false;
this.activePhoto = null; this.activePhoto = null;
this.activePhotoId = null; this.activePhotoId = null;
this.overlayService.hideOverlay(); this.overlayService.hideOverlay();
@ -227,18 +309,6 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
} }
setGridPhotoQL(value: QueryList<GalleryPhotoComponent>) {
if (this.changeSubscription != null) {
this.changeSubscription.unsubscribe();
}
this.gridPhotoQL = value;
this.changeSubscription = this.gridPhotoQL.changes.subscribe(() => {
if (this.activePhotoId != null && this.gridPhotoQL.length > this.activePhotoId) {
this.updateActivePhoto(this.activePhotoId);
}
});
}
public toggleInfoPanel() { public toggleInfoPanel() {
@ -287,7 +357,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
if (this.navigation.hasNext) { if (this.navigation.hasNext) {
this.nextImage(); this.nextImage();
} else { } else {
this.showPhoto(0); this.navigateToPhoto(0);
} }
}); });
this.playBackState = 1; this.playBackState = 1;
@ -326,21 +396,13 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
if (this.navigation.hasNext) { if (this.navigation.hasNext) {
this.nextImage(); this.nextImage();
} else { } else {
this.showPhoto(0); this.navigateToPhoto(0);
} }
}); });
this.playBackState = 2; this.playBackState = 2;
} }
private getBodyScrollTop(): number {
return window.scrollY;
}
private setBodyScrollTop(value: number) {
window.scrollTo(window.scrollX, value);
}
public getPhotoFrameWidth(): number { public getPhotoFrameWidth(): number {
return Math.max(window.innerWidth - this.infoPanelWidth, 0); return Math.max(window.innerWidth - this.infoPanelWidth, 0);
} }
@ -372,15 +434,15 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
const to = this.activePhoto.getDimension(); const to = this.activePhoto.getDimension();
// if target image out of screen -> scroll to there // if target image out of screen -> scroll to there
if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getPhotoFrameHeight() < to.top) { if (PageHelper.ScrollY > to.top || PageHelper.ScrollY + this.getPhotoFrameHeight() < to.top) {
this.setBodyScrollTop(to.top); PageHelper.ScrollY = to.top;
} }
} }
@HostListener('mousemove') @HostListener('mousemove')
onMousemove() { onMouseMove() {
this.showControls(); this.showControls();
} }
@ -432,5 +494,9 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
return <Dimension>{top: top, left: left, width: width, height: height}; return <Dimension>{top: top, left: left, width: width, height: height};
} }
public isVisible(): boolean {
return this.status !== LightboxStates.Closed;
}
} }

View File

@ -2,7 +2,7 @@
<ol id="directory-path" class="breadcrumb"> <ol id="directory-path" class="breadcrumb">
<li *ngFor="let path of routes" class="breadcrumb-item"> <li *ngFor="let path of routes" class="breadcrumb-item">
<a *ngIf="path.route" [routerLink]="['/gallery',path.route]" <a *ngIf="path.route" [routerLink]="['/gallery',path.route]"
[queryParams]="_shareService.isSharing() ? { sk: _shareService.getSharingKey() }:{}">{{path.name}}</a> [queryParams]="queryService.getParams()">{{path.name}}</a>
<ng-container *ngIf="!path.route">{{path.name}}</ng-container> <ng-container *ngIf="!path.route">{{path.name}}</ng-container>
</li> </li>
</ol> </ol>

View File

@ -5,6 +5,7 @@ import {UserDTO} from '../../../../common/entities/UserDTO';
import {AuthenticationService} from '../../model/network/authentication.service'; import {AuthenticationService} from '../../model/network/authentication.service';
import {ShareService} from '../share.service'; import {ShareService} from '../share.service';
import {I18n} from '@ngx-translate/i18n-polyfill'; import {I18n} from '@ngx-translate/i18n-polyfill';
import {QueryService} from '../../model/query.service';
@Component({ @Component({
selector: 'app-gallery-navbar', selector: 'app-gallery-navbar',
@ -17,7 +18,7 @@ export class GalleryNavigatorComponent implements OnChanges {
routes: Array<NavigatorPath> = []; routes: Array<NavigatorPath> = [];
constructor(private _authService: AuthenticationService, constructor(private _authService: AuthenticationService,
public _shareService: ShareService, public queryService: QueryService,
private i18n: I18n) { private i18n: I18n) {
} }

View File

@ -11,6 +11,14 @@ export class PageHelper {
return this.supportPageOffset ? window.pageYOffset : this.isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop; return this.supportPageOffset ? window.pageYOffset : this.isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
} }
public static get ScrollX(): number {
return this.supportPageOffset ? window.pageXOffset : this.isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
}
public static set ScrollY(value: number) {
window.scrollTo(this.ScrollX, value);
}
public static showScrollY() { public static showScrollY() {
PageHelper.body.style.overflowY = 'scroll'; PageHelper.body.style.overflowY = 'scroll';
} }

View File

@ -0,0 +1,24 @@
import {Injectable} from '@angular/core';
import {ShareService} from '../gallery/share.service';
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
@Injectable()
export class QueryService {
public static readonly PHOTO_PARAM = 'p';
constructor(private shareService: ShareService) {
}
getParams(photo?: PhotoDTO): { [key: string]: string } {
const query = {};
if (photo) {
query[QueryService.PHOTO_PARAM] = photo.name;
}
if (this.shareService.isSharing()) {
query['sk'] = this.shareService.getSharingKey();
}
return query;
}
}