Migrate from .NET MAUI to Expo + Convex
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>
This commit is contained in:
parent
56499d5af9
commit
83ab4df537
138 changed files with 19136 additions and 7681 deletions
72
app/_layout.tsx
Normal file
72
app/_layout.tsx
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
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>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue