diff --git a/backend/middlewares/GalleryMWs.ts b/backend/middlewares/GalleryMWs.ts index 2e9ab04c..30c0daaa 100644 --- a/backend/middlewares/GalleryMWs.ts +++ b/backend/middlewares/GalleryMWs.ts @@ -28,7 +28,8 @@ export class GalleryMWs { } req.resultPipe = new ContentWrapper(directory, null); - return next(); + + return; }); } diff --git a/frontend/app/app.component.ts b/frontend/app/app.component.ts index 9e87fcea..cf95014e 100644 --- a/frontend/app/app.component.ts +++ b/frontend/app/app.component.ts @@ -12,6 +12,7 @@ import {GalleryService} from "./gallery/gallery.service"; import {AdminComponent} from "./admin/admin.component"; import {NetworkService} from "./model/network/network.service"; import {ThumbnailLoaderService} from "./gallery/grid/thumnailLoader.service"; +import {GalleryCacheService} from "./gallery/cache.gallery.service"; @Component({ @@ -23,6 +24,7 @@ import {ThumbnailLoaderService} from "./gallery/grid/thumnailLoader.service"; ROUTER_PROVIDERS, NetworkService, UserService, + GalleryCacheService, GalleryService, AuthenticationService, ThumbnailLoaderService] diff --git a/frontend/app/gallery/cache.gallery.service.ts b/frontend/app/gallery/cache.gallery.service.ts new file mode 100644 index 00000000..a73f475e --- /dev/null +++ b/frontend/app/gallery/cache.gallery.service.ts @@ -0,0 +1,40 @@ +/// + +import {Injectable} from "@angular/core"; +import {Photo} from "../../../common/entities/Photo"; +import {Directory} from "../../../common/entities/Directory"; +import {Utils} from "../../../common/Utils"; + +@Injectable() +export class GalleryCacheService { + + + public getDirectory(directoryName:string):Directory { + let value = localStorage.getItem(directoryName); + if (value != null) { + let directory:Directory = JSON.parse(value); + + directory.photos.forEach((photo:Photo) => { + photo.directory = directory; + }); + + return directory; + } + return null; + } + + public setDirectory(directory:Directory):void { + + localStorage.setItem(Utils.concatUrls(directory.path, directory.name), JSON.stringify(directory)); + + directory.directories.forEach((dir:Directory) => { + let name = Utils.concatUrls(dir.path, dir.name); + if (localStorage.getItem(name) == null) { //don't override existing + localStorage.setItem(Utils.concatUrls(dir.path, dir.name), JSON.stringify(dir)); + } + }); + + } + + +} diff --git a/frontend/app/gallery/gallery.service.ts b/frontend/app/gallery/gallery.service.ts index 599460e1..4ac557ed 100644 --- a/frontend/app/gallery/gallery.service.ts +++ b/frontend/app/gallery/gallery.service.ts @@ -7,6 +7,7 @@ import {ContentWrapper} from "../../../common/entities/ConentWrapper"; import {Photo} from "../../../common/entities/Photo"; import {Directory} from "../../../common/entities/Directory"; import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; +import {GalleryCacheService} from "./cache.gallery.service"; @Injectable() export class GalleryService { @@ -15,16 +16,29 @@ export class GalleryService { private lastDirectory:Directory; private searchId:any; - constructor(private _networkService:NetworkService) { + constructor(private networkService:NetworkService, private galleryCacheService:GalleryCacheService) { this.content = new ContentWrapper(); } + lastRequest = { + directory: null + }; public getDirectory(directoryName:string):Promise> { this.content = new ContentWrapper(); - return this._networkService.getJson("/gallery/content/" + directoryName).then( + + this.content.directory = this.galleryCacheService.getDirectory(directoryName); + this.content.searchResult = null; + this.lastRequest.directory = directoryName; + return this.networkService.getJson("/gallery/content/" + directoryName).then( (message:Message) => { if (!message.error && message.result) { + this.galleryCacheService.setDirectory(message.result.directory); //save it before adding references + + if (this.lastRequest.directory != directoryName) { + return; + } + message.result.directory.photos.forEach((photo:Photo) => { photo.directory = message.result.directory; }); @@ -48,7 +62,7 @@ export class GalleryService { queryString += "?type=" + type; } - return this._networkService.getJson(queryString).then( + return this.networkService.getJson(queryString).then( (message:Message) => { if (!message.error && message.result) { this.content = message.result; @@ -75,7 +89,7 @@ export class GalleryService { this.searchId = null; }, 3000); //TODO: set timeout to config - return this._networkService.getJson("/instant-search/" + text).then( + return this.networkService.getJson("/instant-search/" + text).then( (message:Message) => { if (!message.error && message.result) { this.content = message.result; diff --git a/frontend/app/gallery/grid/GridPhoto.ts b/frontend/app/gallery/grid/GridPhoto.ts index 5dd25e30..3b692435 100644 --- a/frontend/app/gallery/grid/GridPhoto.ts +++ b/frontend/app/gallery/grid/GridPhoto.ts @@ -5,7 +5,7 @@ export class GridPhoto { private replacementSizeCache:boolean|number = false; - constructor(public photo:Photo, public renderWidth:number, public renderHeight:number) { + constructor(public photo:Photo, public renderWidth:number, public renderHeight:number, public rowId:number) { } @@ -59,4 +59,19 @@ export class GridPhoto { getPhotoPath() { return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name); } + + + equals(other:any) { + //is gridphoto + if (other.photo) { + return this.photo.directory.path === other.photo.directory.path && this.photo.directory.name === other.photo.directory.name && this.photo.name === other.photo.name + } + + //is photo + if (other.directory) { + return this.photo.directory.path === other.directory.path && this.photo.directory.name === other.directory.name && this.photo.name === other.name + } + + return false; + } } \ No newline at end of file diff --git a/frontend/app/gallery/grid/grid.gallery.component.ts b/frontend/app/gallery/grid/grid.gallery.component.ts index b3d3c7fb..6d639806 100644 --- a/frontend/app/gallery/grid/grid.gallery.component.ts +++ b/frontend/app/gallery/grid/grid.gallery.component.ts @@ -44,7 +44,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit { ngOnChanges() { if (this.isAfterViewInit == false) { return; - } + } this.onPhotosChanged(); } @@ -70,6 +70,8 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit { private onPhotosChanged() { + + //sort pohots by date this.photos.sort((a:Photo, b:Photo) => { if (a.metadata.creationDate > b.metadata.creationDate) { return 1; @@ -80,8 +82,30 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit { // a must be equal to b return 0; }); - this.photosToRender = []; - this.renderedPhotoIndex = 0; + + //merge new data with old one + let lastSameIndex = 0; + let lastRowId = null; + for (let i = 0; i < this.photos.length && i < this.photosToRender.length; i++) { + + //thIf a photo changed the whole row has to be removed + if (this.photosToRender[i].rowId != lastRowId) { + lastSameIndex = i; + lastRowId = this.photosToRender[i].rowId; + } + if (this.photosToRender[i].equals(this.photos[i]) == false) { + break; + } + } + + if (lastSameIndex > 0) { + this.photosToRender.splice(lastSameIndex, this.photosToRender.length - lastSameIndex); + this.renderedPhotoIndex = lastSameIndex; + } else { + this.photosToRender = []; + this.renderedPhotoIndex = 0; + } + setImmediate(() => { this.renderPhotos(); }); @@ -110,7 +134,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit { photoRowBuilder.getPhotoRow().forEach((photo) => { let imageWidth = imageHeight * (photo.metadata.size.width / photo.metadata.size.height); - this.photosToRender.push(new GridPhoto(photo, imageWidth, imageHeight)); + this.photosToRender.push(new GridPhoto(photo, imageWidth, imageHeight, this.renderedPhotoIndex)); }); renderedContentHeight += rowHeight;