Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| The phone app's scaffolding, in apps/mobile: Expo SDK 57 with Expo Router, Android first, with Chat, Code and Customize. It signs in with g1t's own OAuth 2.1 (PKCE, a client id that encodes "g1t for Android" and g1t://oauth/callback, so nothing is registered), keeps the server and credentials in the phone's keystore, refreshes the 30-day token a minute early and shares the single-use refresh between requests. A personal access token is the other way in, and a self-hosted g1t the other server. | 1 | import { Tabs, useGlobalSearchParams } from "expo-router"; |
| 2 | import { Blocks, CircleUser, Code2, MessagesSquare } from "lucide-react-native"; | |
| 3 | import { useEffect } from "react"; | |
| 4 | ||
| 5 | import { useSignedIn } from "@/lib/session"; | |
| 6 | import { useColors } from "@/theme"; | |
| 7 | ||
| 8 | /** | |
| 9 | * The signed-in app: Chat, Code, Customize and You, as the site's phone | |
| 10 | * layout has its bottom bar (apps/web/app/components/mobile.tsx). Home, | |
| 11 | * Notifications, Agents and Artifacts join as they get screens. | |
| 12 | */ | |
| 13 | export default function AppLayout() { | |
| 14 | const colors = useColors(); | |
| 15 | const { workspace, selectWorkspace } = useSignedIn(); | |
| 16 | // A link names its workspace (`/chat?workspace=acme`, lib/links.ts): switch to it. | |
| 17 | const { workspace: linked } = useGlobalSearchParams<{ workspace?: string }>(); | |
| 18 | useEffect(() => { | |
| 19 | if (linked && linked.toLowerCase() !== workspace?.slug.toLowerCase()) void selectWorkspace(linked); | |
| 20 | }, [linked, workspace?.slug, selectWorkspace]); | |
| 21 | ||
| 22 | return ( | |
| 23 | <Tabs | |
| 24 | screenOptions={{ | |
| 25 | headerShown: false, | |
| 26 | tabBarActiveTintColor: colors.accent, | |
| 27 | tabBarInactiveTintColor: colors.muted, | |
| 28 | tabBarStyle: { backgroundColor: colors.surface, borderTopColor: colors.line }, | |
| 29 | }} | |
| 30 | > | |
| 31 | <Tabs.Screen name="index" options={{ href: null }} /> | |
| 32 | <Tabs.Screen name="chat" options={{ title: "Chat", tabBarIcon: ({ color, size }) => <MessagesSquare color={color} size={size} /> }} /> | |
| 33 | <Tabs.Screen name="code" options={{ title: "Code", tabBarIcon: ({ color, size }) => <Code2 color={color} size={size} /> }} /> | |
| 34 | <Tabs.Screen name="customize" options={{ title: "Customize", tabBarIcon: ({ color, size }) => <Blocks color={color} size={size} /> }} /> | |
| 35 | <Tabs.Screen name="you" options={{ title: "You", tabBarIcon: ({ color, size }) => <CircleUser color={color} size={size} /> }} /> | |
| 36 | </Tabs> | |
| 37 | ); | |
| 38 | } |