diff --git a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts index e045c04..3c4f421 100644 --- a/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts +++ b/mediarepo-ui/src/app/components/core/repositories-tab/repositories-tab.component.ts @@ -130,7 +130,7 @@ export class RepositoriesTabComponent implements OnInit, AfterViewInit { "Opening repository..."); let dialog = this.dialog.open(BusyDialogComponent, { data: { - title: `Opening repository ${repository.name}`, + title: `Opening repository '${repository.name}'`, message: dialogMessage, allowCancel: true, }, disableClose: true, diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery.component.html b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery.component.html index df8426b..2e48be3 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery.component.html +++ b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery.component.html @@ -1,4 +1,8 @@ - (); @Output() fileDeleted = new EventEmitter(); - @ViewChild("virtualScroll") virtualScroll!: CdkVirtualScrollViewport; - @ViewChild("inner") inner!: ElementRef; + @ViewChild("previewStripContainer") stripContainer!: ElementRef; public entries: Selectable[] = []; public selectedFile: Selectable | undefined; @@ -45,15 +47,16 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { public imageViewHeightPercent = 80; public previewStripVisible = true; + public previewedEntries: (Selectable | undefined)[] = []; - private scrollTimeout: number | undefined; + private previewStripCount = 5; private escapeCount = 0; constructor( + private changeDetector: ChangeDetectorRef, private tabService: TabService, private fileService: FileService ) { - tabService.selectedTab.subscribe(() => this.adjustElementSizes()); } async ngOnInit(): Promise { @@ -61,6 +64,8 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { this.selectedFile.data) < 0) { await this.onEntrySelect( this.getPreselectedEntry() ?? this.entries[0]); + } else { + this.buildPreviewedFiles(); } } @@ -84,6 +89,10 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { } } + public ngAfterViewChecked(): void { + this.calculatePreviewCount(); + } + /** * Called when a new entry is selected * @param {Selectable} entry @@ -96,15 +105,8 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { this.selectedFile = entry; await this.loadSelectedFile(); - if (this.virtualScroll) { - clearTimeout(this.scrollTimeout); - this.scrollTimeout = setTimeout( - () => this.scrollToSelection(), - 0 - ); // we need to make sure the viewport has rendered - } - this.fileSelect.emit(this.selectedFile.data); + this.buildPreviewedFiles(); } } @@ -151,13 +153,6 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { } } - public adjustElementSizes(): void { - if (this.virtualScroll) { - this.virtualScroll.checkViewportSize(); - this.scrollToSelection(); - } - } - public focus() { this.inner.nativeElement.focus(); } @@ -181,8 +176,8 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { } } - public trackByFileId(index: number, item: Selectable) { - return item.data.id; + public trackByFileId(index: number, item?: Selectable) { + return item?.data.id; } public onFileStatusChange(): void { @@ -199,23 +194,24 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { } } - private scrollToSelection(): void { - if (this.selectedFile) { - const selectedIndex = this.entries.indexOf(this.selectedFile); - const viewportSize = this.virtualScroll.getViewportSize(); - const indexAdjustment = (viewportSize / 260) / 2; // adjustment to have the selected item centered - this.virtualScroll.scrollToIndex( - Math.max(selectedIndex - indexAdjustment, 0), "smooth"); - - if (selectedIndex > indexAdjustment) { - this.virtualScroll.scrollToOffset( - this.virtualScroll.measureScrollOffset("left") + 130, - "smooth" - ); + public calculatePreviewCount() { + if (this.stripContainer && this.stripContainer.nativeElement) { + const width = Math.abs(this.stripContainer.nativeElement.clientWidth); + const height = Math.abs(this.stripContainer.nativeElement.clientHeight); + + const count = Math.floor(Math.floor(width / height) / 2) * 2 + 1; + + if (count != this.previewStripCount) { + this.previewStripCount = count; + this.buildPreviewedFiles(); } } } + public onResize(): void { + this.changeDetector.markForCheck(); + } + private getPreselectedEntry(): Selectable | undefined { if (this.preselectedFile) { const entry = this.entries.find( @@ -235,4 +231,26 @@ export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit { setTimeout(() => this.escapeCount--, 500); } } + + private buildPreviewedFiles() { + if (!this.selectedFile) { + if (this.entries) { + this.onEntrySelect(this.entries[0]).catch(console.error); + } + return; + } + const selectedIndex = this.entries.indexOf(this.selectedFile!); + const previewCountLR = Math.floor(this.previewStripCount / 2); + const previewedEntries = []; + + for (let i = selectedIndex - previewCountLR; i <= selectedIndex + previewCountLR; i++) { + if (i >= 0 && i < this.entries.length) { + previewedEntries.push(this.entries[i]); + } else { + previewedEntries.push(undefined); + } + } + this.previewedEntries = previewedEntries; + this.changeDetector.markForCheck(); + } } diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.html b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.html index f2e0528..bf3f256 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.html +++ b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.html @@ -1,7 +1,7 @@