feat: improve project directory picker

Adds command-palette style project browsing
Keeps native Finder picker as optional desktop action
Supports disabled existing projects and create-and-add paths
This commit is contained in:
Bohdan Triapitsyn
2026-04-27 15:45:14 +03:00
parent 54a09914ac
commit c83986cd94
14 changed files with 642 additions and 412 deletions
@@ -38,8 +38,6 @@ import { CSS } from '@dnd-kit/utilities';
import type { SessionContextUsage } from '@/stores/types/sessionTypes';
import { PROJECT_ICON_MAP, PROJECT_COLOR_MAP, getProjectIconImageUrl } from '@/lib/projectMeta';
import { useDirectoryStore } from '@/stores/useDirectoryStore';
import { toast } from '@/components/ui';
import { isTauriShell, isDesktopLocalOriginActive, requestDirectoryAccess } from '@/lib/desktop';
import { sessionEvents } from '@/lib/sessionEvents';
import {
Dialog,
@@ -1450,7 +1448,6 @@ export const MobileSessionStatusBar: React.FC<MobileSessionStatusBarProps> = ({
const projects = useProjectsStore((state) => state.projects);
const activeProjectId = useProjectsStore((state) => state.activeProjectId);
const setActiveProject = useProjectsStore((state) => state.setActiveProject);
const addProject = useProjectsStore((state) => state.addProject);
const removeProject = useProjectsStore((state) => state.removeProject);
const getActiveProject = useProjectsStore((state) => state.getActiveProject);
@@ -1492,7 +1489,6 @@ export const MobileSessionStatusBar: React.FC<MobileSessionStatusBarProps> = ({
const contextUsage = getContextUsage(contextLimit, outputLimit);
const [isExpanded, setIsExpanded] = React.useState(false);
const tauriIpcAvailable = React.useMemo(() => isTauriShell(), []);
if (!isMobile || !showMobileSessionStatusBar || totalCount === 0) {
return null;
@@ -1520,29 +1516,7 @@ export const MobileSessionStatusBar: React.FC<MobileSessionStatusBarProps> = ({
};
const handleAddProject = () => {
if (!tauriIpcAvailable || !isDesktopLocalOriginActive()) {
sessionEvents.requestDirectoryDialog();
return;
}
requestDirectoryAccess('')
.then((result) => {
if (result.success && result.path) {
const added = addProject(result.path, { id: result.projectId });
if (!added) {
toast.error(t('chat.mobileStatus.toast.addProjectFailed'), {
description: t('chat.mobileStatus.toast.selectValidDirectory'),
});
}
} else if (result.error && result.error !== 'Directory selection cancelled') {
toast.error(t('chat.mobileStatus.toast.selectDirectoryFailed'), {
description: result.error,
});
}
})
.catch((error) => {
console.error('Failed to select directory:', error);
toast.error(t('chat.mobileStatus.toast.selectDirectoryFailed'));
});
sessionEvents.requestDirectoryDialog();
};
if (isMobileSessionStatusBarCollapsed) {