feat: open multi-part packages in browser
This commit is contained in:
47
src/App.tsx
47
src/App.tsx
@@ -20,10 +20,7 @@ import type {
|
||||
OneNoteSectionDto,
|
||||
} from './onenote/model/dto.js';
|
||||
import type { ParserDiagnostic } from './onenote/model/diagnostics.js';
|
||||
import {
|
||||
MAX_SOURCE_FILE_BYTES,
|
||||
sourceKindFromFileName,
|
||||
} from './source-file.js';
|
||||
import { selectSourceFiles } from './source-file.js';
|
||||
import { toolboxApp } from './toolbox/manifest.js';
|
||||
import {
|
||||
OneNoteWorkerClient,
|
||||
@@ -174,21 +171,13 @@ export function OneNoteApplication({
|
||||
}
|
||||
};
|
||||
|
||||
const openFile = async (file: File) => {
|
||||
const sourceKind = sourceKindFromFileName(file.name);
|
||||
if (!sourceKind) {
|
||||
const openFiles = async (files: File[]) => {
|
||||
const selection = selectSourceFiles(files);
|
||||
if (!selection.ok) {
|
||||
setState({
|
||||
phase: 'error',
|
||||
title: 'Unsupported file name',
|
||||
message: 'Choose a file whose name ends in .one or .onepkg.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (file.size > MAX_SOURCE_FILE_BYTES) {
|
||||
setState({
|
||||
phase: 'error',
|
||||
title: 'File is too large',
|
||||
message: 'The selected file exceeds the current 512 MiB safety limit.',
|
||||
title: selection.title,
|
||||
message: selection.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -201,12 +190,24 @@ export function OneNoteApplication({
|
||||
activeClient.current = client;
|
||||
setSelectedSectionId(undefined);
|
||||
setPageState({ phase: 'empty' });
|
||||
setState({ phase: 'reading', fileName: file.name });
|
||||
setState({ phase: 'reading', fileName: selection.source.name });
|
||||
|
||||
try {
|
||||
const bytes = await file.arrayBuffer();
|
||||
const buffers = await Promise.all(
|
||||
[selection.source, ...selection.cabinetParts].map((file) =>
|
||||
file.arrayBuffer()
|
||||
)
|
||||
);
|
||||
if (generation.current !== requestGeneration) return;
|
||||
const response = await client.parseSource(sourceKind, file.name, bytes);
|
||||
const response = await client.parseSource(
|
||||
selection.kind,
|
||||
selection.source.name,
|
||||
buffers[0]!,
|
||||
selection.cabinetParts.map((part, index) => ({
|
||||
fileName: part.name,
|
||||
bytes: buffers[index + 1]!,
|
||||
}))
|
||||
);
|
||||
if (generation.current !== requestGeneration) return;
|
||||
|
||||
if (response.type === 'failure') {
|
||||
@@ -226,7 +227,7 @@ export function OneNoteApplication({
|
||||
if (response.type === 'section') {
|
||||
setState({
|
||||
phase: 'loaded',
|
||||
fileName: file.name,
|
||||
fileName: selection.source.name,
|
||||
source: {
|
||||
kind: 'one',
|
||||
sessionId: response.sessionId,
|
||||
@@ -253,7 +254,7 @@ export function OneNoteApplication({
|
||||
setSelectedSectionId(preferredSection?.id);
|
||||
setState({
|
||||
phase: 'loaded',
|
||||
fileName: file.name,
|
||||
fileName: selection.source.name,
|
||||
source: {
|
||||
kind: 'onepkg',
|
||||
sessionId: response.sessionId,
|
||||
@@ -373,7 +374,7 @@ export function OneNoteApplication({
|
||||
return (
|
||||
<main className="application">
|
||||
{state.phase === 'idle' ? (
|
||||
<FileDropZone onFile={(file) => void openFile(file)} />
|
||||
<FileDropZone onFiles={(files) => void openFiles(files)} />
|
||||
) : null}
|
||||
|
||||
{state.phase === 'reading' ? (
|
||||
|
||||
Reference in New Issue
Block a user