fix: separate resource previews from downloads

This commit is contained in:
2026-07-22 20:06:18 +02:00
parent 50268cb185
commit e6a8111d51
8 changed files with 257 additions and 28 deletions

View File

@@ -53,12 +53,17 @@ class SuccessfulParserWorker implements WorkerPort {
onerror: ((event: ErrorEvent) => void) | null = null;
terminated = false;
lastMessage: WorkerRequest | undefined;
readonly messages: WorkerRequest[] = [];
lastTransfer: Transferable[] = [];
constructor(private readonly packageResult?: OneNotePackageDto) {}
constructor(
private readonly packageResult?: OneNotePackageDto,
private readonly resourcePage = false
) {}
postMessage(message: WorkerRequest, transfer: Transferable[] = []): void {
this.lastMessage = message;
this.messages.push(message);
this.lastTransfer = transfer;
queueMicrotask(() => {
if (message.type === 'parse-one') {
@@ -84,27 +89,67 @@ class SuccessfulParserWorker implements WorkerPort {
page: {
...page,
id: message.pageId,
blocks: [
{
kind: 'text',
id: 'text-1',
sourceText: page.text,
text: page.text,
runs: [
blocks: this.resourcePage
? [
{
start: 0,
end: page.text.length,
kind: 'image',
id: 'image-1',
resourceId: 'resource-image',
filename: 'large.png',
isBackground: false,
layout: {},
},
]
: [
{
kind: 'text',
id: 'text-1',
sourceText: page.text,
text: page.text,
style: {},
runs: [
{
start: 0,
end: page.text.length,
text: page.text,
style: {},
},
],
paragraphStyle: {},
layout: {},
},
],
paragraphStyle: {},
layout: {},
},
],
diagnostics: [],
},
});
} else if (message.type === 'get-resource') {
if (message.intent === 'preview') {
this.respond({
type: 'failure',
requestId: message.requestId,
error: {
code: 'resource-not-available',
message:
'This image can be downloaded but is not approved for automatic preview.',
recoverable: true,
},
});
} else {
this.respond({
type: 'resource',
requestId: message.requestId,
sessionId: message.sessionId,
resource: {
id: message.resourceId,
kind: 'image',
filename: 'large.png',
extension: 'png',
mediaType: 'image/png',
browserRenderable: false,
size: 4,
bytes: Uint8Array.of(1, 2, 3, 4).buffer,
},
});
}
} else if (message.type === 'export-session') {
this.respond({
type: 'export-artifact',
@@ -231,6 +276,54 @@ describe('OneNoteApplication', () => {
expect(click).toHaveBeenCalledOnce();
});
it('requests a rejected preview separately from an explicit image download', async () => {
const user = userEvent.setup();
const worker = new SuccessfulParserWorker(undefined, true);
vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:local-image');
const click = vi
.spyOn(HTMLAnchorElement.prototype, 'click')
.mockImplementation(() => undefined);
render(
<OneNoteApplication
createWorkerClient={() => new OneNoteWorkerClient(() => worker)}
/>
);
await user.upload(
screen.getByLabelText('Choose OneNote files'),
new File([new Uint8Array([1, 2, 3])], 'Section.one')
);
expect(
await screen.findByText(/not approved for automatic preview/i)
).toBeVisible();
expect(worker.messages).toContainEqual(
expect.objectContaining({
type: 'get-resource',
resourceId: 'resource-image',
intent: 'preview',
})
);
expect(
worker.messages.some(
(message) =>
message.type === 'get-resource' && message.intent === 'download'
)
).toBe(false);
await user.click(
screen.getByRole('button', { name: 'Download original image' })
);
expect(worker.messages).toContainEqual(
expect.objectContaining({
type: 'get-resource',
resourceId: 'resource-image',
intent: 'download',
})
);
expect(click).toHaveBeenCalledOnce();
});
it('opens a dropped OneNote package through the local worker', async () => {
const notebook: OneNotePackageDto = {
format: 'onepkg',