| 1 | import { hasCodeAccess } from "@g1t/contracts"; |
| 2 | import { Stack, router } from "expo-router"; |
| 3 | import { BookLock, BookMarked, Code2 } from "lucide-react-native"; |
| 4 | import { useState } from "react"; |
| 5 | import { FlatList, RefreshControl, View } from "react-native"; |
| 6 | |
| 7 | import { Badge, Empty, ErrorView, Field, Loading, Row, Screen } from "@/components/ui"; |
| 8 | import { useRepos } from "@/lib/code"; |
| 9 | import { useSignedIn } from "@/lib/session"; |
| 10 | import { ago } from "@/lib/time"; |
| 11 | import { space, useColors } from "@/theme"; |
| 12 | |
| 13 | /** Code: the workspace's repositories you can see, newest first. */ |
| 14 | export default function Repos() { |
| 15 | const { workspace } = useSignedIn(); |
| 16 | const [search, setSearch] = useState(""); |
| 17 | const repos = useRepos(search.trim()); |
| 18 | const colors = useColors(); |
| 19 | |
| 20 | if (workspace && !hasCodeAccess(workspace)) { |
| 21 | return ( |
| 22 | <Screen> |
| 23 | <Stack.Screen options={{ title: "Code" }} /> |
| 24 | <Empty icon={Code2} title="Code is not on for you here" body={`${workspace.name ?? workspace.slug} gives you Chat, Docs and agents. Ask an owner for Code.`} /> |
| 25 | </Screen> |
| 26 | ); |
| 27 | } |
| 28 | |
| 29 | return ( |
| 30 | <Screen> |
| 31 | <Stack.Screen options={{ title: "Code" }} /> |
| 32 | <View style={{ padding: space.lg, paddingBottom: space.sm }}> |
| 33 | <Field label="Find a repository" placeholder="Name or description" value={search} onChangeText={setSearch} returnKeyType="search" /> |
| 34 | </View> |
| 35 | {repos.isPending ? ( |
| 36 | <Loading /> |
| 37 | ) : repos.error ? ( |
| 38 | <ErrorView error={repos.error} retry={() => repos.refetch()} /> |
| 39 | ) : ( |
| 40 | <FlatList |
| 41 | data={repos.data} |
| 42 | keyExtractor={(repo) => repo.id} |
| 43 | refreshControl={<RefreshControl refreshing={repos.isRefetching} onRefresh={() => repos.refetch()} tintColor={colors.accent} />} |
| 44 | ListEmptyComponent={<Empty icon={BookMarked} title={search ? "Nothing matches" : "No repositories yet"} />} |
| 45 | renderItem={({ item }) => ( |
| 46 | <Row |
| 47 | leading={item.is_private ? <BookLock size={20} color={colors.muted} /> : <BookMarked size={20} color={colors.muted} />} |
| 48 | title={`${item.namespace}/${item.name}`} |
| 49 | subtitle={item.description ?? `Created ${ago(item.created_at)}`} |
| 50 | trailing={item.archived_at ? <Badge label="Archived" tone="warn" /> : null} |
| 51 | onPress={() => router.push({ pathname: "/code/[owner]/[repo]", params: { owner: item.namespace, repo: item.name } })} |
| 52 | /> |
| 53 | )} |
| 54 | /> |
| 55 | )} |
| 56 | </Screen> |
| 57 | ); |
| 58 | } |