feat: move calculation intensive part into a web worker

This commit is contained in:
2026-09-13 21:51:13 +02:00
parent a57ead61b9
commit b58bf8af6d
6 changed files with 182 additions and 149 deletions
+10 -14
View File
@@ -130,20 +130,16 @@
throw new EmptyContentError()
}
const filesInput: NoteInput = {
type: 'files',
files: $state.snapshot(files),
}
const payload = await worker.pack(
isFile
? transfer(
filesInput,
filesInput.files.map((f) => f.data.buffer)
)
: { type: 'text', text: textContent },
customPassword || undefined
)
const noteInput: NoteInput = isFile
? transfer(
{
type: 'files',
files: $state.snapshot(files),
},
files.map((f) => f.data.buffer)
)
: { type: 'text', text: textContent }
const payload = await worker.pack(noteInput, customPassword || undefined)
const serverNote: ServerNote = {
meta: {
...(timeExpiration
+14
View File
@@ -0,0 +1,14 @@
import { wrap } from 'comlink'
import CryptWorker from './worker?worker'
import type { packContent, unpackContent } from '@cryptgeon/shared'
export function createWorker() {
const worker = new CryptWorker()
return wrap<WorkerConract>(worker)
}
export type WorkerConract = {
pack: typeof packContent
unpack: typeof unpackContent
}
@@ -0,0 +1,19 @@
import type { WorkerConract } from '$lib/worker'
import { packContent, unpackContent } from '@cryptgeon/shared'
import { expose, transfer } from 'comlink'
const contract: WorkerConract = {
pack(input, password) {
const content = packContent(input, password)
return transfer(content, [content.data.buffer, content.extra.buffer, content.key.buffer])
},
unpack(data, key) {
const content = unpackContent(data, key)
return transfer(
content,
typeof content.data === 'string' ? [] : content.data.map((f) => f.data.buffer)
)
},
}
expose(contract)
@@ -1,5 +1,13 @@
<script lang="ts">
import { deriveKey, hexToBytes, decode, info, get as apiGet, unpackContent, type FileDTO } from '@cryptgeon/shared'
import {
deriveKey,
hexToBytes,
decode,
info,
get as apiGet,
unpackContent,
type FileDTO,
} from '@cryptgeon/shared'
import { onMount } from 'svelte'
import { t } from 'svelte-intl-precompile'
@@ -8,6 +16,7 @@
import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte'
import TextInput from '$lib/ui/TextInput.svelte'
import type { PageData } from './$types'
import { createWorker } from '$lib/worker'
interface Props {
data: PageData
@@ -44,6 +53,8 @@
}
})
const worker = createWorker()
async function show(e: SubmitEvent) {
e.preventDefault()
try {
@@ -69,7 +80,7 @@
key = hexToBytes(password!)
}
const content = unpackContent(serverNote.data, key)
const content = await worker.unpack(serverNote.data, key)
switch (content.type) {
case 'text':
@@ -78,16 +89,16 @@
contents: content.data,
}
break
case 'files':
const files = (content.data as any[]).map((f: any) => ({
...f,
data: f.data instanceof Uint8Array ? f.data : new Uint8Array(f.data as any),
}))
note = {
meta: { type: 'file' },
contents: files,
}
break
case 'files':
const files = (content.data as any[]).map((f: any) => ({
...f,
data: f.data instanceof Uint8Array ? f.data : new Uint8Array(f.data as any),
}))
note = {
meta: { type: 'file' },
contents: files,
}
break
default:
error = $t('show.errors.unsupported_type')
return
@@ -144,4 +155,4 @@ break
flex-direction: column;
gap: 1rem;
}
</style>
</style>