Skip to content
Source
Sign inSign up
Open History to see the last commit

PullRequestToolbar.android.tsx

87 lines3.3 KB

1import { useNavigation } from "@react-navigation/native";
2import { useEffect } from "react";
3import { BackHandler, Keyboard } from "react-native";
4import { AppBar } from "../../../components/ui/AppBar";
5import { appBarMenuItemsFromActions } from "../../../components/ui/menuActionItems";
6import { useHardwareKeyboardCommand } from "../../keyboard/hardwareKeyboardCommands";
7import { WorkspaceBrandTitle } from "./WorkspaceBrandTitle";
8import { useWorkspaceTabs } from "./WorkspaceTabsContext";
9import type { PullRequestFilterMenu } from "../../pull-requests/PullRequestListFilters";
10import { openSettings } from "../../settings/settings-navigation";
11​
12/** PR search shares the thread list's Android header. */
13export function PullRequestToolbar(props: {
14 readonly filters: PullRequestFilterMenu | null;
15 readonly onRequestVisibility?: () => void;
16}) {
17 const navigation = useNavigation();
18 const { filters } = props;
19 const workspace = useWorkspaceTabs()!;
20 const { dispatch, getScrollOffset, recordScrollOffset, isTabActive } = workspace;
21 const { onRequestVisibility } = props;
22 const tab = workspace.state.tabs.pullRequests;
23 const searching = tab.searchMode !== "resting";
24 const openSearch = () => {
25 onRequestVisibility?.();
26 dispatch({
27 type: "scroll",
28 tab: "pullRequests",
29 offset: getScrollOffset("pullRequests"),
30 });
31 dispatch({ type: "search", tab: "pullRequests" });
32 return true;
33 };
34 useHardwareKeyboardCommand("focusSearch", openSearch);
35 const closeSearch = () => {
36 Keyboard.dismiss();
37 recordScrollOffset("pullRequests", tab.searchEntryOffset);
38 dispatch({ type: "cancel", tab: "pullRequests" });
39 };
40 // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- subscribes to BackHandler while searching to close the PR search on Android back
41 useEffect(() => {
42 if (!searching) return;
43 const subscription = BackHandler.addEventListener("hardwareBackPress", () => {
44 // Frozen Home screens stay mounted under a detail route or another tab,
45 // so back only applies while the PR list is in front.
46 const state = navigation.getState();
47 if (!state || state.routes[state.index]?.name !== "Home" || !isTabActive("pullRequests"))
48 return false;
49 if (Keyboard.isVisible()) Keyboard.dismiss();
50 else closeSearch();
51 return true;
52 });
53 return () => subscription.remove();
54 }, [searching, closeSearch, navigation, isTabActive]);
55 return (
56 <AppBar
57 title="T3 Code"
58 titleContent={
59 <WorkspaceBrandTitle
60 accessibilityLabel="T3 Code, Pull requests"
61 onOpenEnvironments={() => openSettings(navigation, "SettingsEnvironments")}
62 />
63 }
64 search={{
65 value: tab.query,
66 onChangeText: (query) => dispatch({ type: "query", tab: "pullRequests", query }),
67 placeholder: "Search pull requests",
68 active: searching,
69 onOpen: openSearch,
70 onClose: closeSearch,
71 }}
72 menus={
73 filters
74 ? [
75 {
76 title: "Filter pull requests",
77 icon: filters.customized
78 ? "line.3.horizontal.decrease.circle.fill"
79 : "line.3.horizontal.decrease.circle",
80 items: appBarMenuItemsFromActions(filters.actions, filters.onSelect),
81 },
82 ]
83 : undefined
84 }
85 />
86 );