mirror of
https://github.com/infrost/RaptorQR.git
synced 2026-08-31 06:57:45 +08:00
8d894b08e6
- Removed session tracking entirely; single global decode state - Receiver UI: no sessions table, no big progress bar - Inline stats above video: scanned / useful / need · gen X of Y - Sender passes filename and mimeType to encode worker - Packetizer wraps file payloads with [filenameLen][name][mimeLen][mime] header - Decode worker parses metadata and uses it for download name/type - Fixed generation counter bug: final progress was skipped when reconstruction succeeded; now reportProgress is called right before early return
72 lines
2.2 KiB
TypeScript
72 lines
2.2 KiB
TypeScript
/**
|
|
* Encode worker — receives raw data, compresses, packetizes, schedules.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import { packetize } from '@/core/sender/packetizer';
|
|
import { scheduleFrames } from '@/core/sender/scheduler';
|
|
|
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
|
|
interface EncodeInput {
|
|
type: 'encode';
|
|
data: ArrayBuffer;
|
|
isText: boolean;
|
|
compress: boolean;
|
|
filename?: string;
|
|
mimeType?: string;
|
|
}
|
|
|
|
interface EncodeOutput {
|
|
type: 'encoded';
|
|
packets: Uint8Array[];
|
|
sessionId: number;
|
|
totalGenerations: number;
|
|
stats: {
|
|
originalSize: number;
|
|
preprocessedSize: number;
|
|
frameCount: number;
|
|
};
|
|
}
|
|
|
|
interface ErrorOutput {
|
|
type: 'error';
|
|
message: string;
|
|
}
|
|
|
|
// ─── Worker handler ───────────────────────────────────────────────────────────────────
|
|
|
|
self.onmessage = (e: MessageEvent<EncodeInput>) => {
|
|
const msg = e.data;
|
|
if (msg.type !== 'encode') return;
|
|
|
|
try {
|
|
const result = handleEncode(msg);
|
|
const transfer: ArrayBufferLike[] = result.packets
|
|
.map((p) => p.buffer as ArrayBuffer)
|
|
.filter((b): b is ArrayBuffer => b instanceof ArrayBuffer && b.byteLength <= 1024 * 1024);
|
|
self.postMessage(result, transfer.length > 0 ? { transfer } : undefined);
|
|
} catch (err: any) {
|
|
self.postMessage({ type: 'error', message: err.message ?? String(err) } satisfies ErrorOutput);
|
|
}
|
|
};
|
|
|
|
function handleEncode(input: EncodeInput): EncodeOutput {
|
|
const originalBytes = new Uint8Array(input.data);
|
|
const result = packetize(originalBytes, input.isText, input.compress, input.filename, input.mimeType);
|
|
const frames = scheduleFrames(result.packets, result.totalGenerations, result.sessionId);
|
|
|
|
return {
|
|
type: 'encoded',
|
|
packets: frames,
|
|
sessionId: result.sessionId,
|
|
totalGenerations: result.totalGenerations,
|
|
stats: {
|
|
originalSize: originalBytes.length,
|
|
preprocessedSize: result.dataLength,
|
|
frameCount: frames.length,
|
|
},
|
|
};
|
|
}
|