Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at eli/oatproxy-panic 187 lines 5.2 kB view raw
1import { DrawerNavigationOptions } from "@react-navigation/drawer"; 2import { DrawerDescriptorMap } from "@react-navigation/drawer/lib/typescript/src/types"; 3import { 4 CommonActions, 5 DrawerNavigationState, 6 ParamListBase, 7 useNavigation, 8} from "@react-navigation/native"; 9import { Text, zero } from "@streamplace/components"; 10import React from "react"; 11import { Image, Platform, View } from "react-native"; 12import Animated, { 13 SharedValue, 14 useAnimatedStyle, 15} from "react-native-reanimated"; 16import SidebarItem from "./sidebar-item"; 17 18export interface ExternalDrawerItem { 19 item: 20 | React.ComponentType<any> 21 | React.ReactElement 22 | (() => React.ReactElement); 23 label: React.ComponentType<any> | React.ReactElement | string; 24 onPress: () => void; 25} 26 27interface CustomSidebarProps { 28 collapsed: boolean; 29 hidden: boolean; 30 widthAnim: SharedValue<number>; 31 descriptors: DrawerDescriptorMap; 32 state: DrawerNavigationState<ParamListBase>; 33 externalItems?: ExternalDrawerItem[]; 34} 35 36// Combine standard drawer props with custom props 37type SidebarProps = CustomSidebarProps & DrawerNavigationOptions; 38 39export default function Sidebar({ 40 state, 41 descriptors, 42 collapsed, 43 hidden, 44 widthAnim, 45 externalItems = [], 46}: SidebarProps) { 47 const navigation = useNavigation(); 48 const animatedSidebarStyle = useAnimatedStyle(() => { 49 return { 50 minWidth: widthAnim.value, 51 maxWidth: widthAnim.value, 52 }; 53 }); 54 55 if (hidden) { 56 return <View />; 57 } 58 59 return ( 60 <Animated.View 61 style={[ 62 animatedSidebarStyle, 63 zero.p[2], 64 zero.gap.all[2], 65 zero.layout.flex.column, 66 ]} 67 > 68 <View 69 style={[ 70 zero.layout.flex.row, 71 zero.layout.flex.alignCenter, 72 zero.gap.all[3], 73 { 74 marginTop: Platform.OS === "ios" ? 29 : 8, 75 marginBottom: 20, 76 paddingLeft: 11, 77 }, 78 ]} 79 > 80 <Image 81 source={require("../../assets/images/cube.png")} 82 height={30} 83 width={28} 84 style={{ width: 28, height: 30, resizeMode: "contain" }} 85 /> 86 {!collapsed && <Text size="2xl">Streamplace</Text>} 87 </View> 88 89 {state.routes.map((route) => { 90 const descriptor = descriptors[route.key]; 91 const options = descriptor?.options ?? {}; 92 93 const label = 94 typeof options.drawerLabel === "function" 95 ? options.drawerLabel({ focused: false, color: "$color" }) 96 : (options.drawerLabel ?? options.title ?? route.name); 97 98 const IconComponent = options.drawerIcon as 99 | React.ComponentType<any> 100 | undefined; 101 102 // if we have style display: none on the drawer item, completely skip rendering it 103 const drawerItemStyle = options.drawerItemStyle; 104 let isHidden = false; 105 if ( 106 drawerItemStyle && 107 typeof drawerItemStyle === "object" && 108 "display" in drawerItemStyle && 109 (drawerItemStyle as any).display === "none" 110 ) { 111 isHidden = true; 112 } 113 if (isHidden) { 114 return null; 115 } 116 117 return ( 118 <SidebarItem 119 key={route.key} 120 icon={IconComponent ? IconComponent : () => <Text>📄</Text>} 121 label={label} 122 active={descriptor.navigation.isFocused()} 123 collapsed={collapsed} 124 route={route} 125 onPress={(ev) => { 126 ev.preventDefault(); 127 if (route.name === "Home") { 128 // reset the stack (b/c streamlist is in the same stack as home) 129 navigation.dispatch( 130 CommonActions.reset({ 131 index: 0, 132 routes: [ 133 { 134 name: "Home", 135 state: { 136 routes: [{ name: "StreamList" }], 137 }, 138 }, 139 ], 140 }), 141 ); 142 } else { 143 navigation.navigate(route.name as any); 144 } 145 }} 146 style={options.drawerItemStyle} 147 tint={options.drawerActiveTintColor as string} 148 /> 149 ); 150 })} 151 {externalItems.map((i, num) => { 152 // Handle different label types - string, JSX element, or component 153 const renderLabel = () => { 154 if (typeof i.label === "string") { 155 return i.label; 156 } 157 158 // If it's already a JSX element, return it directly 159 if (React.isValidElement(i.label)) { 160 return i.label; 161 } 162 163 // If it's a function (component), call it 164 if (typeof i.label === "function") { 165 const LabelComponent = i.label; 166 return <LabelComponent />; 167 } 168 169 // Fallback 170 return "Item"; 171 }; 172 173 return ( 174 <SidebarItem 175 key={num} 176 icon={i.item} 177 label={renderLabel()} 178 active={false} 179 collapsed={collapsed} 180 onPress={() => i.onPress()} 181 tint="rgba(189, 110, 134)" 182 /> 183 ); 184 })} 185 </Animated.View> 186 ); 187}