Complete rewrite of Scry using TypeScript stack:
- Expo/React Native with Expo Router (file-based routing)
- Convex backend (serverless functions + real-time database)
- Adaptive camera system (expo-camera in Expo Go, Vision Camera in production)
- React Native Skia + fast-opencv for image processing
- GDPR-compliant auth setup with Zitadel OIDC (pending configuration)
Key features:
- Card recognition pipeline ported to TypeScript
- Perceptual hashing (192-bit color pHash)
- CLAHE preprocessing for lighting normalization
- Local SQLite cache with Convex sync
- Collection management with offline support
Removes all .NET/MAUI code (src/, test/, tools/).
💘 Generated with Crush
Assisted-by: Claude Opus 4.5 via Crush <crush@charm.land>
72 lines
1.7 KiB
TypeScript
72 lines
1.7 KiB
TypeScript
import React, { useEffect } from "react";
|
|
import FontAwesome from "@expo/vector-icons/FontAwesome";
|
|
import { useFonts } from "expo-font";
|
|
import * as SplashScreen from "expo-splash-screen";
|
|
import { Stack } from "expo-router";
|
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
import { HashCacheProvider } from "@/lib/context";
|
|
import { useColorScheme } from "@/components/useColorScheme";
|
|
|
|
// Initialize Convex client
|
|
const convex = new ConvexReactClient(
|
|
process.env.EXPO_PUBLIC_CONVEX_URL as string
|
|
);
|
|
|
|
// Keep splash screen visible while loading fonts
|
|
SplashScreen.preventAutoHideAsync();
|
|
|
|
export default function RootLayout() {
|
|
const [loaded, error] = useFonts({
|
|
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
|
|
...FontAwesome.font,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (error) throw error;
|
|
}, [error]);
|
|
|
|
useEffect(() => {
|
|
if (loaded) {
|
|
SplashScreen.hideAsync();
|
|
}
|
|
}, [loaded]);
|
|
|
|
if (!loaded) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<ConvexProvider client={convex}>
|
|
<HashCacheProvider>
|
|
<RootLayoutNav />
|
|
</HashCacheProvider>
|
|
</ConvexProvider>
|
|
);
|
|
}
|
|
|
|
function RootLayoutNav() {
|
|
const colorScheme = useColorScheme();
|
|
|
|
return (
|
|
<Stack
|
|
screenOptions={{
|
|
headerStyle: {
|
|
backgroundColor: colorScheme === "dark" ? "#1a1a1a" : "#fff",
|
|
},
|
|
headerTintColor: colorScheme === "dark" ? "#fff" : "#000",
|
|
contentStyle: {
|
|
backgroundColor: colorScheme === "dark" ? "#1a1a1a" : "#fff",
|
|
},
|
|
}}
|
|
>
|
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
<Stack.Screen
|
|
name="modal"
|
|
options={{
|
|
presentation: "modal",
|
|
title: "Card Details",
|
|
}}
|
|
/>
|
|
</Stack>
|
|
);
|
|
}
|