refactor: replace 'sonner' toast import with local toast component (#177)

This commit is contained in:
Bohdan Triapitsyn
2026-01-19 02:50:40 +02:00
committed by GitHub
parent 28d9324735
commit ce1622b1e2
34 changed files with 87 additions and 32 deletions
@@ -27,7 +27,7 @@ import { parseAgentMentions } from '@/lib/messages/agentMentions';
import { StatusRow } from './StatusRow'; import { StatusRow } from './StatusRow';
import { useAssistantStatus } from '@/hooks/useAssistantStatus'; import { useAssistantStatus } from '@/hooks/useAssistantStatus';
import { useCurrentSessionActivity } from '@/hooks/useSessionActivity'; import { useCurrentSessionActivity } from '@/hooks/useSessionActivity';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useFileStore } from '@/stores/fileStore'; import { useFileStore } from '@/stores/fileStore';
import { calculateEditPermissionUIState, type BashPermissionSetting } from '@/lib/permissions/editPermissionDefaults'; import { calculateEditPermissionUIState, type BashPermissionSetting } from '@/lib/permissions/editPermissionDefaults';
import { isVSCodeRuntime } from '@/lib/desktop'; import { isVSCodeRuntime } from '@/lib/desktop';
@@ -2,7 +2,7 @@ import React, { useRef, memo } from 'react';
import { RiAttachment2, RiCloseLine, RiComputerLine, RiFileImageLine, RiFileLine, RiFilePdfLine, RiHardDrive3Line } from '@remixicon/react'; import { RiAttachment2, RiCloseLine, RiComputerLine, RiFileImageLine, RiFileLine, RiFilePdfLine, RiHardDrive3Line } from '@remixicon/react';
import { useSessionStore, type AttachedFile } from '@/stores/useSessionStore'; import { useSessionStore, type AttachedFile } from '@/stores/useSessionStore';
import { useUIStore } from '@/stores/useUIStore'; import { useUIStore } from '@/stores/useUIStore';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'; import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
import { useIsVSCodeRuntime } from '@/hooks/useRuntimeAPIs'; import { useIsVSCodeRuntime } from '@/hooks/useRuntimeAPIs';
@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { RiDownloadLine, RiInformationLine, RiSettings3Line } from '@remixicon/react'; import { RiDownloadLine, RiInformationLine, RiSettings3Line } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { ErrorBoundary } from '../ui/ErrorBoundary'; import { ErrorBoundary } from '../ui/ErrorBoundary';
import { useUIStore } from '@/stores/useUIStore'; import { useUIStore } from '@/stores/useUIStore';
@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { RiAddLine, RiArrowDownSLine, RiAttachment2, RiCloseLine, RiFileImageLine, RiFileLine, RiPlayLine } from '@remixicon/react'; import { RiAddLine, RiArrowDownSLine, RiAttachment2, RiCloseLine, RiFileImageLine, RiFileLine, RiPlayLine } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
@@ -3,7 +3,7 @@ import { Button } from '@/components/ui/button';
import { ButtonSmall } from '@/components/ui/button-small'; import { ButtonSmall } from '@/components/ui/button-small';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useAgentsStore, type AgentConfig, type AgentScope } from '@/stores/useAgentsStore'; import { useAgentsStore, type AgentConfig, type AgentScope } from '@/stores/useAgentsStore';
import { useConfigStore } from '@/stores/useConfigStore'; import { useConfigStore } from '@/stores/useConfigStore';
import { usePermissionStore } from '@/stores/permissionStore'; import { usePermissionStore } from '@/stores/permissionStore';
@@ -2,7 +2,7 @@ import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { ButtonLarge } from '@/components/ui/button-large'; import { ButtonLarge } from '@/components/ui/button-large';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -2,7 +2,7 @@ import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useCommandsStore, type CommandConfig, type CommandScope } from '@/stores/useCommandsStore'; import { useCommandsStore, type CommandConfig, type CommandScope } from '@/stores/useCommandsStore';
import { RiCheckLine, RiInformationLine, RiSaveLine, RiTerminalBoxLine, RiUser3Line, RiFolderLine } from '@remixicon/react'; import { RiCheckLine, RiInformationLine, RiSaveLine, RiTerminalBoxLine, RiUser3Line, RiFolderLine } from '@remixicon/react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
@@ -2,7 +2,7 @@ import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { ButtonLarge } from '@/components/ui/button-large'; import { ButtonLarge } from '@/components/ui/button-large';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useGitIdentitiesStore, type GitIdentityProfile, type GitIdentityAuthType } from '@/stores/useGitIdentitiesStore'; import { useGitIdentitiesStore, type GitIdentityProfile, type GitIdentityAuthType } from '@/stores/useGitIdentitiesStore';
import { import {
RiUser3Line, RiUser3Line,
@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -3,7 +3,7 @@ import { RiDiscordFill, RiDownloadLine, RiGithubFill, RiLoaderLine, RiRestartLin
import { useUpdateStore } from '@/stores/useUpdateStore'; import { useUpdateStore } from '@/stores/useUpdateStore';
import { UpdateDialog } from '@/components/ui/UpdateDialog'; import { UpdateDialog } from '@/components/ui/UpdateDialog';
import { useDeviceInfo } from '@/lib/device'; import { useDeviceInfo } from '@/lib/device';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { reloadOpenCodeConfiguration } from '@/stores/useAgentsStore'; import { reloadOpenCodeConfiguration } from '@/stores/useAgentsStore';
@@ -2,7 +2,7 @@ import React from 'react';
import { useUIStore } from '@/stores/useUIStore'; import { useUIStore } from '@/stores/useUIStore';
import { isWebRuntime } from '@/lib/desktop'; import { isWebRuntime } from '@/lib/desktop';
import { Switch } from '@/components/ui/switch'; import { Switch } from '@/components/ui/switch';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
export const NotificationSettings: React.FC = () => { export const NotificationSettings: React.FC = () => {
const nativeNotificationsEnabled = useUIStore(state => state.nativeNotificationsEnabled); const nativeNotificationsEnabled = useUIStore(state => state.nativeNotificationsEnabled);
@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { RiInformationLine } from '@remixicon/react'; import { RiInformationLine } from '@remixicon/react';
import { NumberInput } from '@/components/ui/number-input'; import { NumberInput } from '@/components/ui/number-input';
import { ButtonSmall } from '@/components/ui/button-small'; import { ButtonSmall } from '@/components/ui/button-small';
@@ -10,7 +10,7 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'; } from '@/components/ui/dropdown-menu';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { RiStackLine, RiToolsLine, RiBrainAi3Line, RiFileImageLine, RiArrowDownSLine, RiCheckLine, RiSearchLine } from '@remixicon/react'; import { RiStackLine, RiToolsLine, RiBrainAi3Line, RiFileImageLine, RiArrowDownSLine, RiCheckLine, RiSearchLine } from '@remixicon/react';
import { reloadOpenCodeConfiguration } from '@/stores/useAgentsStore'; import { reloadOpenCodeConfiguration } from '@/stores/useAgentsStore';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
@@ -2,7 +2,7 @@ import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useSkillsStore, type SkillConfig, type SkillScope, type SupportingFile, type PendingFile } from '@/stores/useSkillsStore'; import { useSkillsStore, type SkillConfig, type SkillScope, type SupportingFile, type PendingFile } from '@/stores/useSkillsStore';
import { RiAddLine, RiBookOpenLine, RiDeleteBinLine, RiFileLine, RiFolderLine, RiSaveLine, RiUser3Line } from '@remixicon/react'; import { RiAddLine, RiBookOpenLine, RiDeleteBinLine, RiFileLine, RiFolderLine, RiSaveLine, RiUser3Line } from '@remixicon/react';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
@@ -2,7 +2,7 @@ import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { ButtonLarge } from '@/components/ui/button-large'; import { ButtonLarge } from '@/components/ui/button-large';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
@@ -14,7 +14,7 @@ import { useDirectoryStore } from '@/stores/useDirectoryStore';
import { useProjectsStore } from '@/stores/useProjectsStore'; import { useProjectsStore } from '@/stores/useProjectsStore';
import { useFileSystemAccess } from '@/hooks/useFileSystemAccess'; import { useFileSystemAccess } from '@/hooks/useFileSystemAccess';
import { cn, formatPathForDisplay } from '@/lib/utils'; import { cn, formatPathForDisplay } from '@/lib/utils';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
RiCheckboxBlankLine, RiCheckboxBlankLine,
RiCheckboxLine, RiCheckboxLine,
@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import type { Session } from '@opencode-ai/sdk/v2'; import type { Session } from '@opencode-ai/sdk/v2';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
DndContext, DndContext,
DragOverlay, DragOverlay,
@@ -7,7 +7,7 @@ import { OpenChamberLogo } from '@/components/ui/OpenChamberLogo';
import { RiDiscordFill, RiGithubFill, RiTwitterXFill } from '@remixicon/react'; import { RiDiscordFill, RiGithubFill, RiTwitterXFill } from '@remixicon/react';
import { debugUtils } from '@/lib/debug'; import { debugUtils } from '@/lib/debug';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
declare const __APP_VERSION__: string | undefined; declare const __APP_VERSION__: string | undefined;
+2
View File
@@ -0,0 +1,2 @@
export { Toaster } from './sonner'
export { toast } from './toast'
+53
View File
@@ -0,0 +1,53 @@
"use client"
import { toast as sonnerToast } from "sonner"
import type { ExternalToast } from "sonner"
const copyToClipboard = async (text: string) => {
try {
await navigator.clipboard.writeText(text)
} catch (err) {
console.error('Failed to copy to clipboard:', err)
}
}
// Wrapper to automatically add OK button to success and info toasts, Copy button to error and warning toasts
export const toast = {
...sonnerToast,
success: (message: string | React.ReactNode, data?: ExternalToast) => {
return sonnerToast.success(message, {
...data,
action: data?.action || {
label: 'OK',
onClick: () => {},
},
})
},
info: (message: string | React.ReactNode, data?: ExternalToast) => {
return sonnerToast.info(message, {
...data,
action: data?.action || {
label: 'OK',
onClick: () => {},
},
})
},
error: (message: string | React.ReactNode, data?: ExternalToast) => {
return sonnerToast.error(message, {
...data,
action: data?.action || {
label: 'Copy',
onClick: () => copyToClipboard(String(message)),
},
})
},
warning: (message: string | React.ReactNode, data?: ExternalToast) => {
return sonnerToast.warning(message, {
...data,
action: data?.action || {
label: 'Copy',
onClick: () => copyToClipboard(String(message)),
},
})
},
}
@@ -17,7 +17,7 @@ import {
RiSendPlane2Line, RiSendPlane2Line,
RiTextWrap, RiTextWrap,
} from '@remixicon/react'; } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
+1 -1
View File
@@ -15,7 +15,7 @@ import {
} from '@/stores/useGitStore'; } from '@/stores/useGitStore';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
import { RiGitBranchLine, RiLoader4Line } from '@remixicon/react'; import { RiGitBranchLine, RiLoader4Line } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -9,7 +9,7 @@ import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
import { ensureFlexokiThemesRegistered } from '@/lib/shiki/registerFlexokiThemes'; import { ensureFlexokiThemesRegistered } from '@/lib/shiki/registerFlexokiThemes';
import { flexokiThemeNames } from '@/lib/shiki/flexokiThemes'; import { flexokiThemeNames } from '@/lib/shiki/flexokiThemes';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { useSessionStore } from '@/stores/useSessionStore'; import { useSessionStore } from '@/stores/useSessionStore';
import { useConfigStore } from '@/stores/useConfigStore'; import { useConfigStore } from '@/stores/useConfigStore';
@@ -6,7 +6,7 @@ import {
RiMore2Line, RiMore2Line,
RiFileCopyLine, RiFileCopyLine,
} from '@remixicon/react'; } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { ProviderLogo } from '@/components/ui/ProviderLogo'; import { ProviderLogo } from '@/components/ui/ProviderLogo';
@@ -10,7 +10,7 @@ import {
RiHourglassFill, RiHourglassFill,
RiSendPlane2Line, RiSendPlane2Line,
} from '@remixicon/react'; } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
@@ -6,7 +6,7 @@ import {
RiSearchLine, RiSearchLine,
RiGitBranchLine, RiGitBranchLine,
} from '@remixicon/react'; } from '@remixicon/react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { AgentManagerSidebar } from './AgentManagerSidebar'; import { AgentManagerSidebar } from './AgentManagerSidebar';
import { AgentManagerEmptyState } from './AgentManagerEmptyState'; import { AgentManagerEmptyState } from './AgentManagerEmptyState';
import { AgentGroupDetail } from './AgentGroupDetail'; import { AgentGroupDetail } from './AgentGroupDetail';
+1 -1
View File
@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useSessionStore } from '@/stores/useSessionStore'; import { useSessionStore } from '@/stores/useSessionStore';
import { useUIStore } from '@/stores/useUIStore'; import { useUIStore } from '@/stores/useUIStore';
import { useProjectsStore } from '@/stores/useProjectsStore'; import { useProjectsStore } from '@/stores/useProjectsStore';
@@ -4,7 +4,7 @@
* menu actions, or other non-hook contexts. * menu actions, or other non-hook contexts.
*/ */
import { toast } from 'sonner'; import { toast } from '@/components/ui';
import { useSessionStore } from '@/stores/useSessionStore'; import { useSessionStore } from '@/stores/useSessionStore';
import { useProjectsStore } from '@/stores/useProjectsStore'; import { useProjectsStore } from '@/stores/useProjectsStore';
import { useConfigStore } from '@/stores/useConfigStore'; import { useConfigStore } from '@/stores/useConfigStore';