diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component-theme.scss b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component-theme.scss similarity index 88% rename from mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component-theme.scss rename to mediarepo-ui/src/app/components/shared/file/file-card/file-card.component-theme.scss index 1ac9cbb..83f1083 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component-theme.scss +++ b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component-theme.scss @@ -1,5 +1,5 @@ @use 'sass:map'; -@use '../../../../../../../../node_modules/@angular/material/index' as mat; +@use '../../../../../../node_modules/@angular/material/index' as mat; @mixin color($theme) { $color-config: mat.get-color-config($theme); diff --git a/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.html b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.html new file mode 100644 index 0000000..ca38d72 --- /dev/null +++ b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.html @@ -0,0 +1,8 @@ + + + + + + + diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.scss b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.scss similarity index 79% rename from mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.scss rename to mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.scss index e4e9a67..8ae08df 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.scss +++ b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.scss @@ -10,6 +10,11 @@ mat-card-content { width: 100%; } +app-busy-indicator { + height: 100%; + width: 100%; +} + .entry-image { width: 100%; height: 100%; diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.spec.ts b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.spec.ts similarity index 60% rename from mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.spec.ts rename to mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.spec.ts index 47abb34..0336092 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.spec.ts +++ b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.spec.ts @@ -1,20 +1,20 @@ import {ComponentFixture, TestBed} from "@angular/core/testing"; -import {FileGridEntryComponent} from "./file-grid-entry.component"; +import {FileCardComponent} from "./file-card.component"; describe("FileGridEntryComponent", () => { - let component: FileGridEntryComponent; - let fixture: ComponentFixture; + let component: FileCardComponent; + let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [FileGridEntryComponent] + declarations: [FileCardComponent] }) .compileComponents(); }); beforeEach(() => { - fixture = TestBed.createComponent(FileGridEntryComponent); + fixture = TestBed.createComponent(FileCardComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.ts b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.ts new file mode 100644 index 0000000..57a434e --- /dev/null +++ b/mediarepo-ui/src/app/components/shared/file/file-card/file-card.component.ts @@ -0,0 +1,53 @@ +import { + Component, + ElementRef, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, + ViewChild +} from "@angular/core"; +import {File} from "../../../../models/File"; +import {SafeResourceUrl} from "@angular/platform-browser"; +import {Selectable} from "../../../../models/Selectable"; + +@Component({ + selector: "app-file-card", + templateUrl: "./file-card.component.html", + styleUrls: ["./file-card.component.scss"] +}) +export class FileCardComponent implements OnInit, OnChanges { + + @ViewChild("card") card!: ElementRef; + @Input() public entry!: Selectable; + @Output() clickEvent = new EventEmitter(); + @Output() dblClickEvent = new EventEmitter(); + + private cachedId: number | undefined; + private urlSetTimeout: number | undefined; + public loading = false; + + constructor() { + } + + async ngOnInit() { + this.cachedId = this.entry.data.id; + this.setImageDelayed(); + } + + async ngOnChanges(changes: SimpleChanges) { + if (changes["file"] && (this.cachedId === undefined || this.entry.data.id !== this.cachedId)) { + this.cachedId = this.entry.data.id; + this.setImageDelayed(); + } + } + + private setImageDelayed() { + this.loading = true; + clearTimeout(this.urlSetTimeout); + this.urlSetTimeout = setTimeout( + () => this.loading = false, 200); + } +} diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component-theme.scss b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component-theme.scss deleted file mode 100644 index a3e05a9..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component-theme.scss +++ /dev/null @@ -1,27 +0,0 @@ -@use 'sass:map'; -@use '../../../../../../../../node_modules/@angular/material/index' as mat; - -@mixin color($theme) { - $color-config: mat.get-color-config($theme); - $primary-palette: map.get($color-config, 'primary'); - - div.image-wrapper.selected { - background-color: mat.get-color-from-palette($primary-palette, 'darker'); - } -} - -@mixin typography($theme) { -} - -@mixin theme($theme) { - $color-config: mat.get-color-config($theme); - @if $color-config != null { - @include color($theme); - } - - $typography-config: mat.get-typography-config($theme); - @if $typography-config != null { - @include typography($theme); - } -} - diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.html b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.html deleted file mode 100644 index 6fd5788..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.scss b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.scss deleted file mode 100644 index dad5555..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.scss +++ /dev/null @@ -1,18 +0,0 @@ -app-file-thumbnail { - height: 100%; - width: 100%; - position: relative; - display: block; -} - -.image-wrapper { - width: calc(100% - 20px); - height: calc(100% - 20px); - align-items: center; - text-align: center; - background-color: darken(dimgrey, 15); - padding: 10px; - border-radius: 5px; - cursor: pointer; - user-select: none; -} diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.spec.ts b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.spec.ts deleted file mode 100644 index e81e2aa..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {ComponentFixture, TestBed} from "@angular/core/testing"; - -import {FileGalleryEntryComponent} from "./file-gallery-entry.component"; - -describe("FileGalleryEntryComponent", () => { - let component: FileGalleryEntryComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [FileGalleryEntryComponent] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(FileGalleryEntryComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it("should create", () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.ts b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.ts deleted file mode 100644 index 91df5f9..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - Component, - EventEmitter, - Inject, - Input, - OnChanges, - OnInit, - Output, - SimpleChanges -} from "@angular/core"; -import {File} from "../../../../../../models/File"; -import {FileService} from "../../../../../../services/file/file.service"; -import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser"; -import {ErrorBrokerService} from "../../../../../../services/error-broker/error-broker.service"; -import {Selectable} from "../../../../../../models/Selectable"; - -@Component({ - selector: "app-file-gallery-entry", - templateUrl: "./file-gallery-entry.component.html", - styleUrls: ["./file-gallery-entry.component.scss"] -}) -export class FileGalleryEntryComponent implements OnInit, OnChanges { - - @Input() file!: Selectable; - @Output() fileSelectEvent = new EventEmitter>(); - contentUrl: SafeResourceUrl | undefined; - - private cachedFile: File | undefined; - private urlSetTimeout: number | undefined; - - constructor(@Inject( - DomSanitizer) private sanitizer: DomSanitizer, private fileService: FileService, private errorBroker: ErrorBrokerService) { - } - - ngOnChanges(changes: SimpleChanges) { - if (changes["file"] && (!this.cachedFile || this.file.data.hash !== this.cachedFile!.hash)) { // handle changes to the file when the component is not destroyed - this.cachedFile = this.file.data; - this.setImageDelayed(); - } - } - - ngOnInit() { - this.cachedFile = this.file.data; - this.setImageDelayed(); - } - - private setImageDelayed() { - this.contentUrl = undefined; - clearTimeout(this.urlSetTimeout); - this.urlSetTimeout = setTimeout( - () => this.contentUrl = this.fileService.buildThumbnailUrl( - this.file.data, - 250, 250), 200); - } -} 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 c2f4a14..9a67404 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 @@ -14,8 +14,8 @@
- +
diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/GridEntry.ts b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/GridEntry.ts deleted file mode 100644 index ce7965f..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/GridEntry.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {File} from "../../../../../../models/File"; - -export type GridEntry = { - file: File, - selected: boolean, -} diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.html b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.html deleted file mode 100644 index 89a2aa4..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.ts b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.ts deleted file mode 100644 index 82e322d..0000000 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - Component, - ElementRef, - EventEmitter, - Input, - OnChanges, - OnInit, - Output, - SimpleChanges, - ViewChild -} from "@angular/core"; -import {File} from "../../../../../../models/File"; -import {FileService} from "../../../../../../services/file/file.service"; -import {SafeResourceUrl} from "@angular/platform-browser"; -import {GridEntry} from "./GridEntry"; - -@Component({ - selector: "app-file-grid-entry", - templateUrl: "./file-grid-entry.component.html", - styleUrls: ["./file-grid-entry.component.scss"] -}) -export class FileGridEntryComponent implements OnInit, OnChanges { - - @ViewChild("card") card!: ElementRef; - @Input() public gridEntry!: GridEntry; - @Output() clickEvent = new EventEmitter(); - @Output() dblClickEvent = new EventEmitter(); - - contentUrl: SafeResourceUrl | undefined; - private cachedFile: File | undefined; - private urlSetTimeout: number | undefined; - - constructor(private fileService: FileService) { - } - - async ngOnInit() { - this.cachedFile = this.gridEntry.file; - this.setImageDelayed(); - } - - async ngOnChanges(changes: SimpleChanges) { - if (changes["file"] && (!this.cachedFile || this.gridEntry.file.hash !== this.cachedFile.hash)) { - this.cachedFile = this.gridEntry.file; - this.setImageDelayed(); - } - } - - private setImageDelayed() { - this.contentUrl = undefined; - clearTimeout(this.urlSetTimeout); - this.urlSetTimeout = setTimeout( - () => this.contentUrl = this.fileService.buildThumbnailUrl( - this.gridEntry.file, - 250, 250), 200); - } -} 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 81fe5d1..1b0f561 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 @@ -3,12 +3,12 @@ minBufferPx="500">
- + [entry]="gridEntry">
diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.scss b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.scss index abc4365..9859417 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.scss +++ b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.scss @@ -1,4 +1,4 @@ -app-file-grid-entry { +app-file-card { height: 250px; width: 100%; padding: 5px; diff --git a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.ts b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.ts index fba4a8e..c7a9dd1 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.ts +++ b/mediarepo-ui/src/app/components/shared/file/file-multiview/file-grid/file-grid.component.ts @@ -11,11 +11,11 @@ import { ViewChild } from "@angular/core"; import {File} from "../../../../../models/File"; -import {FileGridEntryComponent} from "./file-grid-entry/file-grid-entry.component"; -import {GridEntry} from "./file-grid-entry/GridEntry"; +import {FileCardComponent} from "../../file-card/file-card.component"; import {CdkVirtualScrollViewport} from "@angular/cdk/scrolling"; import {TabService} from "../../../../../services/tab/tab.service"; import {FileService} from "../../../../../services/file/file.service"; +import {Selectable} from "../../../../../models/Selectable"; @Component({ selector: "app-file-grid", @@ -33,11 +33,11 @@ export class FileGridComponent implements OnChanges, OnInit { @ViewChild("virtualScrollGrid") virtualScroll!: CdkVirtualScrollViewport; @ViewChild("galleryWrapper") galleryWrapper!: ElementRef; - selectedEntries: GridEntry[] = []; - partitionedGridEntries: GridEntry[][] = []; + selectedEntries: Selectable[] = []; + partitionedGridEntries: Selectable[][] = []; private shiftClicked = false; private ctrlClicked = false; - private gridEntries: GridEntry[] = [] + private gridEntries: Selectable[] = [] constructor( private tabService: TabService, @@ -47,17 +47,15 @@ export class FileGridComponent implements OnChanges, OnInit { } public ngOnInit(): void { - this.gridEntries = this.files.map(file => { - return {file, selected: false} - }); + this.gridEntries = this.files.map( + file => new Selectable(file, false)); this.setPartitionedGridEntries(); } ngOnChanges(changes: SimpleChanges): void { if (changes["files"]) { - this.gridEntries = this.files.map(file => { - return {file, selected: false} - }); + this.gridEntries = this.files.map( + file => new Selectable(file, false)); this.refreshFileSelections(); this.setPartitionedGridEntries(); } @@ -65,9 +63,9 @@ export class FileGridComponent implements OnChanges, OnInit { /** * File selector logic - * @param {FileGridEntryComponent} clickedEntry + * @param {FileCardComponent} clickedEntry */ - setSelectedFile(clickedEntry: GridEntry) { + setSelectedFile(clickedEntry: Selectable) { if (!(this.shiftClicked || this.ctrlClicked) && this.selectedEntries.length > 0) { this.selectedEntries.forEach(entry => { if (entry !== clickedEntry) entry.selected = false @@ -87,7 +85,7 @@ export class FileGridComponent implements OnChanges, OnInit { this.selectedEntries.push(clickedEntry); } } - this.fileSelectEvent.emit(this.selectedEntries.map(g => g.file)); + this.fileSelectEvent.emit(this.selectedEntries.map(g => g.data)); } public adjustElementSizes(): void { @@ -103,7 +101,7 @@ export class FileGridComponent implements OnChanges, OnInit { private setPartitionedGridEntries() { this.partitionedGridEntries = []; let scrollToIndex = -1; - let selectedEntry: GridEntry | undefined = undefined; + let selectedEntry: Selectable | undefined = undefined; for (let i = 0; i < (Math.ceil( this.gridEntries.length / this.columns)); i++) { @@ -111,7 +109,7 @@ export class FileGridComponent implements OnChanges, OnInit { Math.min(this.gridEntries.length, (i + 1) * this.columns)); this.partitionedGridEntries.push(entries); const preselectedEntry = entries.find( - e => e.file.hash == this.preselectedFile?.hash); + e => e.data.hash == this.preselectedFile?.hash); if (preselectedEntry) { scrollToIndex = i; @@ -132,14 +130,14 @@ export class FileGridComponent implements OnChanges, OnInit { } private refreshFileSelections() { - const newSelection: GridEntry[] = this.gridEntries.filter( + const newSelection: Selectable[] = this.gridEntries.filter( entry => this.selectedEntries.findIndex( - e => e.file.id == entry.file.id) >= 0); + e => e.data.id == entry.data.id) >= 0); newSelection.forEach(entry => entry.selected = true); this.selectedEntries = newSelection; } - private handleShiftSelect(clickedEntry: GridEntry): void { + private handleShiftSelect(clickedEntry: Selectable): void { const lastEntry = this.selectedEntries[this.selectedEntries.length - 1]; let found = false; if (clickedEntry == lastEntry) { diff --git a/mediarepo-ui/src/app/components/shared/file/file-thumbnail/file-thumbnail.component.ts b/mediarepo-ui/src/app/components/shared/file/file-thumbnail/file-thumbnail.component.ts index 9eb62bb..20e96d3 100644 --- a/mediarepo-ui/src/app/components/shared/file/file-thumbnail/file-thumbnail.component.ts +++ b/mediarepo-ui/src/app/components/shared/file/file-thumbnail/file-thumbnail.component.ts @@ -1,8 +1,8 @@ import { - Component, + Component, EventEmitter, Input, OnChanges, - OnInit, + OnInit, Output, SimpleChanges } from "@angular/core"; import {File} from "../../../../models/File"; diff --git a/mediarepo-ui/src/app/components/shared/file/file.module.ts b/mediarepo-ui/src/app/components/shared/file/file.module.ts index 4ff4118..da4609f 100644 --- a/mediarepo-ui/src/app/components/shared/file/file.module.ts +++ b/mediarepo-ui/src/app/components/shared/file/file.module.ts @@ -3,8 +3,7 @@ import { CommonModule } from "@angular/common"; import {FileMultiviewComponent} from "./file-multiview/file-multiview.component"; import {FileGridComponent} from "./file-multiview/file-grid/file-grid.component"; import {FileGalleryComponent} from "./file-multiview/file-gallery/file-gallery.component"; -import {FileGalleryEntryComponent} from "./file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component"; -import {FileGridEntryComponent} from "./file-multiview/file-grid/file-grid-entry/file-grid-entry.component"; +import {FileCardComponent} from "./file-card/file-card.component"; import {FileContextMenuComponent} from "./file-context-menu/file-context-menu.component"; import {FileThumbnailComponent} from "./file-thumbnail/file-thumbnail.component"; import {ContentViewerComponent} from "./content-viewer/content-viewer.component"; @@ -30,10 +29,9 @@ import {MatCardModule} from "@angular/material/card"; FileMultiviewComponent, FileGridComponent, FileGalleryComponent, - FileGalleryEntryComponent, - FileGridEntryComponent, + FileCardComponent, FileContextMenuComponent, - FileThumbnailComponent, + FileThumbnailComponent, ContentViewerComponent, AudioViewerComponent, ImageViewerComponent, diff --git a/mediarepo-ui/src/styles.scss b/mediarepo-ui/src/styles.scss index 44e654a..008bc14 100644 --- a/mediarepo-ui/src/styles.scss +++ b/mediarepo-ui/src/styles.scss @@ -1,9 +1,8 @@ @use 'sass:map'; @use "~@angular/material" as mat; @use 'src/app/app.component-theme' as app; -@use 'app/components/shared/file/file-multiview/file-grid/file-grid-entry/file-grid-entry.component-theme' as file-grid-entry; +@use 'app/components/shared/file/file-card/file-card.component-theme' as file-card; @use 'app/components/shared/sidebar/file-search/file-search.component-theme' as file-search; -@use "app/components/shared/file/file-multiview/file-gallery/file-gallery-entry/file-gallery-entry.component-theme" as gallery-entry; @include mat.core(); @@ -21,6 +20,5 @@ $theme: mat.define-dark-theme(( @include mat.all-component-themes($theme); @include app.theme($theme); -@include file-grid-entry.theme($theme); +@include file-card.theme($theme); @include file-search.theme($theme); -@include gallery-entry.theme($theme);