245 lines · 8.4 KB · TypeScript
RawDownload
import type {  EnvironmentId,  SidebarProjectGroupingMode,  SidebarThreadSortOrder,} from "@t3tools/contracts";import {  DEFAULT_SIDEBAR_PROJECT_GROUPING_MODE,  DEFAULT_SIDEBAR_PROJECT_SORT_ORDER,  DEFAULT_SIDEBAR_THREAD_SORT_ORDER,} from "@t3tools/contracts";import { Stack } from "expo-router";import { Text as RNText, View } from "react-native"; import { useThemeColor } from "../../lib/useThemeColor";import { MOBILE_TYPOGRAPHY } from "../../lib/typography";import type { HomeProjectSortOrder } from "./homeThreadList"; export interface HomeHeaderEnvironment {  readonly environmentId: EnvironmentId;  readonly label: string;} const PROJECT_SORT_OPTIONS: ReadonlyArray<{  readonly value: HomeProjectSortOrder;  readonly label: string;}> = [  { value: "updated_at", label: "Last user message" },  { value: "created_at", label: "Created at" },]; const THREAD_SORT_OPTIONS: ReadonlyArray<{  readonly value: SidebarThreadSortOrder;  readonly label: string;}> = [  { value: "updated_at", label: "Last user message" },  { value: "created_at", label: "Created at" },]; const PROJECT_GROUPING_OPTIONS: ReadonlyArray<{  readonly value: SidebarProjectGroupingMode;  readonly label: string;  readonly subtitle: string;}> = [  {    value: "repository",    label: "Group by repository",    subtitle: "Combine matching repositories across environments",  },  {    value: "repository_path",    label: "Group by repository path",    subtitle: "Combine only matching paths within a repository",  },  {    value: "separate",    label: "Keep separate",    subtitle: "Show every project path separately",  },]; export function HomeHeader(props: {  readonly environments: ReadonlyArray<HomeHeaderEnvironment>;  readonly selectedEnvironmentId: EnvironmentId | null;  readonly projectSortOrder: HomeProjectSortOrder;  readonly threadSortOrder: SidebarThreadSortOrder;  readonly projectGroupingMode: SidebarProjectGroupingMode;  readonly onSearchQueryChange: (query: string) => void;  readonly onEnvironmentChange: (environmentId: EnvironmentId | null) => void;  readonly onProjectSortOrderChange: (sortOrder: HomeProjectSortOrder) => void;  readonly onThreadSortOrderChange: (sortOrder: SidebarThreadSortOrder) => void;  readonly onProjectGroupingModeChange: (mode: SidebarProjectGroupingMode) => void;  readonly onOpenSettings: () => void;  readonly onStartNewTask: () => void;}) {  const iconColor = useThemeColor("--color-icon");  const mutedColor = useThemeColor("--color-foreground-muted");  const subtleColor = useThemeColor("--color-subtle");  const hasCustomListOptions =    props.selectedEnvironmentId !== null ||    props.projectSortOrder !== DEFAULT_SIDEBAR_PROJECT_SORT_ORDER ||    props.threadSortOrder !== DEFAULT_SIDEBAR_THREAD_SORT_ORDER ||    props.projectGroupingMode !== DEFAULT_SIDEBAR_PROJECT_GROUPING_MODE;   return (    <>      <Stack.Screen        options={{          headerShown: true,          headerTransparent: true,          headerStyle: { backgroundColor: "transparent" },          headerShadowVisible: false,          headerTintColor: iconColor,          headerTitle: "",          headerSearchBarOptions: {            placeholder: "Search threads",            hideNavigationBar: false,            onChangeText: (event) => {              props.onSearchQueryChange(event.nativeEvent.text);            },            onCancelButtonPress: () => {              props.onSearchQueryChange("");            },            allowToolbarIntegration: true,          },        }}      />       <Stack.Toolbar placement="left">        <Stack.Toolbar.View hidesSharedBackground>          <View            style={{              width: 128,              height: 32,              flexDirection: "row",              alignItems: "center",              gap: 8,            }}          >            <RNText              style={{                fontFamily: "DMSans_700Bold",                fontSize: MOBILE_TYPOGRAPHY.headline.fontSize,                color: iconColor,                letterSpacing: -0.4,              }}            >              T3 Code            </RNText>            <View              style={{                backgroundColor: subtleColor,                borderRadius: 99,                paddingHorizontal: 8,                paddingVertical: 3,              }}            >              <RNText                style={{                  fontFamily: "DMSans_700Bold",                  fontSize: MOBILE_TYPOGRAPHY.micro.fontSize,                  color: mutedColor,                  letterSpacing: 1.1,                  textTransform: "uppercase",                }}              >                Alpha              </RNText>            </View>          </View>        </Stack.Toolbar.View>      </Stack.Toolbar>       <Stack.Toolbar placement="right">        <Stack.Toolbar.Menu          accessibilityLabel="Filter and sort threads"          icon={            hasCustomListOptions              ? "line.3.horizontal.decrease.circle.fill"              : "line.3.horizontal.decrease.circle"          }          separateBackground          title="Thread list options"        >          <Stack.Toolbar.Menu title="Environment">            <Stack.Toolbar.Label>Environment</Stack.Toolbar.Label>            <Stack.Toolbar.MenuAction              isOn={props.selectedEnvironmentId === null}              onPress={() => props.onEnvironmentChange(null)}              subtitle="Show threads from every environment"            >              <Stack.Toolbar.Label>All environments</Stack.Toolbar.Label>            </Stack.Toolbar.MenuAction>            {props.environments.map((environment) => (              <Stack.Toolbar.MenuAction                key={environment.environmentId}                isOn={props.selectedEnvironmentId === environment.environmentId}                onPress={() => props.onEnvironmentChange(environment.environmentId)}              >                <Stack.Toolbar.Label>{environment.label}</Stack.Toolbar.Label>              </Stack.Toolbar.MenuAction>            ))}          </Stack.Toolbar.Menu>           <Stack.Toolbar.Menu title="Sort projects">            <Stack.Toolbar.Label>Sort projects</Stack.Toolbar.Label>            {PROJECT_SORT_OPTIONS.map((option) => (              <Stack.Toolbar.MenuAction                key={option.value}                isOn={props.projectSortOrder === option.value}                onPress={() => props.onProjectSortOrderChange(option.value)}              >                <Stack.Toolbar.Label>{option.label}</Stack.Toolbar.Label>              </Stack.Toolbar.MenuAction>            ))}          </Stack.Toolbar.Menu>           <Stack.Toolbar.Menu title="Sort threads">            <Stack.Toolbar.Label>Sort threads</Stack.Toolbar.Label>            {THREAD_SORT_OPTIONS.map((option) => (              <Stack.Toolbar.MenuAction                key={option.value}                isOn={props.threadSortOrder === option.value}                onPress={() => props.onThreadSortOrderChange(option.value)}              >                <Stack.Toolbar.Label>{option.label}</Stack.Toolbar.Label>              </Stack.Toolbar.MenuAction>            ))}          </Stack.Toolbar.Menu>           <Stack.Toolbar.Menu title="Group projects">            <Stack.Toolbar.Label>Group projects</Stack.Toolbar.Label>            {PROJECT_GROUPING_OPTIONS.map((option) => (              <Stack.Toolbar.MenuAction                key={option.value}                isOn={props.projectGroupingMode === option.value}                onPress={() => props.onProjectGroupingModeChange(option.value)}                subtitle={option.subtitle}              >                <Stack.Toolbar.Label>{option.label}</Stack.Toolbar.Label>              </Stack.Toolbar.MenuAction>            ))}          </Stack.Toolbar.Menu>        </Stack.Toolbar.Menu>         <Stack.Toolbar.Button          accessibilityLabel="Open settings"          icon="gearshape"          onPress={props.onOpenSettings}          separateBackground        />      </Stack.Toolbar>       <Stack.Toolbar placement="bottom">        <Stack.Toolbar.SearchBarSlot />        <Stack.Toolbar.Spacer width={8} sharesBackground={false} />        <Stack.Toolbar.Button          accessibilityLabel="New task"          icon="square.and.pencil"          onPress={props.onStartNewTask}          separateBackground        />      </Stack.Toolbar>    </>  );}