Add somehow working file content retrieval
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
5e4d6e098f
commit
2940f8089a
@ -0,0 +1,29 @@
|
|||||||
|
use mediarepo::requests::ReadFileRequest;
|
||||||
|
use mediarepo::responses::FileResponse;
|
||||||
|
use crate::context::Context;
|
||||||
|
use crate::error::{AppError, AppResult};
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_all_files(context: tauri::State<'_, Context>) -> AppResult<Vec<FileResponse>> {
|
||||||
|
let ipc = context.ipc.read().await;
|
||||||
|
if let Some(ipc) = &*ipc {
|
||||||
|
let response = ipc.emitter.emit_to("files", "all_files", ()).await?.await_reply(&ipc).await?;
|
||||||
|
|
||||||
|
Ok(response.data::<Vec<FileResponse>>()?)
|
||||||
|
} else {
|
||||||
|
Err(AppError::new("No ipc connection."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn read_file_by_hash(hash: String, context: tauri::State<'_, Context>) -> AppResult<Vec<u8>> {
|
||||||
|
let ipc = context.ipc.read().await;
|
||||||
|
if let Some(ipc) = &*ipc {
|
||||||
|
let response = ipc.emitter.emit_to("files", "read_file", ReadFileRequest::Hash(hash)).await?.await_reply(&ipc).await?;
|
||||||
|
|
||||||
|
Ok(response.data::<Vec<u8>>()?)
|
||||||
|
} else {
|
||||||
|
Err(AppError::new("No ipc connection."))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<mat-card>
|
||||||
|
<mat-card-title *ngIf="!!file?.name">{{file?.name}}</mat-card-title>
|
||||||
|
<mat-card-content>
|
||||||
|
<img class="entry-image" decoding="async" [src]="contentUrl" alt="image">
|
||||||
|
</mat-card-content>
|
||||||
|
<mat-card-footer>{{file?.mime_type}}, {{file?.hash}}</mat-card-footer>
|
||||||
|
</mat-card>
|
@ -0,0 +1,15 @@
|
|||||||
|
mat-card, mat-card-content {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-card-content {
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FileGridEntryComponent } from './file-grid-entry.component';
|
||||||
|
|
||||||
|
describe('FileGridEntryComponent', () => {
|
||||||
|
let component: FileGridEntryComponent;
|
||||||
|
let fixture: ComponentFixture<FileGridEntryComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ FileGridEntryComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FileGridEntryComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,28 @@
|
|||||||
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
|
import {File} from "../../../models/File";
|
||||||
|
import {FileService} from "../../../services/file/file.service";
|
||||||
|
import {ErrorBrokerService} from "../../../services/error-broker/error-broker.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-file-grid-entry',
|
||||||
|
templateUrl: './file-grid-entry.component.html',
|
||||||
|
styleUrls: ['./file-grid-entry.component.scss']
|
||||||
|
})
|
||||||
|
export class FileGridEntryComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() file: File | undefined;
|
||||||
|
contentUrl: string | undefined;
|
||||||
|
constructor(private fileService: FileService, private errorBroker: ErrorBrokerService) { }
|
||||||
|
|
||||||
|
async ngOnInit(): Promise<void> {
|
||||||
|
if (this.file) {
|
||||||
|
console.log(this.file);
|
||||||
|
try {
|
||||||
|
this.contentUrl = await this.fileService.readFile(this.file.hash, this.file.mime_type ?? "image/png");
|
||||||
|
} catch (err) {
|
||||||
|
this.errorBroker.showError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<mat-grid-list cols="5" rowHeight="1:1">
|
||||||
|
<mat-grid-tile *ngFor="let file of files">
|
||||||
|
<app-file-grid-entry [file]="file"></app-file-grid-entry>
|
||||||
|
</mat-grid-tile>
|
||||||
|
</mat-grid-list>
|
@ -0,0 +1,4 @@
|
|||||||
|
app-file-grid-entry {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FileGridComponent } from './file-grid.component';
|
||||||
|
|
||||||
|
describe('FileGridComponent', () => {
|
||||||
|
let component: FileGridComponent;
|
||||||
|
let fixture: ComponentFixture<FileGridComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ FileGridComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FileGridComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import {File} from "../../models/File";
|
||||||
|
import {FileService} from "../../services/file/file.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-file-grid',
|
||||||
|
templateUrl: './file-grid.component.html',
|
||||||
|
styleUrls: ['./file-grid.component.scss']
|
||||||
|
})
|
||||||
|
export class FileGridComponent implements OnInit {
|
||||||
|
|
||||||
|
files: File[] = [];
|
||||||
|
|
||||||
|
constructor(private fileService: FileService) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.fileService.displayedFiles.subscribe((files) => this.files = files);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
export class File {
|
||||||
|
constructor(
|
||||||
|
public name: string | undefined,
|
||||||
|
public comment: string | undefined,
|
||||||
|
public hash: string,
|
||||||
|
public file_type: number,
|
||||||
|
public mime_type: string | undefined,
|
||||||
|
public creation_time: Date,
|
||||||
|
public change_time: Date,
|
||||||
|
public import_time: Date,
|
||||||
|
) {}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
export type Info = {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
}
|
@ -1 +1,14 @@
|
|||||||
<p>home works!</p>
|
<div id="content">
|
||||||
|
<mat-toolbar color="primary">
|
||||||
|
<h1>Files</h1>
|
||||||
|
</mat-toolbar>
|
||||||
|
<mat-drawer-container>
|
||||||
|
<mat-drawer mode="side" opened>
|
||||||
|
<p>Drawer</p>
|
||||||
|
</mat-drawer>
|
||||||
|
<mat-drawer-content>
|
||||||
|
<app-file-grid></app-file-grid>
|
||||||
|
</mat-drawer-content>
|
||||||
|
</mat-drawer-container>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
#content {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-drawer {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-drawer-content {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-drawer-container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
@ -1,15 +1,17 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import {FileService} from "../../services/file/file.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrls: ['./home.component.sass']
|
styleUrls: ['./home.component.scss']
|
||||||
})
|
})
|
||||||
export class HomeComponent implements OnInit {
|
export class HomeComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor(private fileService: FileService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
async ngOnInit() {
|
||||||
|
await this.fileService.getFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FileService } from './file.service';
|
||||||
|
|
||||||
|
describe('FileService', () => {
|
||||||
|
let service: FileService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(FileService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,39 @@
|
|||||||
|
import {Inject, Injectable} from '@angular/core';
|
||||||
|
import {BehaviorSubject} from "rxjs";
|
||||||
|
import {File} from "../../models/File";
|
||||||
|
import {invoke} from "@tauri-apps/api/tauri";
|
||||||
|
import {DOCUMENT} from "@angular/common";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class FileService {
|
||||||
|
|
||||||
|
displayedFiles = new BehaviorSubject<File[]>([]);
|
||||||
|
|
||||||
|
constructor(@Inject(DOCUMENT) private document: Document) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFiles() {
|
||||||
|
let all_files = await invoke<File[]>("get_all_files");
|
||||||
|
this.displayedFiles.next(all_files.slice(0, 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async readFile(hash: string, mime_type: string): Promise<string | undefined> {
|
||||||
|
const data = await invoke<number[]>("read_file_by_hash", {hash});
|
||||||
|
const blob = new Blob([new Uint8Array(data)], {type: mime_type});
|
||||||
|
return new Promise<string | undefined>((res, rej) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
const url = e.target?.result
|
||||||
|
if (url === null) {
|
||||||
|
res(undefined);
|
||||||
|
} else {
|
||||||
|
res(url as string)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue