From ef9ce713da764e569edc6214a9c4b9f7e8f58f2c Mon Sep 17 00:00:00 2001 From: trivernis Date: Thu, 11 Nov 2021 21:13:31 +0100 Subject: [PATCH] Change thumbnails and images to be directly retrieved from custom schemes Signed-off-by: trivernis --- mediarepo-ui/src-tauri/Cargo.lock | 6 +- mediarepo-ui/src-tauri/Cargo.toml | 2 +- mediarepo-ui/src-tauri/tauri.conf.json | 2 +- .../file-gallery-entry.component.ts | 24 ++------ .../file-gallery/file-gallery.component.ts | 4 +- .../file-grid-entry.component.ts | 58 ++++++++----------- .../src/app/services/file/file.service.ts | 20 +++++++ 7 files changed, 56 insertions(+), 60 deletions(-) diff --git a/mediarepo-ui/src-tauri/Cargo.lock b/mediarepo-ui/src-tauri/Cargo.lock index edc739a..59e8ade 100644 --- a/mediarepo-ui/src-tauri/Cargo.lock +++ b/mediarepo-ui/src-tauri/Cargo.lock @@ -1580,12 +1580,13 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mediarepo-api" -version = "0.6.0" -source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=ddebf4bf0c3e96ede64182ff52bd84f134acc33a#ddebf4bf0c3e96ede64182ff52bd84f134acc33a" +version = "0.7.0" +source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=acda7307dc58e9ac489b12bab61561a1cbf951eb#acda7307dc58e9ac489b12bab61561a1cbf951eb" dependencies = [ "async-trait", "chrono", "directories", + "futures", "mime_guess", "parking_lot", "rmp-ipc", @@ -1597,6 +1598,7 @@ dependencies = [ "tokio", "toml", "tracing", + "url", ] [[package]] diff --git a/mediarepo-ui/src-tauri/Cargo.toml b/mediarepo-ui/src-tauri/Cargo.toml index c7422e6..1d6cb43 100644 --- a/mediarepo-ui/src-tauri/Cargo.toml +++ b/mediarepo-ui/src-tauri/Cargo.toml @@ -30,7 +30,7 @@ features = ["env-filter"] [dependencies.mediarepo-api] git = "https://github.com/Trivernis/mediarepo-api.git" -rev = "ddebf4bf0c3e96ede64182ff52bd84f134acc33a" +rev = "acda7307dc58e9ac489b12bab61561a1cbf951eb" features = ["tauri-plugin"] [features] diff --git a/mediarepo-ui/src-tauri/tauri.conf.json b/mediarepo-ui/src-tauri/tauri.conf.json index e129684..128750c 100644 --- a/mediarepo-ui/src-tauri/tauri.conf.json +++ b/mediarepo-ui/src-tauri/tauri.conf.json @@ -61,7 +61,7 @@ } ], "security": { - "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self' once:" + "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self' once: thumb: content:" } } } diff --git a/mediarepo-ui/src/app/components/file-gallery/file-gallery-entry/file-gallery-entry.component.ts b/mediarepo-ui/src/app/components/file-gallery/file-gallery-entry/file-gallery-entry.component.ts index 11005ae..bed53c7 100644 --- a/mediarepo-ui/src/app/components/file-gallery/file-gallery-entry/file-gallery-entry.component.ts +++ b/mediarepo-ui/src/app/components/file-gallery/file-gallery-entry/file-gallery-entry.component.ts @@ -1,6 +1,6 @@ import { Component, - EventEmitter, + EventEmitter, Inject, Input, OnChanges, OnInit, @@ -9,7 +9,7 @@ import { } from '@angular/core'; import {File} from "../../../models/File"; import {FileService} from "../../../services/file/file.service"; -import {SafeResourceUrl} from "@angular/platform-browser"; +import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser"; import {ErrorBrokerService} from "../../../services/error-broker/error-broker.service"; import {Selectable} from "../../../models/Selectable"; @@ -26,32 +26,18 @@ export class FileGalleryEntryComponent implements OnInit, OnChanges { private cachedFile: File | undefined; - constructor(private fileService: FileService, private errorBroker: ErrorBrokerService) { + constructor(@Inject(DomSanitizer) private sanitizer: DomSanitizer, private fileService: FileService, private errorBroker: ErrorBrokerService) { } async ngOnChanges(changes: SimpleChanges): Promise { 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.contentUrl = undefined; - await this.loadImage(); + this.contentUrl = this.fileService.buildThumbnailUrl(this.file.data, 250, 250); } } async ngOnInit() { this.cachedFile = this.file.data; - await this.loadImage(); - } - - async loadImage() { - try { - const hash = this.file.data.hash; - const contentUrl = await this.fileService.getFileThumbnail(this.file.data, 250, 250); - - if (this.file.data.hash === hash) { // avoid issues with changed files - this.contentUrl = contentUrl; - } - } catch (err) { - this.errorBroker.showError(err); - } + this.contentUrl = this.fileService.buildThumbnailUrl(this.file.data, 250, 250); } } diff --git a/mediarepo-ui/src/app/components/file-gallery/file-gallery.component.ts b/mediarepo-ui/src/app/components/file-gallery/file-gallery.component.ts index d924fe1..37a6864 100644 --- a/mediarepo-ui/src/app/components/file-gallery/file-gallery.component.ts +++ b/mediarepo-ui/src/app/components/file-gallery/file-gallery.component.ts @@ -89,9 +89,7 @@ export class FileGalleryComponent implements OnChanges, OnInit { */ async loadSelectedFile() { if (this.selectedFile) { - this.fileContentUrl = undefined; - this.fileContentUrl = await this.fileService.readFile( - this.selectedFile.data); + this.fileContentUrl = this.fileService.buildContentUrl(this.selectedFile.data) } } diff --git a/mediarepo-ui/src/app/components/file-grid/file-grid-entry/file-grid-entry.component.ts b/mediarepo-ui/src/app/components/file-grid/file-grid-entry/file-grid-entry.component.ts index 33982ff..e249ee7 100644 --- a/mediarepo-ui/src/app/components/file-grid/file-grid-entry/file-grid-entry.component.ts +++ b/mediarepo-ui/src/app/components/file-grid/file-grid-entry/file-grid-entry.component.ts @@ -5,7 +5,8 @@ import { Input, OnChanges, OnInit, - Output, SimpleChanges, + Output, + SimpleChanges, ViewChild } from '@angular/core'; import {File} from "../../../models/File"; @@ -15,45 +16,34 @@ 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'] + 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(); + @ViewChild("card") card!: ElementRef; + @Input() public gridEntry!: GridEntry; + @Output() clickEvent = new EventEmitter(); + @Output() dblClickEvent = new EventEmitter(); - contentUrl: SafeResourceUrl | undefined; - private cachedFile: File | undefined; + contentUrl: SafeResourceUrl | undefined; + private cachedFile: File | undefined; - constructor(private fileService: FileService, private errorBroker: ErrorBrokerService) { - } - - async ngOnInit() { - this.cachedFile = this.gridEntry.file; - await this.loadImage(); - } - - async ngOnChanges(changes: SimpleChanges) { - if (changes["file"] && (!this.cachedFile || this.gridEntry.file.hash !== this.cachedFile.hash)) { - this.cachedFile = this.gridEntry.file; - await this.loadImage(); - } - } + constructor(private fileService: FileService, private errorBroker: ErrorBrokerService) { + } - async loadImage() { - try { - const hash = this.gridEntry.file.hash; - const contentUrl = await this.fileService.getFileThumbnail(this.gridEntry.file, 250, 250); + async ngOnInit() { + this.cachedFile = this.gridEntry.file; + this.contentUrl = this.fileService.buildThumbnailUrl(this.gridEntry.file, + 250, 250); + } - if (this.gridEntry.file.hash === hash) { // avoid issues with changed files - this.contentUrl = contentUrl; - } - } catch (err) { - this.errorBroker.showError(err); - } + async ngOnChanges(changes: SimpleChanges) { + if (changes["file"] && (!this.cachedFile || this.gridEntry.file.hash !== this.cachedFile.hash)) { + this.cachedFile = this.gridEntry.file; + this.contentUrl = this.fileService.buildThumbnailUrl(this.gridEntry.file, + 250, 250); } + } } diff --git a/mediarepo-ui/src/app/services/file/file.service.ts b/mediarepo-ui/src/app/services/file/file.service.ts index 7a4323e..9a07e72 100644 --- a/mediarepo-ui/src/app/services/file/file.service.ts +++ b/mediarepo-ui/src/app/services/file/file.service.ts @@ -90,4 +90,24 @@ export class FileService { public async updateFileName(file: File, name: string): Promise { return await invoke("plugin:mediarepo|update_file_name", {id: file.id, name}) } + + /** + * Builds a safe thumbnail url that accesses custom scheme for thumbnails + * @param {File} file + * @param {number} height + * @param {number} width + * @returns {SafeResourceUrl} + */ + public buildThumbnailUrl(file: File, height: number, width: number): SafeResourceUrl { + return this.sanitizer.bypassSecurityTrustResourceUrl(`thumb://${file.hash}?width=${250}&height=${250}`) + } + + /** + * Builds a safe content url that accesses custom scheme for thumbnails + * @param {File} file + * @returns {SafeResourceUrl} + */ + public buildContentUrl(file: File): SafeResourceUrl { + return this.sanitizer.bypassSecurityTrustResourceUrl(`content://${file.hash}`) + } }