You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
3 years ago
|
import {
|
||
3 years ago
|
AfterViewInit,
|
||
|
Component,
|
||
|
Input,
|
||
|
OnChanges,
|
||
|
OnDestroy,
|
||
|
SimpleChanges,
|
||
|
ViewChild
|
||
|
} from "@angular/core";
|
||
3 years ago
|
import {SafeResourceUrl} from "@angular/platform-browser";
|
||
3 years ago
|
import {File} from "../../../../models/File";
|
||
|
import {FileService} from "../../../../services/file/file.service";
|
||
|
import {FileHelper} from "../../../../services/file/file.helper";
|
||
|
import {ErrorBrokerService} from "../../../../services/error-broker/error-broker.service";
|
||
|
import {BusyIndicatorComponent} from "../../app-common/busy-indicator/busy-indicator.component";
|
||
3 years ago
|
|
||
3 years ago
|
type ContentType = "image" | "video" | "audio" | "other";
|
||
3 years ago
|
|
||
|
@Component({
|
||
3 years ago
|
selector: "app-content-viewer",
|
||
|
templateUrl: "./content-viewer.component.html",
|
||
|
styleUrls: ["./content-viewer.component.scss"]
|
||
3 years ago
|
})
|
||
3 years ago
|
export class ContentViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||
3 years ago
|
@Input() file!: File;
|
||
3 years ago
|
|
||
3 years ago
|
public contentUrl: SafeResourceUrl | undefined;
|
||
|
public blobUrl: SafeResourceUrl | undefined;
|
||
3 years ago
|
|
||
3 years ago
|
@ViewChild(BusyIndicatorComponent) busyIndicator!: BusyIndicatorComponent;
|
||
3 years ago
|
|
||
3 years ago
|
constructor(
|
||
|
private errorBroker: ErrorBrokerService,
|
||
|
private fileService: FileService
|
||
|
) {
|
||
3 years ago
|
}
|
||
|
|
||
3 years ago
|
public async ngAfterViewInit() {
|
||
|
if (["audio", "video"].includes(this.getContentType())) {
|
||
|
await this.loadBlobUrl();
|
||
|
} else {
|
||
|
this.contentUrl = this.fileService.buildContentUrl(this.file);
|
||
|
}
|
||
3 years ago
|
}
|
||
|
|
||
3 years ago
|
public async ngOnChanges(changes: SimpleChanges) {
|
||
|
if (changes["file"]) {
|
||
|
if (["audio", "video"].includes(
|
||
|
this.getContentType()) && this.busyIndicator) {
|
||
|
await this.loadBlobUrl();
|
||
|
} else {
|
||
|
this.contentUrl = this.fileService.buildContentUrl(this.file);
|
||
|
this.unloadBlobUrl();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
3 years ago
|
|
||
3 years ago
|
public ngOnDestroy(): void {
|
||
|
this.unloadBlobUrl();
|
||
3 years ago
|
}
|
||
|
|
||
3 years ago
|
public getContentType(): ContentType {
|
||
|
if (!this.file.mime_type) {
|
||
|
return "other";
|
||
|
}
|
||
|
let mimeParts = this.file.mime_type.split("/");
|
||
|
const type = mimeParts.shift() ?? "other";
|
||
|
const subtype = mimeParts.shift() ?? "*";
|
||
|
|
||
|
switch (type) {
|
||
|
case "image":
|
||
|
return "image";
|
||
|
case "video":
|
||
|
return "video";
|
||
|
case "audio":
|
||
|
return "audio";
|
||
|
default:
|
||
|
return "other";
|
||
|
}
|
||
3 years ago
|
}
|
||
3 years ago
|
|
||
3 years ago
|
public async downloadContent() {
|
||
|
const path = await FileHelper.getFileDownloadLocation(this.file)
|
||
3 years ago
|
|
||
3 years ago
|
if (path) {
|
||
|
try {
|
||
|
await this.fileService.saveFile(this.file, path);
|
||
|
} catch (err) {
|
||
|
this.errorBroker.showError(err);
|
||
|
}
|
||
|
}
|
||
3 years ago
|
}
|
||
|
|
||
3 years ago
|
public async loadBlobUrl(): Promise<void> {
|
||
|
await this.busyIndicator.wrapAsyncOperation(async () => {
|
||
|
const startId = this.file.id;
|
||
|
this.unloadBlobUrl();
|
||
|
const url = await this.fileService.readFile(this.file);
|
||
|
if (startId === this.file.id) {
|
||
|
this.blobUrl = url;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
3 years ago
|
|
||
3 years ago
|
private unloadBlobUrl() {
|
||
|
if (this.blobUrl) {
|
||
|
URL?.revokeObjectURL(this.blobUrl as string);
|
||
|
this.blobUrl = undefined;
|
||
|
}
|
||
3 years ago
|
}
|
||
3 years ago
|
}
|