feat: export parser sessions from the browser
This commit is contained in:
62
src/App.tsx
62
src/App.tsx
@@ -3,6 +3,10 @@ import { AppShell } from '@add-ideas/toolbox-shell-react';
|
||||
import '@add-ideas/toolbox-shell-react/styles.css';
|
||||
|
||||
import { DiagnosticsPanel } from './components/DiagnosticsPanel.js';
|
||||
import {
|
||||
ExportControls,
|
||||
type OneNoteExportFormat,
|
||||
} from './components/ExportControls.js';
|
||||
import { FileDropZone } from './components/FileDropZone.js';
|
||||
import { HelpDialog } from './components/HelpDialog.js';
|
||||
import { PackageInspector } from './components/PackageInspector.js';
|
||||
@@ -337,21 +341,39 @@ export function OneNoteApplication({
|
||||
suggestedName ??
|
||||
`onenote-resource.${resource.extension ?? 'bin'}`
|
||||
);
|
||||
const url = URL.createObjectURL(
|
||||
new Blob([resource.bytes], { type: resource.mediaType })
|
||||
);
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = url;
|
||||
anchor.download = filename;
|
||||
anchor.rel = 'noopener';
|
||||
document.body.append(anchor);
|
||||
anchor.click();
|
||||
anchor.remove();
|
||||
window.setTimeout(() => URL.revokeObjectURL(url), 1_000);
|
||||
downloadBrowserFile(resource.bytes, resource.mediaType, filename);
|
||||
},
|
||||
[loadSelectedResource]
|
||||
);
|
||||
|
||||
const exportLoadedSource = useCallback(
|
||||
async (format: OneNoteExportFormat): Promise<void> => {
|
||||
const client = activeClient.current;
|
||||
if (!client || state.phase !== 'loaded') {
|
||||
throw new WorkerClientError(
|
||||
'session-not-available',
|
||||
'The local parser session is no longer available.'
|
||||
);
|
||||
}
|
||||
const response = await client.exportSession(
|
||||
state.source.sessionId,
|
||||
format
|
||||
);
|
||||
if (response.type === 'failure') {
|
||||
throw new WorkerClientError(
|
||||
response.error.code,
|
||||
response.error.message
|
||||
);
|
||||
}
|
||||
downloadBrowserFile(
|
||||
response.artifact.bytes,
|
||||
response.artifact.mediaType,
|
||||
safeDownloadFilename(response.artifact.filename)
|
||||
);
|
||||
},
|
||||
[state]
|
||||
);
|
||||
|
||||
const visibleDiagnostics = uniqueDiagnostics(
|
||||
(() => {
|
||||
if (state.phase !== 'loaded') return [];
|
||||
@@ -409,6 +431,8 @@ export function OneNoteApplication({
|
||||
<PackageInspector notebook={state.source.notebook} />
|
||||
) : null}
|
||||
|
||||
<ExportControls onExport={exportLoadedSource} />
|
||||
|
||||
<div className="reader-workspace">
|
||||
{state.source.kind === 'one' ? (
|
||||
<SingleSectionNavigation
|
||||
@@ -486,6 +510,22 @@ function safeDownloadFilename(value: string): string {
|
||||
return (cleaned || 'onenote-resource.bin').slice(0, 180);
|
||||
}
|
||||
|
||||
function downloadBrowserFile(
|
||||
bytes: ArrayBuffer,
|
||||
mediaType: string,
|
||||
filename: string
|
||||
): void {
|
||||
const url = URL.createObjectURL(new Blob([bytes], { type: mediaType }));
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = url;
|
||||
anchor.download = filename;
|
||||
anchor.rel = 'noopener';
|
||||
document.body.append(anchor);
|
||||
anchor.click();
|
||||
anchor.remove();
|
||||
window.setTimeout(() => URL.revokeObjectURL(url), 1_000);
|
||||
}
|
||||
|
||||
export function App() {
|
||||
const [helpOpen, setHelpOpen] = useState(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user