Refactor file grid and gallery to use the same type of thumbnail container
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
8728fcdc71
commit
62cba1ce56
@ -1,5 +1,5 @@
|
|||||||
@use 'sass:map';
|
@use 'sass:map';
|
||||||
@use '../../../../../../../../node_modules/@angular/material/index' as mat;
|
@use '../../../../../../node_modules/@angular/material/index' as mat;
|
||||||
|
|
||||||
@mixin color($theme) {
|
@mixin color($theme) {
|
||||||
$color-config: mat.get-color-config($theme);
|
$color-config: mat.get-color-config($theme);
|
@ -0,0 +1,8 @@
|
|||||||
|
<mat-card #card (click)="clickEvent.emit(this)" (dblclick)="dblClickEvent.emit(this)"
|
||||||
|
[ngClass]="{'selected': entry.selected}">
|
||||||
|
<mat-card-content>
|
||||||
|
<app-busy-indicator [busy]="this.loading">
|
||||||
|
<app-file-thumbnail *ngIf="!loading" [file]="this.entry.data" class=".entry-image"></app-file-thumbnail>
|
||||||
|
</app-busy-indicator>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
@ -1,20 +1,20 @@
|
|||||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||||
|
|
||||||
import {FileGridEntryComponent} from "./file-grid-entry.component";
|
import {FileCardComponent} from "./file-card.component";
|
||||||
|
|
||||||
describe("FileGridEntryComponent", () => {
|
describe("FileGridEntryComponent", () => {
|
||||||
let component: FileGridEntryComponent;
|
let component: FileCardComponent;
|
||||||
let fixture: ComponentFixture<FileGridEntryComponent>;
|
let fixture: ComponentFixture<FileCardComponent>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [FileGridEntryComponent]
|
declarations: [FileCardComponent]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(FileGridEntryComponent);
|
fixture = TestBed.createComponent(FileCardComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
@ -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<File>;
|
||||||
|
@Output() clickEvent = new EventEmitter<FileCardComponent>();
|
||||||
|
@Output() dblClickEvent = new EventEmitter<FileCardComponent>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
<div (click)="fileSelectEvent.emit(this.file)" [class.selected]="this.file.selected" class="image-wrapper">
|
|
||||||
<app-file-thumbnail [file]="file.data"></app-file-thumbnail>
|
|
||||||
</div>
|
|
@ -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;
|
|
||||||
}
|
|
@ -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<FileGalleryEntryComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
declarations: [FileGalleryEntryComponent]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(FileGalleryEntryComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should create", () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -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<File>;
|
|
||||||
@Output() fileSelectEvent = new EventEmitter<Selectable<File>>();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
import {File} from "../../../../../../models/File";
|
|
||||||
|
|
||||||
export type GridEntry = {
|
|
||||||
file: File,
|
|
||||||
selected: boolean,
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<mat-card #card (click)="clickEvent.emit(this)" (dblclick)="dblClickEvent.emit(this)"
|
|
||||||
[ngClass]="{'selected': gridEntry.selected}">
|
|
||||||
<mat-card-content *ngIf="contentUrl !== undefined">
|
|
||||||
<app-file-thumbnail [file]="this.gridEntry.file" class=".entry-image"></app-file-thumbnail>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
@ -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<FileGridEntryComponent>();
|
|
||||||
@Output() dblClickEvent = new EventEmitter<FileGridEntryComponent>();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue