Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 17 additions & 24 deletions packages/desktop/src/renderer/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Toaster } from 'sonner';
import { Toaster, TOAST_DURATION_MS, TOAST_OPTIONS } from '@/lib/toast';
import LeftNav from './layouts/LeftNav';
import MainArea from './layouts/MainArea';
import RightPanel from './layouts/RightPanel';
import Setup from './layouts/Setup';
import Settings from './layouts/Settings';
import ApprovalDialog from './components/ApprovalDialog';
import CommandPalette from './components/CommandPalette';
import { useUiStore } from './stores/uiStore';
import { useUiStore, type Theme } from './stores/uiStore';
import { useTaskStore } from './stores/taskStore';
import { useFileStore } from './stores/fileStore';
import { composer } from './platform';
Expand All @@ -20,6 +20,19 @@ import { TooltipProvider } from '@/components/ui/tooltip';
import { motionDuration, motionEase } from '@/styles/design-tokens';
import { useSettingsStore } from './stores/settingsStore';

function AppToaster({ themeMode }: { themeMode: Theme }) {
return (
<Toaster
theme={themeMode === 'auto' ? 'system' : themeMode}
position="top-right"
closeButton
visibleToasts={3}
duration={TOAST_DURATION_MS}
toastOptions={TOAST_OPTIONS}
/>
);
}

export default function App() {
const [ready, setReady] = useState(false);
const [needsSetup, setNeedsSetup] = useState(false);
Expand Down Expand Up @@ -204,17 +217,7 @@ export default function App() {
setReady(true);
}}
/>
<Toaster
theme={themeMode === 'auto' ? 'system' : themeMode}
position="bottom-right"
toastOptions={{
style: {
background: 'var(--bg-elevated)',
border: '1px solid var(--border)',
color: 'var(--text-primary)',
},
}}
/>
<AppToaster themeMode={themeMode} />
</TooltipProvider>
);
}
Expand Down Expand Up @@ -268,17 +271,7 @@ export default function App() {
</>
)}
</AnimatePresence>
<Toaster
theme={themeMode === 'auto' ? 'system' : themeMode}
position="bottom-right"
toastOptions={{
style: {
background: 'var(--bg-elevated)',
border: '1px solid var(--border)',
color: 'var(--text-primary)',
},
}}
/>
<AppToaster themeMode={themeMode} />
<ApprovalDialog />
</div>
</TooltipProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { Sparkles, Send, Loader2, Bot, User, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from 'lucide-react';
import { type KeyboardEvent, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import AgentIcon from '@/components/AgentIcon';
import ToolbarButton from '@/components/semantic/ToolbarButton';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
type SetStateAction,
} from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type {
Task,
AgentInfo,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useCallback, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { FileIndexEntry } from '@clawwork/shared';
import { useTaskStore } from '../../stores/taskStore';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { PendingAttachment } from './types';
import { MAX_ATTACHMENT_SIZE, GATEWAY_INJECTED_MODEL } from './constants';

Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/renderer/components/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { motion } from 'framer-motion';
import type { Message } from '@clawwork/shared';
import { Check, Copy, File, FileCode, Loader2, Save } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { motion as motionPresets } from '@/styles/design-tokens';
import { copyTextToClipboard } from '@/lib/clipboard';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
ChevronRight,
} from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { ModelCatalogEntry, InstallEvent } from '@clawwork/shared';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createGatewayDispatcher } from '@clawwork/core';
import type { ExecApprovalRequest, ModelCatalogEntry, AgentInfo } from '@clawwork/shared';
import { parseAgentIdFromSessionKey, parseTaskIdFromSessionKey } from '@clawwork/shared';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { hydrateFromLocal, retrySyncPending, syncFromGateway, syncSessionMessages } from '../lib/session-sync';
import i18n from '../i18n';
import { composer, composerBridge, ports, useMessageStore, useTaskStore, useUiStore, useRoomStore } from '../platform';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Clock, Plus, Search, RefreshCw, ChevronDown, Server, Loader2 } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { useUiStore } from '@/stores/uiStore';
import { cn } from '@/lib/utils';
import { motion as motionPresets, STAGGER_STEP } from '@/styles/design-tokens';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { QRCodeSVG } from 'qrcode.react';
import { Smartphone, Loader2 } from 'lucide-react';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { useTranslation } from 'react-i18next';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { Star, Bug, RefreshCw, Loader2, Download, RotateCcw, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import SettingRow from '@/components/semantic/SettingRow';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
Sparkles,
} from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { motion as motionPresets } from '@/styles/design-tokens';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
X,
} from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { motion as motionPresets } from '@/styles/design-tokens';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useMemo } from 'react';
import { Moon, Sun, Monitor, Bell, Smartphone } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { modKey } from '@/lib/utils';
import {
useUiStore,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
Settings2,
} from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { motion as motionPresets, motionDuration } from '@/styles/design-tokens';
import { useUiStore } from '@/stores/uiStore';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback } from 'react';
import { MonitorDot, Zap, FolderOpen, Loader2, ExternalLink } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import Toggle from '../components/Toggle';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
import { ArrowLeft, MessageSquare, Pencil, Check, X, Loader2, Puzzle, Package } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { Team } from '@clawwork/shared';
import { Button } from '@/components/ui/button';
import { ScrollArea } from '@/components/ui/scroll-area';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useMemo, useCallback } from 'react';
import { ArrowLeft, Download, Check, Loader2, Package, User, Tag } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { TeamHubEntry, ParsedTeam, AgentFileSet } from '@clawwork/shared';
import { extractSkillSlugs } from '@clawwork/core';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useMemo } from 'react';
import { Search, Settings, RefreshCw, Loader2, Store } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { TeamHubRegistry, TeamHubEntry } from '@clawwork/shared';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useCallback, useEffect, useMemo } from 'react';
import { Users, Plus, Sparkles } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import type { Team, TeamHubEntry } from '@clawwork/shared';
import { cn } from '@/lib/utils';
import WindowTitlebar from '@/components/semantic/WindowTitlebar';
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/renderer/lib/export-session.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import i18n from '../i18n';

export function exportToFiles(taskId: string): void {
Expand Down
38 changes: 38 additions & 0 deletions packages/desktop/src/renderer/lib/toast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { toast as sonnerToast } from 'sonner';
import type { ExternalToast, ToasterProps } from 'sonner';

export { Toaster } from 'sonner';

export const TOAST_DURATION_MS = 4000;
const WARNING_TOAST_DURATION_MS = 8000;
const ERROR_TOAST_DURATION_MS = 10000;
const TOAST_CLOSE_BUTTON_CLASS =
'!left-auto !right-3 !top-1/2 !h-7 !w-7 !-translate-y-1/2 !translate-x-0 !border-0 !bg-transparent !text-[var(--text-muted)] hover:!bg-[var(--bg-hover)] hover:!text-[var(--text-primary)]';

export const TOAST_OPTIONS: NonNullable<ToasterProps['toastOptions']> = {
closeButton: true,
closeButtonAriaLabel: 'Close notification',
classNames: {
toast: 'pr-11',
closeButton: TOAST_CLOSE_BUTTON_CLASS,
},
style: {
background: 'var(--bg-elevated)',
border: '1px solid var(--border)',
color: 'var(--text-primary)',
},
};

type ToastMessage = Parameters<typeof sonnerToast>[0];
type RendererToast = typeof sonnerToast;

export const toast: RendererToast = Object.assign(
(message: ToastMessage, data?: ExternalToast) => sonnerToast(message, data),
sonnerToast,
{
warning: (message: ToastMessage, data?: ExternalToast) =>
sonnerToast.warning(message, { duration: WARNING_TOAST_DURATION_MS, ...data }),
error: (message: ToastMessage, data?: ExternalToast) =>
sonnerToast.error(message, { duration: ERROR_TOAST_DURATION_MS, ...data }),
},
);
2 changes: 1 addition & 1 deletion packages/desktop/src/renderer/platform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
SystemSessionState,
SystemSessionService,
} from '@clawwork/core';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { createElectronPorts } from './electron-adapter';
import i18n from '../i18n';
import { syncSettingsUpdate } from '../stores/settingsStore';
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/renderer/stores/approvalStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { create } from 'zustand';
import { parseTaskIdFromSessionKey } from '@clawwork/shared';
import type { ApprovalDecision, ExecApprovalRequest } from '@clawwork/shared';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import i18n from '../i18n';
import { useTaskStore } from './taskStore';
import { useUiStore } from './uiStore';
Expand Down
4 changes: 2 additions & 2 deletions packages/desktop/test/conductor-catalog-fallback.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key }),
}));

vi.mock('sonner', () => ({
vi.mock('../src/renderer/lib/toast', () => ({
toast: {
error: vi.fn(),
},
Expand Down Expand Up @@ -112,7 +112,7 @@ vi.mock('../src/renderer/platform', () => ({
useTeamStore: makeStoreMock(mocks.teamState),
}));

import { toast } from 'sonner';
import { toast } from '../src/renderer/lib/toast';
import { useChatSend } from '../src/renderer/components/ChatInput/useChatSend';

/* ---------- helpers ---------- */
Expand Down