diff --git a/src/workspaces/officerdev/src/apps/ChatHistory/DirPickerModal.tsx b/src/workspaces/officerdev/src/apps/ChatHistory/DirPickerModal.tsx index 01b92e60..37432966 100644 --- a/src/workspaces/officerdev/src/apps/ChatHistory/DirPickerModal.tsx +++ b/src/workspaces/officerdev/src/apps/ChatHistory/DirPickerModal.tsx @@ -8,12 +8,14 @@ type DirPickerModalProps = { open: boolean; onClose: () => void; onSelect: (absPath: string) => void; + /** Whose filesystem to browse. Absent = this origin. */ + serverId?: string | null; }; // A simplified file-browser modal for picking a working directory (returns an absolute path). // Navigates within the home root; dirs elsewhere are reachable via the selector's free-text field. -export const DirPickerModal = ({ open, onClose, onSelect }: DirPickerModalProps) => { - const api = useFilesAPI('home'); +export const DirPickerModal = ({ open, onClose, onSelect, serverId }: DirPickerModalProps) => { + const api = useFilesAPI('home', serverId); const [path, setPath] = useState('/'); // root-relative, always starts with '/' const [creating, setCreating] = useState(false); const [newName, setNewName] = useState(''); @@ -23,7 +25,9 @@ export const DirPickerModal = ({ open, onClose, onSelect }: DirPickerModalProps) const [showHidden, setShowHidden] = useState(false); const { data, isLoading, refetch } = useQuery({ - queryKey: ['dir-picker', path], + // Server in the key: two machines have different trees, and without it one machine's folders + // are served from cache under the other's name. + queryKey: ['dir-picker', path, serverId ?? null], queryFn: () => api.listDir(path), enabled: open, }); diff --git a/src/workspaces/officerdev/src/apps/ChatHistory/PwdSelector.tsx b/src/workspaces/officerdev/src/apps/ChatHistory/PwdSelector.tsx index 4748faa0..6799cf22 100644 --- a/src/workspaces/officerdev/src/apps/ChatHistory/PwdSelector.tsx +++ b/src/workspaces/officerdev/src/apps/ChatHistory/PwdSelector.tsx @@ -6,14 +6,16 @@ import { DirPickerModal } from './DirPickerModal'; type PwdSelectorProps = { value: string | null; // null = the default general_chat_sessions dir onChange: (cwd: string | null) => void; + /** Which Officer's directories to offer. Absent = this origin. */ + serverId?: string | null; }; // A shorter, friendlier label for a working directory. const shorten = (cwd: string) => cwd.replace(/^\/home\/[^/]+/, '~'); const basename = (cwd: string) => cwd.split('/').filter(Boolean).pop() ?? cwd; -export const PwdSelector = ({ value, onChange }: PwdSelectorProps) => { - const { pwds, defaultCwd } = useChatPwds(); +export const PwdSelector = ({ value, onChange, serverId }: PwdSelectorProps) => { + const { pwds, defaultCwd } = useChatPwds(serverId); const [open, setOpen] = useState(false); const [browse, setBrowse] = useState(false); const [custom, setCustom] = useState(''); @@ -96,7 +98,7 @@ export const PwdSelector = ({ value, onChange }: PwdSelectorProps) => { )} - setBrowse(false)} onSelect={(p) => pick(p)} /> + setBrowse(false)} onSelect={(p) => pick(p)} serverId={serverId} /> ); }; diff --git a/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx b/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx index 75157bf2..99629874 100644 --- a/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx +++ b/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx @@ -95,6 +95,7 @@ export const SessionList = () => { }} /> { setSelected(null); // sessions belong to a cwd — clear the open one when switching diff --git a/src/workspaces/officerdev/src/hooks/useFilesAPI.ts b/src/workspaces/officerdev/src/hooks/useFilesAPI.ts index a5f9ea03..e5b9df0b 100644 --- a/src/workspaces/officerdev/src/hooks/useFilesAPI.ts +++ b/src/workspaces/officerdev/src/hooks/useFilesAPI.ts @@ -1,9 +1,17 @@ import { useClient, getHeaders } from 'hooks/useClient'; +import { useServerClient } from 'hooks/useServerClient'; const API_URL = '/api'; -export const useFilesAPI = (root: string = 'home') => { - const client = useClient(); +/** + * `serverId` names another Officer; absent is this origin, which is every existing caller. + * + * Load-bearing for the chat directory pickers: a path only means something on the machine it came from, + * so browsing without it showed THIS server's folders while the pane was pointed at another — the exact + * bug the mobile app has with `browseDirectories`. + */ +export const useFilesAPI = (root: string = 'home', serverId?: string | null) => { + const client = useServerClient(serverId); const rootParam = root !== 'home' ? `root=${encodeURIComponent(root)}` : ''; const withRoot = (url: string) => rootParam ? (url.includes('?') ? `${url}&${rootParam}` : `${url}?${rootParam}`) : url;