Rename sidebar to LeftSidebar and hide empty filters
This commit is contained in:
@@ -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 />
|
||||||
|
|||||||
+2
-2
@@ -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}
|
||||||
|
|||||||
Reference in New Issue
Block a user