Files
solelog/apps/mobile/polyfills/web/documentPicker.web.ts
Bas van Rossem d94d0b188b Initial commit: code as received (Create/Anything export)
Insole-production time tracker exported from the Create/Anything AI
platform. Baseline snapshot before any reverse-engineering or cleanup.

- apps/mobile: Expo Router app (iOS/Android/web), the only workspace
- publisher/: standalone OpenNext/AWS deploy tooling for the web side
- Backend (/api/tasks, /api/logs + DB) lives remotely, not in this repo
2026-06-17 10:19:33 +02:00

95 lines
2.2 KiB
TypeScript

interface DocumentPickerAsset {
name: string;
size: number | null;
uri: string;
mimeType: string | null;
}
interface DocumentPickerResult {
canceled: boolean;
assets: DocumentPickerAsset[];
output: null;
}
interface DocumentPickerOptions {
type?: string | string[];
copyToCacheDirectory?: boolean;
multiple?: boolean;
}
export async function getDocumentAsync(
options?: DocumentPickerOptions
): Promise<DocumentPickerResult> {
return new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
input.multiple = options?.multiple ?? false;
if (options?.type) {
const types = Array.isArray(options.type)
? options.type
: [options.type];
const filtered = types.filter((t) => t !== '*/*');
if (filtered.length > 0) {
input.accept = filtered.join(',');
}
}
input.style.display = 'none';
document.body.appendChild(input);
let resolved = false;
const cleanup = () => {
if (!resolved) {
resolved = true;
document.body.removeChild(input);
}
};
input.addEventListener('change', () => {
const files = input.files;
if (!files || files.length === 0) {
cleanup();
resolve({ canceled: true, assets: [], output: null });
return;
}
const promises = Array.from(files).map(
(file) =>
new Promise<DocumentPickerAsset>((resolveAsset) => {
const reader = new FileReader();
reader.onload = () => {
resolveAsset({
name: file.name,
size: file.size,
uri: reader.result as string,
mimeType: file.type || null,
});
};
reader.readAsDataURL(file);
})
);
void Promise.all(promises).then((assets) => {
cleanup();
resolve({ canceled: false, assets, output: null });
});
});
window.addEventListener(
'focus',
() => {
setTimeout(() => {
if (!resolved) {
cleanup();
resolve({ canceled: true, assets: [], output: null });
}
}, 300);
},
{ once: true }
);
input.click();
});
}