feat(companion): initial rn port scaffold

This commit is contained in:
2026-01-11 18:10:27 +00:00
parent 22fbfb9790
commit 8873c372f0
38 changed files with 3179 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
import { Ionicons } from "@expo/vector-icons";
import { Tabs } from "expo-router";
const iconSize = 22;
export default function TabLayout() {
return (
<Tabs screenOptions={{ headerShown: false }}>
<Tabs.Screen
name="index"
options={{
title: "BLE",
tabBarLabel: "BLE",
tabBarIcon: ({ color, focused }) => (
<Ionicons
color={color}
name={focused ? "bluetooth" : "bluetooth-outline"}
size={iconSize}
/>
),
}}
/>
<Tabs.Screen
name="orchestrator"
options={{
title: "Orchestrator",
tabBarLabel: "Orchestrator",
tabBarIcon: ({ color, focused }) => (
<Ionicons
color={color}
name={focused ? "flash" : "flash-outline"}
size={iconSize}
/>
),
}}
/>
<Tabs.Screen
name="todos"
options={{
title: "Todos",
tabBarLabel: "Todos",
tabBarIcon: ({ color, focused }) => (
<Ionicons
color={color}
name={focused ? "checkmark-done" : "checkmark-done-outline"}
size={iconSize}
/>
),
}}
/>
<Tabs.Screen
name="stocks"
options={{
title: "Stocks",
tabBarLabel: "Stocks",
tabBarIcon: ({ color, focused }) => (
<Ionicons
color={color}
name={focused ? "stats-chart" : "stats-chart-outline"}
size={iconSize}
/>
),
}}
/>
<Tabs.Screen
name="settings"
options={{
title: "Settings",
tabBarLabel: "Settings",
tabBarIcon: ({ color, focused }) => (
<Ionicons
color={color}
name={focused ? "settings" : "settings-outline"}
size={iconSize}
/>
),
}}
/>
</Tabs>
);
}

22
aris/app/(tabs)/index.tsx Normal file
View File

@@ -0,0 +1,22 @@
import { View } from "react-native";
import { Container } from "@/components/Container";
import { Text } from "@/components/ui/text";
export default function BleScreen() {
return (
<View className={styles.container}>
<Container>
<Text variant="h3">BLE</Text>
<Text className={styles.subtitle}>
Port of SwiftUI BleStatusView will live here.
</Text>
</Container>
</View>
);
}
const styles = {
container: "flex flex-1 bg-white",
subtitle: "mt-2 text-sm text-muted-foreground",
};

View File

@@ -0,0 +1,22 @@
import { View } from "react-native";
import { Container } from "@/components/Container";
import { Text } from "@/components/ui/text";
export default function OrchestratorScreen() {
return (
<View className={styles.container}>
<Container>
<Text variant="h3">Orchestrator</Text>
<Text className={styles.subtitle}>
Port of SwiftUI OrchestratorView will live here.
</Text>
</Container>
</View>
);
}
const styles = {
container: "flex flex-1 bg-white",
subtitle: "mt-2 text-sm text-muted-foreground",
};

View File

@@ -0,0 +1,22 @@
import { View } from "react-native";
import { Container } from "@/components/Container";
import { Text } from "@/components/ui/text";
export default function SettingsScreen() {
return (
<View className={styles.container}>
<Container>
<Text variant="h3">Settings</Text>
<Text className={styles.subtitle}>
Port of SwiftUI SettingsView will live here.
</Text>
</Container>
</View>
);
}
const styles = {
container: "flex flex-1 bg-white",
subtitle: "mt-2 text-sm text-muted-foreground",
};

View File

@@ -0,0 +1,22 @@
import { View } from "react-native";
import { Container } from "@/components/Container";
import { Text } from "@/components/ui/text";
export default function StocksScreen() {
return (
<View className={styles.container}>
<Container>
<Text variant="h3">Stocks</Text>
<Text className={styles.subtitle}>
Port of SwiftUI StockSettingsView will live here.
</Text>
</Container>
</View>
);
}
const styles = {
container: "flex flex-1 bg-white",
subtitle: "mt-2 text-sm text-muted-foreground",
};

22
aris/app/(tabs)/todos.tsx Normal file
View File

@@ -0,0 +1,22 @@
import { View } from "react-native";
import { Container } from "@/components/Container";
import { Text } from "@/components/ui/text";
export default function TodosScreen() {
return (
<View className={styles.container}>
<Container>
<Text variant="h3">Todos</Text>
<Text className={styles.subtitle}>
Port of SwiftUI TodosView will live here.
</Text>
</Container>
</View>
);
}
const styles = {
container: "flex flex-1 bg-white",
subtitle: "mt-2 text-sm text-muted-foreground",
};

46
aris/app/+html.tsx Normal file
View File

@@ -0,0 +1,46 @@
import { ScrollViewStyleReset } from 'expo-router/html';
// This file is web-only and used to configure the root HTML for every
// web page during static rendering.
// The contents of this function only run in Node.js environments and
// do not have access to the DOM or browser APIs.
export default function Root({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
{/*
This viewport disables scaling which makes the mobile website act more like a native app.
However this does reduce built-in accessibility. If you want to enable scaling, use this instead:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
*/}
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1.00001,viewport-fit=cover"
/>
{/*
Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
*/}
<ScrollViewStyleReset />
{/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */}
<style dangerouslySetInnerHTML={{ __html: responsiveBackground }} />
{/* Add any additional <head> elements that you want globally available on web... */}
</head>
<body>{children}</body>
</html>
);
}
const responsiveBackground = `
body {
background-color: #fff;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #000;
}
}`;

26
aris/app/+not-found.tsx Normal file
View File

@@ -0,0 +1,26 @@
import { Link, Stack } from 'expo-router';
import { Text, View } from 'react-native';
import { Container } from '@/components/Container';
export default function NotFoundScreen() {
return (
<View className={styles.container}>
<Stack.Screen options={{ title: 'Oops!' }} />
<Container>
<Text className={styles.title}>{"This screen doesn't exist."}</Text>
<Link href="/" className={styles.link}>
<Text className={styles.linkText}>Go to home screen!</Text>
</Link>
</Container>
</View>
);
}
const styles = {
container: `flex flex-1 bg-white`,
title: `text-xl font-bold`,
link: `mt-4 pt-4`,
linkText: `text-base text-[#2e78b7]`,
};

15
aris/app/_layout.tsx Normal file
View File

@@ -0,0 +1,15 @@
import "../global.css";
import { Stack } from "expo-router";
import { PortalHost } from "@rn-primitives/portal";
export default function Layout() {
return (
<>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
<PortalHost />
</>
);
}

23
aris/app/details.tsx Normal file
View File

@@ -0,0 +1,23 @@
import { View } from 'react-native';
import { Stack, useLocalSearchParams } from 'expo-router';
import { Container } from '@/components/Container';
import { ScreenContent } from '@/components/ScreenContent';
export default function Details() {
const { name } = useLocalSearchParams();
return (
<View className={styles.container}>
<Stack.Screen options={{ title: 'Details' }} />
<Container>
<ScreenContent path="screens/details.tsx" title={`Showing details for user ${name}`} />
</Container>
</View>
);
}
const styles = {
container: 'flex flex-1 bg-white',
};