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 {FileService} from "../../services/file/file.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.sass']
|
||||
styleUrls: ['./home.component.scss']
|
||||
})
|
||||
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