Files
solelog/apps/mobile/index.web.tsx
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

128 lines
3.5 KiB
TypeScript

import '@expo/metro-runtime';
import { toPng } from 'html-to-image';
import React, { useEffect } from 'react';
import { renderRootComponent } from 'expo-router/build/renderRootComponent';
import { LoadSkiaWeb } from '@shopify/react-native-skia/lib/module/web';
import CreateApp from './App';
async function inlineGoogleFonts(): Promise<void> {
// Find all <link> elements that load Google Fonts CSS
const links = Array.from(document.querySelectorAll<HTMLLinkElement>(
'link[rel="stylesheet"][href*="fonts.googleapis.com"]'
));
for (const link of links) {
try {
const href = link.href;
const res = await fetch(href);
let cssText = await res.text();
// Ensure font URLs are absolute
cssText = cssText.replace(/url\(([^)]+)\)/g, (match, url) => {
const clean = url.replace(/["']/g, "");
if (clean.startsWith("http")) {
return `url(${clean})`;
}
return `url(${new URL(clean, href).toString()})`;
});
// Inject <style> with the CSS
const style = document.createElement("style");
style.textContent = cssText;
document.head.appendChild(style);
} catch {
}
}
// Wait for all fonts to actually load
if ("fonts" in document) {
await document.fonts.ready;
}
}
const waitForScreenshotReady = async () => {
const images = Array.from(document.images);
await Promise.all([
inlineGoogleFonts(),
...images.map(
(img) =>
new Promise((resolve) => {
img.crossOrigin = "anonymous";
if (img.complete) {
resolve(true);
return;
}
img.onload = () => resolve(true);
img.onerror = () => resolve(true);
})
)
]);
// small buffer to ensure rendering is stable
await new Promise((resolve) => setTimeout(resolve, 250));
};
export const useHandleScreenshotRequest = () => {
useEffect(() => {
const handleMessage = async (event: MessageEvent) => {
if (event.data.type === "sandbox:web:screenshot:request") {
try {
await waitForScreenshotReady();
const width = window.innerWidth;
const height = window.innerHeight;
const app = document.querySelector<HTMLElement>('#root')
if (!app) {
throw new Error("Could not find app element");
}
const dataUrl = await toPng(app, {
cacheBust: true,
skipFonts: false,
width,
height,
style: {
width: `${width}px`,
height: `${height}px`,
margin: "0",
},
});
window.parent.postMessage(
{ type: "sandbox:web:screenshot:response", dataUrl },
"*"
);
} catch (error) {
window.parent.postMessage(
{
type: "sandbox:web:screenshot:error",
error: error instanceof Error ? error.message : String(error),
},
"*"
);
}
}
};
const listener = (event: MessageEvent) => { void handleMessage(event); };
window.addEventListener("message", listener);
return () => {
window.removeEventListener("message", listener);
};
}, []);
};
const CreateAppWithFonts = () => {
useHandleScreenshotRequest();
return <CreateApp />;
}
LoadSkiaWeb({
locateFile: (file: string) => `/${file}`,
}).then(async () => {
renderRootComponent(CreateAppWithFonts)
}).catch(() => {
renderRootComponent(CreateAppWithFonts)
});