()
| 197 | })); |
| 198 | |
| 199 | export function SessionsList() { |
| 200 | const styles = stylesheet; |
| 201 | const safeArea = useSafeAreaInsets(); |
| 202 | const data = useVisibleSessionListViewData(); |
| 203 | const pathname = usePathname(); |
| 204 | const isTablet = useIsTablet(); |
| 205 | const [hideInactiveSessions, setHideInactiveSessions] = useSettingMutable('hideInactiveSessions'); |
| 206 | const toggleArchived = React.useCallback(() => { |
| 207 | setHideInactiveSessions(!hideInactiveSessions); |
| 208 | }, [hideInactiveSessions, setHideInactiveSessions]); |
| 209 | // Selection is derived once from pathname so the data array stays stable |
| 210 | // across navigations. This keeps FlatList virtualization intact: only |
| 211 | // the previously- and newly-selected rows re-render, instead of the |
| 212 | // whole visible window. |
| 213 | const selectedSessionId = React.useMemo<string | undefined>(() => { |
| 214 | if (!isTablet) return undefined; |
| 215 | if (!pathname.startsWith('/session/')) return undefined; |
| 216 | return pathname.split('/')[2]; |
| 217 | }, [isTablet, pathname]); |
| 218 | |
| 219 | // Request review |
| 220 | React.useEffect(() => { |
| 221 | if (data && data.length > 0) { |
| 222 | requestReview(); |
| 223 | } |
| 224 | }, [data && data.length > 0]); |
| 225 | |
| 226 | // Early return if no data yet |
| 227 | if (!data) { |
| 228 | return ( |
| 229 | <View style={styles.container} /> |
| 230 | ); |
| 231 | } |
| 232 | |
| 233 | const keyExtractor = React.useCallback((item: SessionListViewItem, index: number) => { |
| 234 | switch (item.type) { |
| 235 | case 'header': return `header-${item.title}-${index}`; |
| 236 | case 'active-sessions': return 'active-sessions'; |
| 237 | case 'archive-toggle': return 'archive-toggle'; |
| 238 | case 'project-group': return `project-group-${item.machine.id}-${item.displayPath}-${index}`; |
| 239 | case 'session': return `session-${item.session.id}`; |
| 240 | } |
| 241 | }, []); |
| 242 | |
| 243 | const renderItem = React.useCallback(({ item, index }: { item: SessionListViewItem, index: number }) => { |
| 244 | switch (item.type) { |
| 245 | case 'header': |
| 246 | return ( |
| 247 | <View style={styles.headerSection}> |
| 248 | <Text style={styles.headerText}> |
| 249 | {item.title} |
| 250 | </Text> |
| 251 | </View> |
| 252 | ); |
| 253 | |
| 254 | case 'archive-toggle': |
| 255 | return ( |
| 256 | <Pressable style={styles.archiveToggle} onPress={toggleArchived}> |
nothing calls this directly
no test coverage detected