Rename sidebar to LeftSidebar and hide empty filters

This commit is contained in:
Mohamed Boudra
2026-02-19 12:57:23 +07:00
parent 8d379a6215
commit fb6b5ca886
3 changed files with 97 additions and 94 deletions
+3 -3
View File
@@ -20,7 +20,7 @@ import { useState, useEffect, type ReactNode, useMemo, useRef } from "react";
import { Platform } from "react-native"; import { Platform } from "react-native";
import * as Linking from "expo-linking"; import * as Linking from "expo-linking";
import * as Notifications from "expo-notifications"; import * as Notifications from "expo-notifications";
import { SlidingSidebar } from "@/components/sliding-sidebar"; import { LeftSidebar } from "@/components/left-sidebar";
import { DownloadToast } from "@/components/download-toast"; import { DownloadToast } from "@/components/download-toast";
import { ToastProvider } from "@/contexts/toast-context"; import { ToastProvider } from "@/contexts/toast-context";
import { usePanelStore } from "@/stores/panel-store"; import { usePanelStore } from "@/stores/panel-store";
@@ -282,12 +282,12 @@ function AppContainer({ children, selectedAgentId }: AppContainerProps) {
const content = ( const content = (
<View style={{ flex: 1, backgroundColor: theme.colors.surface0 }}> <View style={{ flex: 1, backgroundColor: theme.colors.surface0 }}>
<View style={{ flex: 1, flexDirection: "row" }}> <View style={{ flex: 1, flexDirection: "row" }}>
{!isMobile && chromeEnabled && <SlidingSidebar selectedAgentId={selectedAgentId} />} {!isMobile && chromeEnabled && <LeftSidebar selectedAgentId={selectedAgentId} />}
<View style={{ flex: 1, paddingLeft: needsTrafficLightPadding ? trafficLightPadding.left : 0 }}> <View style={{ flex: 1, paddingLeft: needsTrafficLightPadding ? trafficLightPadding.left : 0 }}>
{children} {children}
</View> </View>
</View> </View>
{isMobile && chromeEnabled && <SlidingSidebar selectedAgentId={selectedAgentId} />} {isMobile && chromeEnabled && <LeftSidebar selectedAgentId={selectedAgentId} />}
<DownloadToast /> <DownloadToast />
<CommandCenter /> <CommandCenter />
<KeyboardShortcutsDialog /> <KeyboardShortcutsDialog />
@@ -43,11 +43,11 @@ import {
const DESKTOP_SIDEBAR_WIDTH = 320; const DESKTOP_SIDEBAR_WIDTH = 320;
interface SlidingSidebarProps { interface LeftSidebarProps {
selectedAgentId?: string; selectedAgentId?: string;
} }
export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) { export function LeftSidebar({ selectedAgentId }: LeftSidebarProps) {
const { theme } = useUnistyles(); const { theme } = useUnistyles();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const isMobile = const isMobile =
@@ -488,6 +488,7 @@ export function SidebarAgentList({
projectOptions.find((option) => option.projectKey === selectedProjectKeys[0]) ?? null projectOptions.find((option) => option.projectKey === selectedProjectKeys[0]) ?? null
); );
}, [projectOptions, selectedProjectKeys]); }, [projectOptions, selectedProjectKeys]);
const showProjectFilters = projectOptions.length > 0;
const sessions = useSessionStore((state) => state.sessions); const sessions = useSessionStore((state) => state.sessions);
const projectIconRequests = useMemo(() => { const projectIconRequests = useMemo(() => {
@@ -745,98 +746,100 @@ export function SidebarAgentList({
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.filtersRow}> {showProjectFilters ? (
<Pressable <View style={styles.filtersRow}>
ref={projectFilterAnchorRef} <Pressable
style={({ hovered = false, pressed }) => [ ref={projectFilterAnchorRef}
styles.filterTrigger, style={({ hovered = false, pressed }) => [
(selectedProjectKeys.length > 0 || hovered || pressed) && styles.filterTrigger,
styles.filterTriggerActive, (selectedProjectKeys.length > 0 || hovered || pressed) &&
]} styles.filterTriggerActive,
onPress={() => setIsProjectFilterOpen(true)} ]}
> onPress={() => setIsProjectFilterOpen(true)}
{({ hovered = false, pressed }) => { >
const isInteracting = hovered || pressed; {({ hovered = false, pressed }) => {
const showActiveForeground = const isInteracting = hovered || pressed;
selectedProjectKeys.length > 0 || isInteracting; const showActiveForeground =
return ( selectedProjectKeys.length > 0 || isInteracting;
<> return (
{selectedProjectKeys.length === 1 && selectedProjectIconUri ? ( <>
<Image {selectedProjectKeys.length === 1 && selectedProjectIconUri ? (
source={{ <Image
uri: selectedProjectIconUri, source={{
}} uri: selectedProjectIconUri,
style={styles.selectedProjectIcon} }}
style={styles.selectedProjectIcon}
/>
) : selectedProjectKeys.length > 1 ? (
<View style={styles.projectCountBadge}>
<Text style={styles.projectCountBadgeText}>
{selectedProjectKeys.length}
</Text>
</View>
) : null}
<Text
style={[
styles.filterTriggerText,
!showActiveForeground && styles.filterTriggerTextMuted,
]}
numberOfLines={1}
>
{selectedProjectLabel}
</Text>
<ChevronDown
size={theme.iconSize.sm}
color={
showActiveForeground
? theme.colors.foreground
: theme.colors.foregroundMuted
}
/> />
) : selectedProjectKeys.length > 1 ? ( </>
<View style={styles.projectCountBadge}> );
<Text style={styles.projectCountBadgeText}> }}
{selectedProjectKeys.length}
</Text>
</View>
) : null}
<Text
style={[
styles.filterTriggerText,
!showActiveForeground && styles.filterTriggerTextMuted,
]}
numberOfLines={1}
>
{selectedProjectLabel}
</Text>
<ChevronDown
size={theme.iconSize.sm}
color={
showActiveForeground
? theme.colors.foreground
: theme.colors.foregroundMuted
}
/>
</>
);
}}
</Pressable>
{selectedProjectKeys.length > 0 ? (
<Pressable style={styles.clearFilterButton} onPress={handleClearProjectFilter}>
<Text style={styles.clearFilterText}>Clear</Text>
</Pressable> </Pressable>
) : null}
<Combobox {selectedProjectKeys.length > 0 ? (
options={[]} <Pressable style={styles.clearFilterButton} onPress={handleClearProjectFilter}>
value="" <Text style={styles.clearFilterText}>Clear</Text>
onSelect={() => {}} </Pressable>
title="Filter by project" ) : null}
placeholder="Search projects"
searchPlaceholder="Search projects" <Combobox
desktopPlacement="bottom-start" options={[]}
open={isProjectFilterOpen} value=""
onOpenChange={setIsProjectFilterOpen} onSelect={() => {}}
anchorRef={projectFilterAnchorRef} title="Filter by project"
> placeholder="Search projects"
<View style={styles.filterOptionsList}> searchPlaceholder="Search projects"
{projectOptions.length === 0 ? ( desktopPlacement="bottom-start"
<Text style={styles.filterEmptyText}>No projects</Text> open={isProjectFilterOpen}
) : ( onOpenChange={setIsProjectFilterOpen}
projectOptions.map((option) => ( anchorRef={projectFilterAnchorRef}
<ProjectFilterOptionRow >
key={option.projectKey} <View style={styles.filterOptionsList}>
option={option} {projectOptions.length === 0 ? (
selected={selectedProjectKeys.includes(option.projectKey)} <Text style={styles.filterEmptyText}>No projects</Text>
iconDataUri={projectIconByProjectKey.get(option.projectKey) ?? null} ) : (
displayName={deriveProjectDisplayName({ projectOptions.map((option) => (
projectKey: option.projectKey, <ProjectFilterOptionRow
projectName: option.projectName, key={option.projectKey}
remoteUrl: null, option={option}
})} selected={selectedProjectKeys.includes(option.projectKey)}
onToggle={handleToggleProject} iconDataUri={projectIconByProjectKey.get(option.projectKey) ?? null}
/> displayName={deriveProjectDisplayName({
)) projectKey: option.projectKey,
)} projectName: option.projectName,
</View> remoteUrl: null,
</Combobox> })}
</View> onToggle={handleToggleProject}
/>
))
)}
</View>
</Combobox>
</View>
) : null}
<DraggableList <DraggableList
data={entries} data={entries}