From b66116280d8bdf3c112fe6dc985fbaba1c92dc0b Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Tue, 8 Sep 2026 00:54:34 -0700 Subject: [PATCH] Hide empty Filters section in activity options menu - Extract visibility logic into reusable hook `useActivityScopeFilterMenuItemsVisible` to avoid duplication - Only render Filters label and items when filters are available, preventing empty section in dropdown - Improves UX by not showing unused menu sections --- .../activity-scope-filter-controls.tsx | 22 +++++- .../activity/activity-thread-options-menu.tsx | 70 +++++++++++-------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/renderer/src/components/activity/activity-scope-filter-controls.tsx b/src/renderer/src/components/activity/activity-scope-filter-controls.tsx index 7aa229bc267..e90ec1f3322 100644 --- a/src/renderer/src/components/activity/activity-scope-filter-controls.tsx +++ b/src/renderer/src/components/activity/activity-scope-filter-controls.tsx @@ -10,6 +10,24 @@ import { } from '@/components/sidebar/sidebar-host-options' import { useSidebarHostScopeOptions } from '@/components/sidebar/use-sidebar-host-scope-options' +/** + * Whether {@link ActivityScopeFilterMenuItems} renders anything. + * Why exported: the parent owns the Filters label and separator, so it has to + * know whether the section would be empty. + */ +export function useActivityScopeFilterMenuItemsVisible(): boolean { + const repos = useAppStore((s) => s.repos) + const agentsVisibleHostIds = useAppStore((s) => s.agentsVisibleHostIds) + const agentsFilterRepoIds = useAppStore((s) => s.agentsFilterRepoIds) + const { hostOptions } = useSidebarHostScopeOptions() + return ( + agentsVisibleHostIds !== null || + agentsFilterRepoIds.length > 0 || + shouldShowHostScopeControls(hostOptions) || + repos.length > 1 + ) +} + /** * Host/project scope items for the Agents activity surfaces. State is the * persisted agents-view scope (agentsVisibleHostIds / agentsFilterRepoIds), @@ -17,7 +35,6 @@ import { useSidebarHostScopeOptions } from '@/components/sidebar/use-sidebar-hos * Filters label and separator. */ export function ActivityScopeFilterMenuItems(): React.JSX.Element | null { - const repos = useAppStore((s) => s.repos) const agentsVisibleHostIds = useAppStore((s) => s.agentsVisibleHostIds) const setAgentsVisibleHostIds = useAppStore((s) => s.setAgentsVisibleHostIds) const agentsFilterRepoIds = useAppStore((s) => s.agentsFilterRepoIds) @@ -25,8 +42,9 @@ export function ActivityScopeFilterMenuItems(): React.JSX.Element | null { const { hostOptions } = useSidebarHostScopeOptions() const showHostScopeControls = shouldShowHostScopeControls(hostOptions) const hasScopeFilter = agentsVisibleHostIds !== null || agentsFilterRepoIds.length > 0 + const visible = useActivityScopeFilterMenuItemsVisible() - if (!hasScopeFilter && !showHostScopeControls && repos.length <= 1) { + if (!visible) { return null } diff --git a/src/renderer/src/components/activity/activity-thread-options-menu.tsx b/src/renderer/src/components/activity/activity-thread-options-menu.tsx index ad8ae349ca3..5a9bd3bc59c 100644 --- a/src/renderer/src/components/activity/activity-thread-options-menu.tsx +++ b/src/renderer/src/components/activity/activity-thread-options-menu.tsx @@ -19,7 +19,8 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip import { translate } from '@/i18n/i18n' import { ActivityScopeFilterMenuItems, - useActivityScopeFilterActive + useActivityScopeFilterActive, + useActivityScopeFilterMenuItemsVisible } from './activity-scope-filter-controls' import type { ActivityGroupBy } from './activity-thread-types' @@ -79,6 +80,10 @@ export function ActivityThreadOptionsMenu({ }): React.JSX.Element { const skipCloseAutoFocusRef = React.useRef(false) const scopeFilterActive = useActivityScopeFilterActive() + const scopeFilterItemsVisible = useActivityScopeFilterMenuItemsVisible() + const hasFilters = Boolean( + onUnreadOnlyChange || onShowChildAgentsChange || scopeFilterItemsVisible + ) const optionsLabel = scopeFilterActive ? translate( 'auto.components.activity.ActivityPrototypePage.threadListOptionsFiltered', @@ -131,35 +136,42 @@ export function ActivityThreadOptionsMenu({ } }} > - - {translate('auto.components.activity.ActivityPrototypePage.filtersSection', 'Filters')} - - {onUnreadOnlyChange ? ( - onUnreadOnlyChange(checked === true)} - onSelect={(event) => event.preventDefault()} - > - {translate( - 'auto.components.activity.ActivityPrototypePage.showUnreadOnly', - 'Show unread only' - )} - + {hasFilters ? ( + <> + + {translate( + 'auto.components.activity.ActivityPrototypePage.filtersSection', + 'Filters' + )} + + {onUnreadOnlyChange ? ( + onUnreadOnlyChange(checked === true)} + onSelect={(event) => event.preventDefault()} + > + {translate( + 'auto.components.activity.ActivityPrototypePage.showUnreadOnly', + 'Show unread only' + )} + + ) : null} + {onShowChildAgentsChange ? ( + onShowChildAgentsChange(checked === true)} + onSelect={(event) => event.preventDefault()} + > + {translate( + 'auto.components.activity.ActivityPrototypePage.showChildAgents', + 'Show child agents' + )} + + ) : null} + + + ) : null} - {onShowChildAgentsChange ? ( - onShowChildAgentsChange(checked === true)} - onSelect={(event) => event.preventDefault()} - > - {translate( - 'auto.components.activity.ActivityPrototypePage.showChildAgents', - 'Show child agents' - )} - - ) : null} - - {translate('auto.components.activity.ActivityPrototypePage.viewSection', 'View')}