fix(desktop): honor effective project profile scope
This commit is contained in:
@@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { NO_PROJECT_ID, type SidebarProjectTree } from '@/app/chat/sidebar/projects/workspace-groups'
|
||||
import { $sidebarAgentsGrouped, setSidebarAgentsGrouped } from '@/store/layout'
|
||||
import { $activeGatewayProfile, $profileScope, ALL_PROFILES, setShowAllProfiles } from '@/store/profile'
|
||||
import { $activeGatewayProfile, $profiles, $profileScope, ALL_PROFILES, setShowAllProfiles } from '@/store/profile'
|
||||
import { $currentCwd, $selectedStoredSessionId, $sessions, applyConfiguredDefaultProjectDir } from '@/store/session'
|
||||
import { deferred } from '@/test/deferred'
|
||||
import type { ProjectInfo } from '@/types/hermes'
|
||||
@@ -135,6 +135,7 @@ describe('projects RPC profile forwarding', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
$activeGatewayProfile.set('default')
|
||||
$profiles.set([{ is_default: true, name: 'default' } as never])
|
||||
$activeProjectId.set(null)
|
||||
$projectTree.set([])
|
||||
setShowAllProfiles(false)
|
||||
@@ -199,6 +200,7 @@ describe('projects RPC profile forwarding', () => {
|
||||
const gateway = { connectionState: 'open', request }
|
||||
activeGateway.mockReturnValue(gateway as never)
|
||||
gatewayAtom.set(gateway as never)
|
||||
$profiles.set([{ is_default: true, name: 'default' } as never, { is_default: false, name: 'work' } as never])
|
||||
setShowAllProfiles(true)
|
||||
|
||||
await refreshProjects()
|
||||
@@ -208,6 +210,32 @@ describe('projects RPC profile forwarding', () => {
|
||||
expect(request).not.toHaveBeenCalled()
|
||||
setShowAllProfiles(false)
|
||||
})
|
||||
|
||||
it('uses the active profile when a persisted all-profiles preference is hidden for one profile', async () => {
|
||||
const project = { id: 'p_123', label: 'P', path: null, repos: [], sessionCount: 0 } as SidebarProjectTree
|
||||
|
||||
const request = vi.fn(async (method: string) =>
|
||||
method === 'projects.project_sessions' ? { project } : { active_id: null, projects: [], scoped_session_ids: [] }
|
||||
)
|
||||
|
||||
const gateway = { connectionState: 'open', request }
|
||||
|
||||
activeGateway.mockReturnValue(gateway as never)
|
||||
gatewayAtom.set(gateway as never)
|
||||
setShowAllProfiles(true)
|
||||
|
||||
await refreshProjects()
|
||||
await refreshProjectTree()
|
||||
await expect(fetchProjectSessions('p_123')).resolves.toBe(project)
|
||||
|
||||
expect(request).toHaveBeenNthCalledWith(1, 'projects.list', { profile: 'default' })
|
||||
expect(request).toHaveBeenNthCalledWith(2, 'projects.tree', { preview_limit: 3, profile: 'default' })
|
||||
expect(request).toHaveBeenNthCalledWith(3, 'projects.project_sessions', {
|
||||
profile: 'default',
|
||||
project_id: 'p_123'
|
||||
})
|
||||
setShowAllProfiles(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveNewSessionCwd', () => {
|
||||
@@ -425,6 +453,7 @@ describe('createProject', () => {
|
||||
$projects.set([])
|
||||
$projectTree.set([])
|
||||
$activeGatewayProfile.set('default')
|
||||
$profiles.set([{ is_default: true, name: 'default' } as never, { is_default: false, name: 'work' } as never])
|
||||
setShowAllProfiles(false)
|
||||
})
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import { $sidebarShowAllSessions, setSidebarAgentsGrouped } from '@/store/layout
|
||||
import { notify } from '@/store/notifications'
|
||||
import {
|
||||
$activeGatewayProfile,
|
||||
$profiles,
|
||||
$profileScope,
|
||||
ALL_PROFILES,
|
||||
normalizeProfileKey,
|
||||
@@ -304,10 +305,14 @@ async function gatewayRequest<T>(method: string, params: Record<string, unknown>
|
||||
return gateway.request<T>(method, params)
|
||||
}
|
||||
|
||||
function viewingAllProfiles(): boolean {
|
||||
return $profileScope.get() === ALL_PROFILES && $profiles.get().length > 1
|
||||
}
|
||||
|
||||
export function projectProfile(): null | string {
|
||||
const profile = normalizeProfileKey($activeGatewayProfile.get())
|
||||
|
||||
return $profileScope.get() === ALL_PROFILES || profile === ALL_PROFILES ? null : profile
|
||||
return viewingAllProfiles() || profile === ALL_PROFILES ? null : profile
|
||||
}
|
||||
|
||||
// All profiles filters the sidebar. Writes still belong to the live gateway profile.
|
||||
@@ -561,7 +566,7 @@ async function refreshProjectTreeOn(context: ActiveProjectsContext): Promise<voi
|
||||
// sessions + the scoped-session-id set). Best-effort: a failure leaves the
|
||||
// cached tree intact so the sidebar doesn't flicker.
|
||||
export async function refreshProjectTree(): Promise<void> {
|
||||
if ($profileScope.get() === ALL_PROFILES) {
|
||||
if (viewingAllProfiles()) {
|
||||
await refreshProjectTreeAcrossProfiles()
|
||||
|
||||
return
|
||||
@@ -593,7 +598,7 @@ async function refreshProjectTreeAcrossProfiles(): Promise<void> {
|
||||
// scope; the newer refresh owns the tree.
|
||||
if (
|
||||
generation !== projectTreeRefreshGeneration ||
|
||||
$profileScope.get() !== ALL_PROFILES ||
|
||||
!viewingAllProfiles() ||
|
||||
activeGatewayConnectionId() !== owner.connectionId
|
||||
) {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user