| 1 | import { Stack, router } from "expo-router"; |
| 2 | import { Hash } from "lucide-react-native"; |
| 3 | import { FlatList, RefreshControl } from "react-native"; |
| 4 | |
| 5 | import { Badge, Button, Empty, ErrorView, Loading, Row, Screen } from "@/components/ui"; |
| 6 | import { useBrowseChannels, useChatSidebar, useStartConversation } from "@/lib/chat"; |
| 7 | import { useColors } from "@/theme"; |
| 8 | |
| 9 | /** The workspace's public channels: open one you are in, or join one you are not. */ |
| 10 | export default function Browse() { |
| 11 | const channels = useBrowseChannels(); |
| 12 | const sidebar = useChatSidebar(); |
| 13 | const { join } = useStartConversation(); |
| 14 | const colors = useColors(); |
| 15 | const mine = new Set((sidebar.data?.entries ?? []).map((entry) => entry.channel.id)); |
| 16 | |
| 17 | return ( |
| 18 | <Screen> |
| 19 | <Stack.Screen options={{ title: "Browse channels" }} /> |
| 20 | {channels.isPending ? ( |
| 21 | <Loading /> |
| 22 | ) : channels.error ? ( |
| 23 | <ErrorView error={channels.error} retry={() => channels.refetch()} /> |
| 24 | ) : ( |
| 25 | <FlatList |
| 26 | data={channels.data} |
| 27 | keyExtractor={(channel) => channel.id} |
| 28 | refreshControl={<RefreshControl refreshing={channels.isRefetching} onRefresh={() => channels.refetch()} tintColor={colors.accent} />} |
| 29 | ListEmptyComponent={<Empty icon={Hash} title="No other channels" />} |
| 30 | renderItem={({ item }) => { |
| 31 | const joined = mine.has(item.id); |
| 32 | const open = () => router.replace({ pathname: "/chat/[channel]", params: { channel: item.id } }); |
| 33 | return ( |
| 34 | <Row |
| 35 | leading={<Hash size={20} color={colors.muted} />} |
| 36 | title={item.name ?? ""} |
| 37 | subtitle={item.topic ?? undefined} |
| 38 | chevron={false} |
| 39 | onPress={joined ? open : undefined} |
| 40 | trailing={ |
| 41 | joined ? ( |
| 42 | <Badge label="Joined" /> |
| 43 | ) : ( |
| 44 | <Button |
| 45 | title="Join" |
| 46 | variant="secondary" |
| 47 | busy={join.isPending && join.variables === item.id} |
| 48 | onPress={() => join.mutate(item.id, { onSuccess: open })} |
| 49 | /> |
| 50 | ) |
| 51 | } |
| 52 | /> |
| 53 | ); |
| 54 | }} |
| 55 | /> |
| 56 | )} |
| 57 | </Screen> |
| 58 | ); |
| 59 | } |