Implement Dokio screens from the design doc (turns 3 + 4)
Scaffold an Expo + TypeScript app for Dokio, the app that scans Behördenpost and explains it in plain language, and build the four screens specified in "Dokio Design.dc.html": 4a Onboarding, full-bleed dither gradient 4b Home, dithered scan card 3a Kamera, mocked viewfinder 3b Archiv, search + filters + month groups Design tokens from the turn 4 blue palette live in src/theme.ts. Content is mocked in src/data/letters.ts, taken verbatim from the doc. DitherBackground is a GLSL port of the doc's dither-bg.js, which drew a low-resolution canvas and upscaled it with image-rendering: pixelated; the fragment shader snaps to the same grid instead. Two notes on the port: - The original's fract(sin(x) * 43758.5453) hash only distributes well in float64. A fragment shader's highp float has ~24 mantissa bits, so it collapsed to a near-constant field and the gradient bands rendered straight rather than warped. Replaced with Hoskins' hash, verified against the original running side by side. - The 4x4 Bayer matrix is built recursively rather than as a lookup, which avoids dynamic array indexing; the construction reproduces all 16 entries of the original exactly. The camera screen deliberately stops short of expo-camera: the viewfinder is a static stand-in, so the flow is navigable without permissions. The 2a result screen is not part of turns 3 and 4 and is not included. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
42
app/_layout.tsx
Normal file
42
app/_layout.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { BricolageGrotesque_800ExtraBold } from '@expo-google-fonts/bricolage-grotesque';
|
||||
import {
|
||||
NunitoSans_400Regular,
|
||||
NunitoSans_600SemiBold,
|
||||
NunitoSans_700Bold,
|
||||
NunitoSans_800ExtraBold,
|
||||
} from '@expo-google-fonts/nunito-sans';
|
||||
import { useFonts } from 'expo-font';
|
||||
import { Stack } from 'expo-router';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { ActivityIndicator, View } from 'react-native';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { colors } from '../src/theme';
|
||||
|
||||
export default function RootLayout() {
|
||||
const [fontsLoaded] = useFonts({
|
||||
BricolageGrotesque_800ExtraBold,
|
||||
NunitoSans_400Regular,
|
||||
NunitoSans_600SemiBold,
|
||||
NunitoSans_700Bold,
|
||||
NunitoSans_800ExtraBold,
|
||||
});
|
||||
|
||||
if (!fontsLoaded) {
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: colors.canvas, justifyContent: 'center' }}>
|
||||
<ActivityIndicator color={colors.blue} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaProvider>
|
||||
<StatusBar style="auto" />
|
||||
<Stack screenOptions={{ headerShown: false, contentStyle: { backgroundColor: colors.canvas } }}>
|
||||
<Stack.Screen name="onboarding" />
|
||||
<Stack.Screen name="(tabs)" />
|
||||
<Stack.Screen name="scan" options={{ presentation: 'fullScreenModal', animation: 'fade' }} />
|
||||
</Stack>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user