feat(sidebar): add missed upload files dialog

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-07-24 15:09:54 -07:00
parent 1c8a15dfab
commit 389337da0b
3 changed files with 63 additions and 5 deletions

View file

@ -26,3 +26,10 @@ export const localExpandedFolderKeysAtom = atomWithStorage<Record<number, string
* null means no folder is being renamed.
*/
export const renamingFolderIdAtom = atom<number | null>(null);
/**
* Bumped whenever a folder is (un)watched outside DocumentsSidebar (e.g. the
* sidebar-footer "Watch Local Folder" button) so the tree re-reads Electron's
* watched-folder list and shows the sync badge without a reload.
*/
export const watchedFoldersRefreshAtom = atom(0);

View file

@ -17,7 +17,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { makeFolderMention, mentionedDocumentsAtom } from "@/atoms/chat/mentioned-documents.atom";
import { deleteDocumentMutationAtom } from "@/atoms/documents/document-mutation.atoms";
import { expandedFolderIdsAtom } from "@/atoms/documents/folder.atoms";
import { expandedFolderIdsAtom, watchedFoldersRefreshAtom } from "@/atoms/documents/folder.atoms";
import { agentCreatedDocumentsAtom } from "@/atoms/documents/ui.atoms";
import { openEditorPanelAtom } from "@/atoms/editor/editor-panel.atom";
import { CreateFolderDialog } from "@/components/documents/CreateFolderDialog";
@ -401,9 +401,12 @@ function AuthenticatedDocumentsSidebarBase({
setWatchedFolderIds(ids);
}, [workspaceId, electronAPI]);
// Re-runs when the sidebar-footer "Watch Local Folder" dialog bumps the atom.
const watchedFoldersRefreshTick = useAtomValue(watchedFoldersRefreshAtom);
useEffect(() => {
void watchedFoldersRefreshTick;
refreshWatchedIds();
}, [refreshWatchedIds]);
}, [refreshWatchedIds, watchedFoldersRefreshTick]);
const { mutateAsync: deleteDocumentMutation } = useAtomValue(deleteDocumentMutationAtom);
const [sidebarDocs, setSidebarDocs] = useAtom(mentionedDocumentsAtom);

View file

@ -1,16 +1,22 @@
"use client";
import { CreditCard, MessageCircleMore, SquarePen, Zap } from "lucide-react";
import { useSetAtom } from "jotai";
import { CreditCard, FolderSync, MessageCircleMore, SquarePen, Upload, Zap } from "lucide-react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { useTranslations } from "next-intl";
import { type ReactNode, useMemo, useState } from "react";
import { watchedFoldersRefreshAtom } from "@/atoms/documents/folder.atoms";
import { useDocumentUploadDialog } from "@/components/assistant-ui/document-upload-popup";
import { ConnectAgentDialog } from "@/components/mcp/connect-agent-dialog";
import { FolderWatchDialog } from "@/components/sources/FolderWatchDialog";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { Skeleton } from "@/components/ui/skeleton";
import { useIsAnonymous } from "@/contexts/anonymous-mode";
import { getWorkspaceIdParam } from "@/lib/route-params";
import { useLoginGate } from "@/contexts/login-gate";
import { usePlatform } from "@/hooks/use-platform";
import { getWorkspaceIdNumber, getWorkspaceIdParam } from "@/lib/route-params";
import { cn } from "@/lib/utils";
import { SIDEBAR_MIN_WIDTH } from "../../hooks/useSidebarResize";
import type { ChatItem, NavItem, PageUsage, User, Workspace } from "../../types/layout.types";
@ -355,7 +361,8 @@ export function Sidebar({
)}
{!isCollapsed && (
<div className="shrink-0 py-1.5">
<div className="flex shrink-0 flex-col gap-0.5 py-1.5">
<SidebarImportActions />
<ConnectAgentDialog className="w-[calc(100%-1rem)]" />
</div>
)}
@ -384,6 +391,47 @@ export function Sidebar({
);
}
/**
* Sidebar-footer import actions rendered above "Connect your agent":
* "Watch Local Folder" (desktop app only) and "Upload Files". Both reuse the
* existing dialogs; in anonymous mode they open the login gate instead.
*/
function SidebarImportActions() {
const params = useParams();
const workspaceId = getWorkspaceIdNumber(params) ?? 0;
const { isDesktop } = usePlatform();
const isAnonymous = useIsAnonymous();
const { gate } = useLoginGate();
const { openDialog: openUploadDialog } = useDocumentUploadDialog();
const [folderWatchOpen, setFolderWatchOpen] = useState(false);
const bumpWatchedFoldersRefresh = useSetAtom(watchedFoldersRefreshAtom);
return (
<>
{isDesktop && (
<SidebarButton
icon={FolderSync}
label="Watch Local Folder"
onClick={() => (isAnonymous ? gate("watch local folders") : setFolderWatchOpen(true))}
/>
)}
<SidebarButton
icon={Upload}
label="Upload Files"
onClick={() => (isAnonymous ? gate("upload files") : openUploadDialog())}
/>
{isDesktop && !isAnonymous && (
<FolderWatchDialog
open={folderWatchOpen}
onOpenChange={setFolderWatchOpen}
workspaceId={workspaceId}
onSuccess={() => bumpWatchedFoldersRefresh((c) => c + 1)}
/>
)}
</>
);
}
function SidebarUsageFooter({
pageUsage,
isCollapsed,