| 1 | import type { |
| 2 | NativeStackHeaderItem, |
| 3 | NativeStackHeaderItemMenu, |
| 4 | } from "@react-navigation/native-stack"; |
| 5 | |
| 6 | import type { HomeListFilterMenu } from "../home/home-list-filter-menu"; |
| 7 | import { withNativeGlassHeaderItem } from "../layout/native-glass-header-items"; |
| 8 | |
| 9 | type NativeHeaderMenuItems = NativeStackHeaderItemMenu["menu"]["items"]; |
| 10 | type NativeHeaderIcon = NonNullable<Extract<NativeStackHeaderItem, { type: "button" }>["icon"]>; |
| 11 | |
| 12 | function sfSymbolIcon(name: string): NativeHeaderIcon { |
| 13 | return { type: "sfSymbol", name: name as never }; |
| 14 | } |
| 15 | |
| 16 | function toNativeHeaderMenuItems(items: HomeListFilterMenu["items"]): NativeHeaderMenuItems { |
| 17 | return items.map((item) => |
| 18 | item.type === "action" |
| 19 | ? { |
| 20 | type: "action" as const, |
| 21 | label: item.title, |
| 22 | description: item.subtitle, |
| 23 | onPress: item.onPress, |
| 24 | state: item.state === "on" ? ("on" as const) : undefined, |
| 25 | } |
| 26 | : { |
| 27 | type: "submenu" as const, |
| 28 | label: item.title, |
| 29 | items: toNativeHeaderMenuItems(item.items), |
| 30 | }, |
| 31 | ); |
| 32 | } |
| 33 | |
| 34 | /** |
| 35 | * Right-side UINavigationBar items for the sidebar column: the thread list |
| 36 | * filter/sort menu plus the settings button, sharing one glass capsule — |
| 37 | * the Messages-style grouped header buttons. The embedded sidebar keeps these |
| 38 | * beside its title; only the detail column uses the Duo's vertical bar. |
| 39 | */ |
| 40 | export function createSidebarHeaderItems(input: { |
| 41 | readonly filterIcon: string; |
| 42 | readonly filterMenu: HomeListFilterMenu; |
| 43 | readonly onOpenSettings: () => void; |
| 44 | }): NativeStackHeaderItem[] { |
| 45 | return [ |
| 46 | withNativeGlassHeaderItem({ |
| 47 | type: "menu", |
| 48 | axisBehavior: "horizontalOnly", |
| 49 | label: "", |
| 50 | accessibilityLabel: "Filter threads", |
| 51 | icon: sfSymbolIcon(input.filterIcon), |
| 52 | menu: { |
| 53 | title: input.filterMenu.title, |
| 54 | items: toNativeHeaderMenuItems(input.filterMenu.items), |
| 55 | }, |
| 56 | }), |
| 57 | withNativeGlassHeaderItem({ |
| 58 | type: "button", |
| 59 | axisBehavior: "horizontalOnly", |
| 60 | label: "Settings", |
| 61 | accessibilityLabel: "Open settings", |
| 62 | icon: sfSymbolIcon("gearshape"), |
| 63 | onPress: input.onOpenSettings, |
| 64 | }), |
| 65 | ]; |
| 66 | } |