chore: ran linting

This commit is contained in:
Anish Sarkar 2026-03-11 12:30:20 +05:30
parent 1173f6ba19
commit 9503d4ade1
9 changed files with 317 additions and 316 deletions

View file

@ -1,6 +1,6 @@
import { atom } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query";
import { agentToolsApiService, type AgentToolInfo } from "@/lib/apis/agent-tools-api.service";
import { type AgentToolInfo, agentToolsApiService } from "@/lib/apis/agent-tools-api.service";
import { cacheKeys } from "@/lib/query-client/cache-keys";
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";

View file

@ -235,39 +235,39 @@ export const ComposioDriveConfig: FC<ComposioDriveConfigProps> = ({
</div>
)}
{isEditMode ? (
<div className="space-y-2">
<button
type="button"
onClick={() => setIsFolderTreeOpen(!isFolderTreeOpen)}
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-foreground transition-colors w-fit"
>
{isFolderTreeOpen ? (
<ChevronDown className="size-4" />
) : (
<ChevronRight className="size-4" />
{isEditMode ? (
<div className="space-y-2">
<button
type="button"
onClick={() => setIsFolderTreeOpen(!isFolderTreeOpen)}
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-foreground transition-colors w-fit"
>
{isFolderTreeOpen ? (
<ChevronDown className="size-4" />
) : (
<ChevronRight className="size-4" />
)}
Change Selection
</button>
{isFolderTreeOpen && (
<ComposioDriveFolderTree
connectorId={connector.id}
selectedFolders={selectedFolders}
onSelectFolders={handleSelectFolders}
selectedFiles={selectedFiles}
onSelectFiles={handleSelectFiles}
/>
)}
Change Selection
</button>
{isFolderTreeOpen && (
<ComposioDriveFolderTree
connectorId={connector.id}
selectedFolders={selectedFolders}
onSelectFolders={handleSelectFolders}
selectedFiles={selectedFiles}
onSelectFiles={handleSelectFiles}
/>
)}
</div>
) : (
<ComposioDriveFolderTree
connectorId={connector.id}
selectedFolders={selectedFolders}
onSelectFolders={handleSelectFolders}
selectedFiles={selectedFiles}
onSelectFiles={handleSelectFiles}
/>
)}
</div>
) : (
<ComposioDriveFolderTree
connectorId={connector.id}
selectedFolders={selectedFolders}
onSelectFolders={handleSelectFolders}
selectedFiles={selectedFiles}
onSelectFiles={handleSelectFiles}
/>
)}
</div>
{/* Indexing Options */}

View file

@ -123,11 +123,7 @@ export const useConnectorDialog = () => {
}, []);
const handleAutoIndex = useCallback(
async (
connector: SearchSourceConnector,
connectorTitle: string,
connectorType: string
) => {
async (connector: SearchSourceConnector, connectorTitle: string, connectorType: string) => {
if (!searchSpaceId || isAutoIndexingRef.current) return;
isAutoIndexingRef.current = true;
@ -159,12 +155,10 @@ export const useConnectorDialog = () => {
},
});
trackIndexWithDateRangeStarted(
Number(searchSpaceId),
connectorType,
connector.id,
{ hasStartDate: true, hasEndDate: true }
);
trackIndexWithDateRangeStarted(Number(searchSpaceId), connectorType, connector.id, {
hasStartDate: true,
hasEndDate: true,
});
toast.success(`${connectorTitle} connected!`, {
id: toastId,
@ -316,46 +310,46 @@ export const useConnectorDialog = () => {
}
}
}
} else {
// Do NOT call setIsOpen(false) here. Closing the dialog is handled
// explicitly by handleOpenChange and the individual action handlers.
// Relying on URL params to close the dialog caused a race condition
// where Next.js router updates from tab switches briefly produced
// stale searchParams without the "modal" key, closing the popup.
} else {
// Do NOT call setIsOpen(false) here. Closing the dialog is handled
// explicitly by handleOpenChange and the individual action handlers.
// Relying on URL params to close the dialog caused a race condition
// where Next.js router updates from tab switches briefly produced
// stale searchParams without the "modal" key, closing the popup.
// Still clean up sub-view state when the modal param is gone
// (e.g. after browser back navigation or explicit handler URL cleanup).
if (indexingConfig) {
setIndexingConfig(null);
setIndexingConnector(null);
setIndexingConnectorConfig(null);
setStartDate(undefined);
setEndDate(undefined);
setPeriodicEnabled(false);
setFrequencyMinutes("1440");
setEnableSummary(false);
setIsScrolled(false);
setSearchQuery("");
// Still clean up sub-view state when the modal param is gone
// (e.g. after browser back navigation or explicit handler URL cleanup).
if (indexingConfig) {
setIndexingConfig(null);
setIndexingConnector(null);
setIndexingConnectorConfig(null);
setStartDate(undefined);
setEndDate(undefined);
setPeriodicEnabled(false);
setFrequencyMinutes("1440");
setEnableSummary(false);
setIsScrolled(false);
setSearchQuery("");
}
if (editingConnector) {
setEditingConnector(null);
setConnectorName(null);
setConnectorConfig(null);
setStartDate(undefined);
setEndDate(undefined);
setPeriodicEnabled(false);
setFrequencyMinutes("1440");
setEnableSummary(false);
setIsScrolled(false);
setSearchQuery("");
}
if (connectingConnectorType) {
setConnectingConnectorType(null);
}
if (viewingAccountsType) {
setViewingAccountsType(null);
}
}
if (editingConnector) {
setEditingConnector(null);
setConnectorName(null);
setConnectorConfig(null);
setStartDate(undefined);
setEndDate(undefined);
setPeriodicEnabled(false);
setFrequencyMinutes("1440");
setEnableSummary(false);
setIsScrolled(false);
setSearchQuery("");
}
if (connectingConnectorType) {
setConnectingConnectorType(null);
}
if (viewingAccountsType) {
setViewingAccountsType(null);
}
}
} catch (error) {
// Invalid query params - log but don't crash
console.warn("Invalid connector popup query params:", error);
@ -412,18 +406,18 @@ export const useConnectorDialog = () => {
COMPOSIO_CONNECTORS.find((c) => c.id === params.connector)
: null;
if (earlyConnector && AUTO_INDEX_CONNECTOR_TYPES.has(earlyConnector.connectorType)) {
toast.loading(`Setting up ${earlyConnector.title}...`, { id: "auto-index" });
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("success");
url.searchParams.delete("connector");
url.searchParams.delete("connectorId");
url.searchParams.delete("view");
url.searchParams.delete("modal");
url.searchParams.delete("tab");
router.replace(url.pathname + url.search, { scroll: false });
}
if (earlyConnector && AUTO_INDEX_CONNECTOR_TYPES.has(earlyConnector.connectorType)) {
toast.loading(`Setting up ${earlyConnector.title}...`, { id: "auto-index" });
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("success");
url.searchParams.delete("connector");
url.searchParams.delete("connectorId");
url.searchParams.delete("view");
url.searchParams.delete("modal");
url.searchParams.delete("tab");
router.replace(url.pathname + url.search, { scroll: false });
}
refetchAllConnectors().then(async (result) => {
if (!result.data) {
@ -792,22 +786,22 @@ export const useConnectorDialog = () => {
},
});
const successMessage =
currentConnectorType === "MCP_CONNECTOR"
? `${connector.name} added successfully`
: `${connectorTitle} connected and syncing started!`;
toast.success(successMessage);
const successMessage =
currentConnectorType === "MCP_CONNECTOR"
? `${connector.name} added successfully`
: `${connectorTitle} connected and syncing started!`;
toast.success(successMessage);
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorType");
router.replace(url.pathname + url.search, { scroll: false });
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorType");
router.replace(url.pathname + url.search, { scroll: false });
// Clear indexing config state since we're not showing the view
// Clear indexing config state since we're not showing the view
setIndexingConfig(null);
setIndexingConnector(null);
setIndexingConnectorConfig(null);
@ -855,24 +849,24 @@ export const useConnectorDialog = () => {
// Refresh connectors list
await refetchAllConnectors();
} else {
// Other non-indexable connectors - just show success message and close
const successMessage =
currentConnectorType === "MCP_CONNECTOR"
? `${connector.name} added successfully`
: `${connectorTitle} connected successfully!`;
toast.success(successMessage);
// Other non-indexable connectors - just show success message and close
const successMessage =
currentConnectorType === "MCP_CONNECTOR"
? `${connector.name} added successfully`
: `${connectorTitle} connected successfully!`;
toast.success(successMessage);
// Refresh connectors list before closing modal
await refetchAllConnectors();
// Refresh connectors list before closing modal
await refetchAllConnectors();
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorType");
router.replace(url.pathname + url.search, { scroll: false });
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorType");
router.replace(url.pathname + url.search, { scroll: false });
// Clear indexing config state
setIndexingConfig(null);
@ -1129,19 +1123,19 @@ export const useConnectorDialog = () => {
);
}
toast.success(`${indexingConfig.connectorTitle} indexing started`);
toast.success(`${indexingConfig.connectorTitle} indexing started`);
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("success");
url.searchParams.delete("connector");
url.searchParams.delete("view");
router.replace(url.pathname + url.search, { scroll: false });
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("success");
url.searchParams.delete("connector");
url.searchParams.delete("view");
router.replace(url.pathname + url.search, { scroll: false });
refreshConnectors();
refreshConnectors();
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
@ -1421,43 +1415,43 @@ export const useConnectorDialog = () => {
: indexingDescription,
});
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorId");
router.replace(url.pathname + url.search, { scroll: false });
// Close dialog and clean up URL
setIsOpen(false);
const url = new URL(window.location.href);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorId");
router.replace(url.pathname + url.search, { scroll: false });
refreshConnectors();
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
} catch (error) {
console.error("Error saving connector:", error);
toast.error("Failed to save connector changes");
} finally {
setIsSaving(false);
}
},
[
editingConnector,
searchSpaceId,
isSaving,
startDate,
endDate,
indexConnector,
updateConnector,
periodicEnabled,
frequencyMinutes,
enableSummary,
getFrequencyLabel,
router,
connectorConfig,
connectorName,
setIsOpen,
]
refreshConnectors();
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
} catch (error) {
console.error("Error saving connector:", error);
toast.error("Failed to save connector changes");
} finally {
setIsSaving(false);
}
},
[
editingConnector,
searchSpaceId,
isSaving,
startDate,
endDate,
indexConnector,
updateConnector,
periodicEnabled,
frequencyMinutes,
enableSummary,
getFrequencyLabel,
router,
connectorConfig,
connectorName,
setIsOpen,
]
);
// Handle disconnecting connector
@ -1484,36 +1478,36 @@ export const useConnectorDialog = () => {
: `${editingConnector.name} disconnected successfully`
);
// Update URL - for MCP from list view, go back to list; otherwise close modal
const url = new URL(window.location.href);
if (editingConnector.connector_type === "MCP_CONNECTOR" && cameFromMCPList) {
// Go back to MCP list view only if we came from there
setViewingMCPList(true);
url.searchParams.set("modal", "connectors");
url.searchParams.set("view", "mcp-list");
url.searchParams.delete("connectorId");
} else {
// Close dialog for all other cases
setIsOpen(false);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorId");
}
router.replace(url.pathname + url.search, { scroll: false });
// Update URL - for MCP from list view, go back to list; otherwise close modal
const url = new URL(window.location.href);
if (editingConnector.connector_type === "MCP_CONNECTOR" && cameFromMCPList) {
// Go back to MCP list view only if we came from there
setViewingMCPList(true);
url.searchParams.set("modal", "connectors");
url.searchParams.set("view", "mcp-list");
url.searchParams.delete("connectorId");
} else {
// Close dialog for all other cases
setIsOpen(false);
url.searchParams.delete("modal");
url.searchParams.delete("tab");
url.searchParams.delete("view");
url.searchParams.delete("connectorId");
}
router.replace(url.pathname + url.search, { scroll: false });
refreshConnectors();
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
} catch (error) {
console.error("Error disconnecting connector:", error);
toast.error("Failed to disconnect connector");
} finally {
setIsDisconnecting(false);
}
},
[editingConnector, searchSpaceId, deleteConnector, router, cameFromMCPList, setIsOpen]
refreshConnectors();
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(Number(searchSpaceId)),
});
} catch (error) {
console.error("Error disconnecting connector:", error);
toast.error("Failed to disconnect connector");
} finally {
setIsDisconnecting(false);
}
},
[editingConnector, searchSpaceId, deleteConnector, router, cameFromMCPList, setIsOpen]
);
// Handle quick index (index with selected date range, or backend defaults if none selected)

View file

@ -28,6 +28,13 @@ import {
import { useParams } from "next/navigation";
import { type FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import {
agentToolsAtom,
disabledToolsAtom,
enabledToolCountAtom,
hydrateDisabledToolsAtom,
toggleToolAtom,
} from "@/atoms/agent-tools/agent-tools.atoms";
import { chatSessionStateAtom } from "@/atoms/chat/chat-session-state.atom";
import {
mentionedDocumentsAtom,
@ -66,21 +73,14 @@ import {
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
import { Avatar, AvatarFallback, AvatarGroup } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Switch } from "@/components/ui/switch";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
import type { Document } from "@/contracts/types/document.types";
import { useBatchCommentsPreload } from "@/hooks/use-comments";
import { useCommentsElectric } from "@/hooks/use-comments-electric";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Switch } from "@/components/ui/switch";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { useMediaQuery } from "@/hooks/use-media-query";
import {
agentToolsAtom,
disabledToolsAtom,
enabledToolCountAtom,
hydrateDisabledToolsAtom,
toggleToolAtom,
} from "@/atoms/agent-tools/agent-tools.atoms";
import { cn } from "@/lib/utils";
/** Placeholder texts that cycle in new chats when input is empty */
@ -623,13 +623,13 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
<Wrench className="size-4" />
</TooltipIconButton>
</PopoverTrigger>
<PopoverContent
side="bottom"
align="start"
sideOffset={12}
className="w-[calc(100vw-2rem)] max-w-56 sm:max-w-72 sm:w-72 p-0 select-none"
onOpenAutoFocus={(e) => e.preventDefault()}
>
<PopoverContent
side="bottom"
align="start"
sideOffset={12}
className="w-[calc(100vw-2rem)] max-w-56 sm:max-w-72 sm:w-72 p-0 select-none"
onOpenAutoFocus={(e) => e.preventDefault()}
>
<div className="flex items-center justify-between px-2.5 py-2 sm:px-3 sm:py-2.5 border-b">
<span className="text-xs sm:text-sm font-medium">Agent Tools</span>
<span className="text-[10px] sm:text-xs text-muted-foreground">
@ -648,7 +648,9 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
const isDisabled = disabledTools.includes(tool.name);
const row = (
<label className="flex items-center gap-2 sm:gap-3 px-2.5 sm:px-3 py-1 sm:py-1.5 cursor-pointer hover:bg-muted-foreground/10 transition-colors">
<span className="flex-1 min-w-0 text-xs sm:text-sm font-medium truncate">{formatToolName(tool.name)}</span>
<span className="flex-1 min-w-0 text-xs sm:text-sm font-medium truncate">
{formatToolName(tool.name)}
</span>
<Switch
checked={!isDisabled}
onCheckedChange={() => toggleTool(tool.name)}
@ -661,9 +663,7 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
}
return (
<Tooltip key={tool.name}>
<TooltipTrigger asChild>
{row}
</TooltipTrigger>
<TooltipTrigger asChild>{row}</TooltipTrigger>
<TooltipContent side="right" className="max-w-64 text-xs">
{tool.description}
</TooltipContent>

View file

@ -123,7 +123,7 @@ export function ChatListItem({
)}
</DropdownMenuItem>
)}
{onDelete && (
{onDelete && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();

View file

@ -233,63 +233,70 @@ export function DocumentsSidebar({
</div>
{/* Connected tools strip */}
<div className="shrink-0 mx-4 mt-2 mb-3 flex select-none items-center gap-2 rounded-lg border bg-muted/50 transition-colors hover:bg-muted/80">
<button
type="button"
onClick={() => setConnectorDialogOpen(true)}
className="flex items-center gap-2 min-w-0 flex-1 text-left px-3 py-2"
<div className="shrink-0 mx-4 mt-2 mb-3 flex select-none items-center gap-2 rounded-lg border bg-muted/50 transition-colors hover:bg-muted/80">
<button
type="button"
onClick={() => setConnectorDialogOpen(true)}
className="flex items-center gap-2 min-w-0 flex-1 text-left px-3 py-2"
>
<Unplug className="size-4 shrink-0 text-muted-foreground" />
<span className="truncate text-xs text-muted-foreground">
{connectorCount > 0 ? "Manage connectors" : "Connect your connectors"}
</span>
{connectorCount > 0 && (
<span className="shrink-0 rounded-full bg-muted-foreground/15 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
{connectorCount}
<Unplug className="size-4 shrink-0 text-muted-foreground" />
<span className="truncate text-xs text-muted-foreground">
{connectorCount > 0 ? "Manage connectors" : "Connect your connectors"}
</span>
)}
<AvatarGroup className="ml-auto shrink-0">
{connectorCount > 0 && connectors
? connectors
.slice(0, isMobile ? 5 : 9)
.map((connector, i) => {
const avatar = (
<Avatar key={connector.id} className="size-6" style={{ zIndex: Math.max(9 - i, 1) }}>
<AvatarFallback className="bg-muted text-[10px]">
{getConnectorIcon(connector.connector_type, "size-3.5")}
</AvatarFallback>
</Avatar>
);
if (isMobile) return avatar;
return (
<Tooltip key={connector.id}>
<TooltipTrigger asChild>{avatar}</TooltipTrigger>
<TooltipContent side="top" className="text-xs">
{connector.name}
</TooltipContent>
</Tooltip>
);
})
: (isMobile ? SHOWCASE_CONNECTORS.slice(0, 5) : SHOWCASE_CONNECTORS).map(({ type, label }, i) => {
const avatar = (
<Avatar key={type} className="size-6" style={{ zIndex: SHOWCASE_CONNECTORS.length - i }}>
<AvatarFallback className="bg-muted text-[10px]">
{getConnectorIcon(type, "size-3.5")}
</AvatarFallback>
</Avatar>
);
if (isMobile) return avatar;
return (
<Tooltip key={type}>
<TooltipTrigger asChild>{avatar}</TooltipTrigger>
<TooltipContent side="top" className="text-xs">
{label}
</TooltipContent>
</Tooltip>
);
})
}
</AvatarGroup>
{connectorCount > 0 && (
<span className="shrink-0 rounded-full bg-muted-foreground/15 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
{connectorCount}
</span>
)}
<AvatarGroup className="ml-auto shrink-0">
{connectorCount > 0 && connectors
? connectors.slice(0, isMobile ? 5 : 9).map((connector, i) => {
const avatar = (
<Avatar
key={connector.id}
className="size-6"
style={{ zIndex: Math.max(9 - i, 1) }}
>
<AvatarFallback className="bg-muted text-[10px]">
{getConnectorIcon(connector.connector_type, "size-3.5")}
</AvatarFallback>
</Avatar>
);
if (isMobile) return avatar;
return (
<Tooltip key={connector.id}>
<TooltipTrigger asChild>{avatar}</TooltipTrigger>
<TooltipContent side="top" className="text-xs">
{connector.name}
</TooltipContent>
</Tooltip>
);
})
: (isMobile ? SHOWCASE_CONNECTORS.slice(0, 5) : SHOWCASE_CONNECTORS).map(
({ type, label }, i) => {
const avatar = (
<Avatar
key={type}
className="size-6"
style={{ zIndex: SHOWCASE_CONNECTORS.length - i }}
>
<AvatarFallback className="bg-muted text-[10px]">
{getConnectorIcon(type, "size-3.5")}
</AvatarFallback>
</Avatar>
);
if (isMobile) return avatar;
return (
<Tooltip key={type}>
<TooltipTrigger asChild>{avatar}</TooltipTrigger>
<TooltipContent side="top" className="text-xs">
{label}
</TooltipContent>
</Tooltip>
);
}
)}
</AvatarGroup>
</button>
</div>

View file

@ -217,20 +217,20 @@ export function Sidebar({
<div
className={`flex flex-col gap-0.5 max-h-full overflow-y-auto scrollbar-thin scrollbar-thumb-muted-foreground/20 scrollbar-track-transparent ${sharedChats.length > 4 ? "pb-8" : ""}`}
>
{sharedChats.slice(0, 20).map((chat) => (
<ChatListItem
key={chat.id}
name={chat.name}
isActive={chat.id === activeChatId}
archived={chat.archived}
dropdownOpen={openDropdownChatId === chat.id}
onDropdownOpenChange={(open) => setOpenDropdownChatId(open ? chat.id : null)}
onClick={() => onChatSelect(chat)}
onRename={() => onChatRename?.(chat)}
onArchive={() => onChatArchive?.(chat)}
onDelete={() => onChatDelete?.(chat)}
/>
))}
{sharedChats.slice(0, 20).map((chat) => (
<ChatListItem
key={chat.id}
name={chat.name}
isActive={chat.id === activeChatId}
archived={chat.archived}
dropdownOpen={openDropdownChatId === chat.id}
onDropdownOpenChange={(open) => setOpenDropdownChatId(open ? chat.id : null)}
onClick={() => onChatSelect(chat)}
onRename={() => onChatRename?.(chat)}
onArchive={() => onChatArchive?.(chat)}
onDelete={() => onChatDelete?.(chat)}
/>
))}
</div>
{/* Gradient fade indicator when more than 4 items */}
{sharedChats.length > 4 && (
@ -291,20 +291,20 @@ export function Sidebar({
<div
className={`flex flex-col gap-0.5 h-full overflow-y-auto scrollbar-thin scrollbar-thumb-muted-foreground/20 scrollbar-track-transparent ${chats.length > 4 ? "pb-8" : ""}`}
>
{chats.slice(0, 20).map((chat) => (
<ChatListItem
key={chat.id}
name={chat.name}
isActive={chat.id === activeChatId}
archived={chat.archived}
dropdownOpen={openDropdownChatId === chat.id}
onDropdownOpenChange={(open) => setOpenDropdownChatId(open ? chat.id : null)}
onClick={() => onChatSelect(chat)}
onRename={() => onChatRename?.(chat)}
onArchive={() => onChatArchive?.(chat)}
onDelete={() => onChatDelete?.(chat)}
/>
))}
{chats.slice(0, 20).map((chat) => (
<ChatListItem
key={chat.id}
name={chat.name}
isActive={chat.id === activeChatId}
archived={chat.archived}
dropdownOpen={openDropdownChatId === chat.id}
onDropdownOpenChange={(open) => setOpenDropdownChatId(open ? chat.id : null)}
onClick={() => onChatSelect(chat)}
onRename={() => onChatRename?.(chat)}
onArchive={() => onChatArchive?.(chat)}
onDelete={() => onChatDelete?.(chat)}
/>
))}
</div>
{/* Gradient fade indicator when more than 4 items */}
{chats.length > 4 && (

View file

@ -9,8 +9,8 @@ import {
Laptop,
LogOut,
Moon,
UserCog,
Sun,
UserCog,
} from "lucide-react";
import Image from "next/image";
import { useTranslations } from "next-intl";

View file

@ -154,17 +154,17 @@ export function useGooglePicker({ connectorId, onPicked }: UseGooglePickerOption
}
}
if (action === google.picker.Action.ERROR) {
setError("Google Drive encountered an error. Please try again.");
}
if (action === google.picker.Action.ERROR) {
setError("Google Drive encountered an error. Please try again.");
}
if (
action === google.picker.Action.PICKED ||
action === google.picker.Action.CANCEL ||
action === google.picker.Action.ERROR
) {
closePicker();
}
if (
action === google.picker.Action.PICKED ||
action === google.picker.Action.CANCEL ||
action === google.picker.Action.ERROR
) {
closePicker();
}
})
.build();