mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-02-04 08:06:56 +00:00
누락된 @eslint/js 패키지 추가
This commit is contained in:
102
src/routes/(fullscreen)/settings/thumbnail/service.ts
Normal file
102
src/routes/(fullscreen)/settings/thumbnail/service.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { limitFunction } from "p-limit";
|
||||
import { SvelteMap } from "svelte/reactivity";
|
||||
import { encryptData } from "$lib/modules/crypto";
|
||||
import { storeFileThumbnailCache } from "$lib/modules/file";
|
||||
import type { FileInfo } from "$lib/modules/filesystem";
|
||||
import { Scheduler } from "$lib/modules/scheduler";
|
||||
import { generateThumbnail as doGenerateThumbnail } from "$lib/modules/thumbnail";
|
||||
import { requestFileDownload, requestFileThumbnailUpload } from "$lib/services/file";
|
||||
|
||||
export type GenerationStatus =
|
||||
| "queued"
|
||||
| "generation-pending"
|
||||
| "generating"
|
||||
| "upload-pending"
|
||||
| "uploading"
|
||||
| "uploaded"
|
||||
| "error";
|
||||
|
||||
const scheduler = new Scheduler();
|
||||
const statuses = new SvelteMap<number, GenerationStatus>();
|
||||
|
||||
export const getThumbnailGenerationStatus = (fileId: number) => {
|
||||
return statuses.get(fileId);
|
||||
};
|
||||
|
||||
export const clearThumbnailGenerationStatuses = () => {
|
||||
for (const [id, status] of statuses) {
|
||||
if (status === "uploaded" || status === "error") {
|
||||
statuses.delete(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const generateThumbnail = limitFunction(
|
||||
async (fileId: number, fileBuffer: ArrayBuffer, fileType: string, dataKey: CryptoKey) => {
|
||||
statuses.set(fileId, "generating");
|
||||
|
||||
const thumbnail = await doGenerateThumbnail(fileBuffer, fileType);
|
||||
if (!thumbnail) return null;
|
||||
|
||||
const thumbnailBuffer = await thumbnail.arrayBuffer();
|
||||
const thumbnailEncrypted = await encryptData(thumbnailBuffer, dataKey);
|
||||
statuses.set(fileId, "upload-pending");
|
||||
return { plaintext: thumbnailBuffer, ...thumbnailEncrypted };
|
||||
},
|
||||
{ concurrency: 4 },
|
||||
);
|
||||
|
||||
const requestThumbnailUpload = limitFunction(
|
||||
async (
|
||||
fileId: number,
|
||||
dataKeyVersion: Date,
|
||||
thumbnail: { plaintext: ArrayBuffer; ciphertext: ArrayBuffer; iv: string },
|
||||
) => {
|
||||
statuses.set(fileId, "uploading");
|
||||
|
||||
const res = await requestFileThumbnailUpload(fileId, dataKeyVersion, thumbnail);
|
||||
if (!res.ok) return false;
|
||||
statuses.set(fileId, "uploaded");
|
||||
storeFileThumbnailCache(fileId, thumbnail.plaintext); // Intended
|
||||
return true;
|
||||
},
|
||||
{ concurrency: 4 },
|
||||
);
|
||||
|
||||
export const requestThumbnailGeneration = async (fileInfo: FileInfo) => {
|
||||
const status = statuses.get(fileInfo.id);
|
||||
if (status) {
|
||||
if (status !== "error") return;
|
||||
} else {
|
||||
statuses.set(fileInfo.id, "queued");
|
||||
}
|
||||
|
||||
try {
|
||||
let file: ArrayBuffer | undefined;
|
||||
|
||||
await scheduler.schedule(
|
||||
async () => {
|
||||
statuses.set(fileInfo.id, "generation-pending");
|
||||
file = await requestFileDownload(fileInfo.id, fileInfo.contentIv!, fileInfo.dataKey?.key!);
|
||||
return file.byteLength;
|
||||
},
|
||||
async () => {
|
||||
const thumbnail = await generateThumbnail(
|
||||
fileInfo.id,
|
||||
file!,
|
||||
fileInfo.contentType,
|
||||
fileInfo.dataKey?.key!,
|
||||
);
|
||||
if (
|
||||
!thumbnail ||
|
||||
!(await requestThumbnailUpload(fileInfo.id, fileInfo.dataKey?.version!, thumbnail))
|
||||
) {
|
||||
statuses.set(fileInfo.id, "error");
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
statuses.set(fileInfo.id, "error");
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user