diff --git a/src/frontend/app/ui/gallery/grid/grid.gallery.component.spec.ts b/src/frontend/app/ui/gallery/grid/grid.gallery.component.spec.ts index 0d92c2a3..0ae6b1ad 100644 --- a/src/frontend/app/ui/gallery/grid/grid.gallery.component.spec.ts +++ b/src/frontend/app/ui/gallery/grid/grid.gallery.component.spec.ts @@ -74,7 +74,7 @@ describe('GalleryGridComponent', () => { component.mediaGroups = [{name: 'equal 1', media: [phs[0], phs[1]]}]; component.mediaToRender = [{name: 'equal 1', media: [gPhs[0], gPhs[1]]}]; component.mergeNewPhotos(); - expect(component.mediaToRender).toEqual([{name: 'equal 1', media: [gPhs[0], gPhs[1]]}]); + expect(component.mediaToRender).toEqual([{name: 'equal 1', media: [gPhs[0],gPhs[1]]}]); /*-----------------------*/ component.mediaGroups = [{name: 'empty render', media: [phs[0], phs[1]]}]; component.mediaToRender = []; @@ -109,7 +109,7 @@ describe('GalleryGridComponent', () => { component.mediaGroups = [{name: 'removed 2nd 2', media: [phs[0], phs[1]]}, {name: '2', media: [phs[2], phs[5]]}]; component.mediaToRender = [{name: 'removed 2nd 2', media: [gPhs[0], gPhs[1]]}, {name: '2', media: [gPhs[2], gPhs[5], gPhs[3], gPhs[4]]}]; component.mergeNewPhotos(); - expect(component.mediaToRender).toEqual([{name: 'removed 2nd 2', media: [gPhs[0], gPhs[1]]}, {name: '2', media: [gPhs[2]]}]); + expect(component.mediaToRender).toEqual([{name: 'removed 2nd 2', media: [gPhs[0], gPhs[1]]}, {name: '2', media: [gPhs[2], gPhs[5]]}]); /*-----------------------*/ component.mediaGroups = [{name: 'removed from 1st', media: [phs[0]]},{name: '2', media: [phs[2],phs[3],phs[4]]}]; component.mediaToRender = [{name: 'removed from 1st', media: [gPhs[0], gPhs[1]]},{name: '2', media: [gPhs[2], gPhs[3], gPhs[4]]}]; @@ -129,12 +129,20 @@ describe('GalleryGridComponent', () => { component.mediaGroups = [{name: 'merged', media: [phs[0], phs[1],phs[2],phs[3]]}]; component.mediaToRender = [{name: 'merged dif name', media: [gPhs[0], gPhs[1]]},{name: '2', media: [gPhs[2], gPhs[3]]}]; component.mergeNewPhotos(); - expect(component.mediaToRender).toEqual([{name: 'merged', media: [gPhs[0], gPhs[1]]}]); + expect(component.mediaToRender).toEqual([{name: 'merged', media: [gPhs[0]]}]); /*-----------------------*/ component.mediaGroups = [{name: '3', media: [phs[0], phs[1],phs[2],phs[3]]}]; component.mediaToRender = [{name: '1', media: [gPhs[0], gPhs[1],gPhs[3], gPhs[2]]}]; component.mergeNewPhotos(); expect(component.mediaToRender).toEqual([{name: '3', media: [gPhs[0], gPhs[1]]}]); + /*-----------------------*/ + gPhs[1].rowId = 3; + gPhs[3].rowId = 3; + gPhs[2].rowId = 3; + component.mediaGroups = [{name: '3', media: [phs[0], phs[1],phs[2],phs[3]]}]; + component.mediaToRender = [{name: '1', media: [gPhs[0], gPhs[1],gPhs[3], gPhs[2]]}]; + component.mergeNewPhotos(); + expect(component.mediaToRender).toEqual([{name: '3', media: [gPhs[0]]}]); }); }); diff --git a/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts b/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts index 8c4399e5..cf2af03a 100644 --- a/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts +++ b/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts @@ -34,7 +34,7 @@ import {GroupByTypes} from '../../../../../common/entities/SortingMethods'; styleUrls: ['./grid.gallery.component.css'], }) export class GalleryGridComponent - implements OnInit, OnChanges, AfterViewInit, OnDestroy { + implements OnInit, OnChanges, AfterViewInit, OnDestroy { @ViewChild('gridContainer', {static: false}) gridContainer: ElementRef; @ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList; @@ -61,13 +61,13 @@ export class GalleryGridComponent public readonly GroupByTypes = GroupByTypes; constructor( - private overlayService: OverlayService, - private changeDetector: ChangeDetectorRef, - public queryService: QueryService, - private router: Router, - public galleryService: ContentService, - public sortingService: GallerySortingService, - private route: ActivatedRoute + private overlayService: OverlayService, + private changeDetector: ChangeDetectorRef, + public queryService: QueryService, + private router: Router, + public galleryService: ContentService, + public sortingService: GallerySortingService, + private route: ActivatedRoute ) { } @@ -87,19 +87,19 @@ export class GalleryGridComponent ngOnInit(): void { this.subscriptions.route = this.route.queryParams.subscribe( - (params: Params): void => { - if ( - params[QueryParams.gallery.photo] && - params[QueryParams.gallery.photo] !== '' - ) { - this.delayedRenderUpToPhoto = params[QueryParams.gallery.photo]; - if (!this.mediaGroups?.length) { - return; - } - - this.renderUpToMedia(params[QueryParams.gallery.photo]); + (params: Params): void => { + if ( + params[QueryParams.gallery.photo] && + params[QueryParams.gallery.photo] !== '' + ) { + this.delayedRenderUpToPhoto = params[QueryParams.gallery.photo]; + if (!this.mediaGroups?.length) { + return; } + + this.renderUpToMedia(params[QueryParams.gallery.photo]); } + } ); } @@ -150,7 +150,7 @@ export class GalleryGridComponent if (Config.Gallery.enableOnScrollThumbnailPrioritising === true) { this.gridPhotoQL.changes.subscribe((): void => { this.scrollListenerPhotos = this.gridPhotoQL.filter( - (pc): boolean => pc.ScrollListener + (pc): boolean => pc.ScrollListener ); }); } @@ -176,104 +176,89 @@ export class GalleryGridComponent this.clearRenderedPhotos(); return; } - // const minGI = Math.min(this.mediaGroups.length, this.mediaToRender.length) - 1; - // const minMI = Math.min(this.mediaGroups[minGI].media.length, this.mediaToRender[minGI].media.length) - 1; // merge new data with old one const firstDeleteIndex = { groups: 0, media: 0 }; + const lastOkIndex = { + groups: 0, + media: 0 + }; let diffFound = false; + let i = 0; + let j = 0; - for (let i = 0; i < this.mediaGroups.length && i < this.mediaToRender.length; ++i) { - if (diffFound) { + for (; i < this.mediaGroups.length && i < this.mediaToRender.length; ++i) { + + if (diffFound) { break; } this.mediaToRender[i].name = this.mediaGroups[i].name; // update name if only this changed let lastRowId = null; - for (let j = 0; j < this.mediaGroups[i].media.length && j < this.mediaToRender[i].media.length; ++j) { + j = 0; + for (; j < this.mediaGroups[i].media.length && j < this.mediaToRender[i].media.length; ++j) { const media = this.mediaGroups[i].media[j]; const gridMedia = this.mediaToRender[i].media[j]; + // If a media changed the whole row has to be removed if (gridMedia.rowId !== lastRowId) { firstDeleteIndex.groups = i; firstDeleteIndex.media = j; lastRowId = gridMedia.rowId; } + + // we go no further. Found the first bad media if (gridMedia.equals(media) === false) { diffFound = true; break; } + // save the last media that was checked and was ok + lastOkIndex.groups = i; + lastOkIndex.media = j; } - - // delete last row if the length of the two are not equal - - if (!diffFound && this.mediaGroups[i].media.length > this.mediaToRender[i].media.length) { - firstDeleteIndex.groups = i; - firstDeleteIndex.media = this.mediaToRender[i].media.length; - diffFound = true; - } - - if (!diffFound && this.mediaGroups[i].media.length < this.mediaToRender[i].media.length) { - const endIndex = Math.min(this.mediaToRender[i].media.length, this.mediaGroups[i].media.length) - 1; - lastRowId = this.mediaToRender[i].media[endIndex].rowId; - - // make sure we delete if there is no 2 rows - diffFound = true; - firstDeleteIndex.groups = i; - firstDeleteIndex.media = endIndex + 1; - - // finding the last but one row - for (let j = endIndex; j >= 0; --j) { - const gridMedia = this.mediaToRender[i].media[j]; - if (gridMedia.rowId !== lastRowId) { - firstDeleteIndex.groups = i; - firstDeleteIndex.media = j + 1; - break; - } - } + if (this.mediaGroups[i].media.length != this.mediaToRender[i].media.length) { + break; } } - if (!diffFound && this.mediaGroups.length < this.mediaToRender.length) { - diffFound = true; - firstDeleteIndex.groups = this.mediaGroups.length - 1; - firstDeleteIndex.media = 0; + + // if all check passed, nothing to delete from the last group + if (!diffFound && + lastOkIndex.media == this.mediaGroups[lastOkIndex.groups].media.length - 1) { + firstDeleteIndex.groups = lastOkIndex.groups; + firstDeleteIndex.media = lastOkIndex.media + 1; } - // if all the same - if (diffFound) { - if (firstDeleteIndex.media < 0 && firstDeleteIndex.groups < 0) { - this.clearRenderedPhotos(); - return; - } - // only delete the whole group if all media is different - if (firstDeleteIndex.media === 0) { - this.mediaToRender.splice(firstDeleteIndex.groups); - return; - } - this.mediaToRender.splice(firstDeleteIndex.groups + 1); - - const media = this.mediaToRender[firstDeleteIndex.groups].media; - media.splice(firstDeleteIndex.media); - + if (firstDeleteIndex.media < 0 && firstDeleteIndex.groups < 0) { + this.clearRenderedPhotos(); + return; } + // only delete the whole group if all media is different + if (firstDeleteIndex.media === 0) { + this.mediaToRender.splice(firstDeleteIndex.groups); + return; + } + this.mediaToRender.splice(firstDeleteIndex.groups + 1); + const media = this.mediaToRender[firstDeleteIndex.groups].media; + media.splice(firstDeleteIndex.media); + } public renderARow(): number { if ( - !this.isMoreToRender() || - this.containerWidth === 0 + !this.isMoreToRender() || + this.containerWidth === 0 ) { return null; } // step group if (this.mediaToRender.length == 0 || - this.mediaToRender[this.mediaToRender.length - 1].media.length >= - this.mediaGroups[this.mediaToRender.length - 1].media.length) { + this.mediaToRender[this.mediaToRender.length - 1].media.length >= + this.mediaGroups[this.mediaToRender.length - 1].media.length) { this.mediaToRender.push({name: this.mediaGroups[this.mediaToRender.length].name, media: []}); } @@ -281,10 +266,10 @@ export class GalleryGridComponent const minRowHeight = this.screenHeight / this.MAX_ROW_COUNT; const photoRowBuilder = new GridRowBuilder( - this.mediaGroups[this.mediaToRender.length - 1].media, - this.mediaToRender[this.mediaToRender.length - 1].media.length, - this.IMAGE_MARGIN, - this.containerWidth - this.overlayService.getPhantomScrollbarWidth() + this.mediaGroups[this.mediaToRender.length - 1].media, + this.mediaToRender[this.mediaToRender.length - 1].media.length, + this.IMAGE_MARGIN, + this.containerWidth - this.overlayService.getPhantomScrollbarWidth() ); photoRowBuilder.addPhotos(this.TARGET_COL_COUNT); @@ -297,13 +282,13 @@ export class GalleryGridComponent const noFullRow = photoRowBuilder.calcRowHeight() > maxRowHeight; // if the row is not full, make it average sized const rowHeight = noFullRow ? (minRowHeight + maxRowHeight) / 2 : - Math.min(photoRowBuilder.calcRowHeight(), maxRowHeight); + Math.min(photoRowBuilder.calcRowHeight(), maxRowHeight); const imageHeight = rowHeight - this.IMAGE_MARGIN * 2; photoRowBuilder.getPhotoRow().forEach((media): void => { const imageWidth = imageHeight * MediaDTOUtils.calcAspectRatio(media); this.mediaToRender[this.mediaToRender.length - 1].media.push( - new GridMedia(media, imageWidth, imageHeight, this.mediaToRender[this.mediaToRender.length - 1].media.length) + new GridMedia(media, imageWidth, imageHeight, this.mediaToRender[this.mediaToRender.length - 1].media.length) ); }); @@ -314,23 +299,23 @@ export class GalleryGridComponent @HostListener('window:scroll') onScroll(): void { if ( - !this.onScrollFired && - this.mediaGroups && - // should we trigger this at all? - (this.isMoreToRender() || - this.scrollListenerPhotos.length > 0) + !this.onScrollFired && + this.mediaGroups && + // should we trigger this at all? + (this.isMoreToRender() || + this.scrollListenerPhotos.length > 0) ) { window.requestAnimationFrame((): void => { this.renderPhotos(); if (Config.Gallery.enableOnScrollThumbnailPrioritising === true) { this.scrollListenerPhotos.forEach( - (pc: GalleryPhotoComponent): void => { - pc.onScroll(); - } + (pc: GalleryPhotoComponent): void => { + pc.onScroll(); + } ); this.scrollListenerPhotos = this.scrollListenerPhotos.filter( - (pc): boolean => pc.ScrollListener + (pc): boolean => pc.ScrollListener ); } @@ -352,7 +337,7 @@ export class GalleryGridComponent let mediaIndex = -1; for (let i = 0; i < this.mediaGroups.length; ++i) { mediaIndex = this.mediaGroups[i].media.findIndex( - (p): boolean => this.queryService.getMediaStringId(p) === mediaStringId + (p): boolean => this.queryService.getMediaStringId(p) === mediaStringId ); if (mediaIndex !== -1) { groupIndex = i; @@ -368,11 +353,11 @@ export class GalleryGridComponent // so not required to render more, but the scrollbar does not trigger more photos to render // (on lightbox navigation) while ( - (this.mediaToRender.length - 1 < groupIndex && - this.mediaToRender[this.mediaToRender.length - 1].media.length < mediaIndex) && - this.renderARow() !== null - // eslint-disable-next-line no-empty - ) { + (this.mediaToRender.length - 1 < groupIndex && + this.mediaToRender[this.mediaToRender.length - 1].media.length < mediaIndex) && + this.renderARow() !== null + // eslint-disable-next-line no-empty + ) { } } @@ -390,13 +375,13 @@ export class GalleryGridComponent private shouldRenderMore(offset = 0): boolean { const bottomOffset = this.getMaxRowHeight() * 2; return ( - Config.Gallery.enableOnScrollRendering === false || - PageHelper.ScrollY >= - document.body.clientHeight + - offset - - window.innerHeight - - bottomOffset || - (document.body.clientHeight + offset) * 0.85 < window.innerHeight + Config.Gallery.enableOnScrollRendering === false || + PageHelper.ScrollY >= + document.body.clientHeight + + offset - + window.innerHeight - + bottomOffset || + (document.body.clientHeight + offset) * 0.85 < window.innerHeight ); } @@ -405,9 +390,9 @@ export class GalleryGridComponent return; } if ( - this.containerWidth === 0 || - !this.isMoreToRender() || - !this.shouldRenderMore() + this.containerWidth === 0 || + !this.isMoreToRender() || + !this.shouldRenderMore() ) { return; } @@ -415,10 +400,10 @@ export class GalleryGridComponent let renderedContentHeight = 0; while ( - this.isMoreToRender() && - (this.shouldRenderMore(renderedContentHeight) === true || - this.getNumberOfRenderedMedia() < numberOfPhotos) - ) { + this.isMoreToRender() && + (this.shouldRenderMore(renderedContentHeight) === true || + this.getNumberOfRenderedMedia() < numberOfPhotos) + ) { const ret = this.renderARow(); if (ret === null) { throw new Error('Grid media rendering failed'); @@ -429,7 +414,7 @@ export class GalleryGridComponent private isMoreToRender() { return this.mediaToRender.length < this.mediaGroups.length || - (this.mediaToRender[this.mediaToRender.length - 1]?.media.length || 0) < this.mediaGroups[this.mediaToRender.length - 1]?.media.length; + (this.mediaToRender[this.mediaToRender.length - 1]?.media.length || 0) < this.mediaGroups[this.mediaToRender.length - 1]?.media.length; } getNumberOfRenderedMedia() { @@ -445,9 +430,9 @@ export class GalleryGridComponent PageHelper.showScrollY(); // if the width changed a bit or the height changed a lot if ( - this.containerWidth !== this.gridContainer.nativeElement.parentElement.clientWidth || - this.screenHeight < window.innerHeight * 0.75 || - this.screenHeight > window.innerHeight * 1.25 + this.containerWidth !== this.gridContainer.nativeElement.parentElement.clientWidth || + this.screenHeight < window.innerHeight * 0.75 || + this.screenHeight > window.innerHeight * 1.25 ) { this.screenHeight = window.innerHeight; this.containerWidth = this.gridContainer.nativeElement.parentElement.clientWidth;