refactor: move shared hooks from ui/hooks to shared/hooks (#729)

Reorganize hook structure to follow vertical slice architecture:
- Move useSmartPolling, useThemeAware, useToast to features/shared/hooks
- Update 38+ import statements across codebase
- Update test file mocks to reference new locations
- Remove old ui/hooks directory

This change aligns shared utilities with the architectural pattern
where truly shared code resides in the shared directory.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Wirasm 2025-09-22 12:54:55 +03:00 committed by GitHub
parent 3ff3f7f2dc
commit d3a5c3311a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 40 additions and 40 deletions

View File

@ -5,7 +5,7 @@ import { Button } from "../ui/Button";
import { Input } from "../ui/Input"; import { Input } from "../ui/Input";
import { Card } from "../ui/Card"; import { Card } from "../ui/Card";
import { Select } from "../ui/Select"; import { Select } from "../ui/Select";
import { useToast } from "../../features/ui/hooks/useToast"; import { useToast } from "../../features/shared/hooks/useToast";
import { import {
bugReportService, bugReportService,
BugContext, BugContext,

View File

@ -2,7 +2,7 @@ import { AlertCircle, WifiOff } from "lucide-react";
import type React from "react"; import type React from "react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { useToast } from "../../features/ui/hooks/useToast"; import { useToast } from "../../features/shared/hooks/useToast";
import { cn } from "../../lib/utils"; import { cn } from "../../lib/utils";
import { credentialsService } from "../../services/credentialsService"; import { credentialsService } from "../../services/credentialsService";
import { isLmConfigured } from "../../utils/onboarding"; import { isLmConfigured } from "../../utils/onboarding";

View File

@ -3,7 +3,7 @@ import { Key, ExternalLink, Save, Loader } from "lucide-react";
import { Input } from "../ui/Input"; import { Input } from "../ui/Input";
import { Button } from "../ui/Button"; import { Button } from "../ui/Button";
import { Select } from "../ui/Select"; import { Select } from "../ui/Select";
import { useToast } from "../../features/ui/hooks/useToast"; import { useToast } from "../../features/shared/hooks/useToast";
import { credentialsService } from "../../services/credentialsService"; import { credentialsService } from "../../services/credentialsService";
interface ProviderStepProps { interface ProviderStepProps {

View File

@ -4,7 +4,7 @@ import { Input } from '../ui/Input';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { Card } from '../ui/Card'; import { Card } from '../ui/Card';
import { credentialsService, Credential } from '../../services/credentialsService'; import { credentialsService, Credential } from '../../services/credentialsService';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
interface CustomCredential { interface CustomCredential {
key: string; key: string;

View File

@ -3,7 +3,7 @@ import { Code, Check, Save, Loader } from 'lucide-react';
import { Card } from '../ui/Card'; import { Card } from '../ui/Card';
import { Input } from '../ui/Input'; import { Input } from '../ui/Input';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { credentialsService } from '../../services/credentialsService'; import { credentialsService } from '../../services/credentialsService';
interface CodeExtractionSettingsProps { interface CodeExtractionSettingsProps {

View File

@ -4,7 +4,7 @@ import { Toggle } from '../ui/Toggle';
import { Card } from '../ui/Card'; import { Card } from '../ui/Card';
import { useTheme } from '../../contexts/ThemeContext'; import { useTheme } from '../../contexts/ThemeContext';
import { credentialsService } from '../../services/credentialsService'; import { credentialsService } from '../../services/credentialsService';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { serverHealthService } from '../../services/serverHealthService'; import { serverHealthService } from '../../services/serverHealthService';
export const FeaturesSection = () => { export const FeaturesSection = () => {

View File

@ -2,7 +2,7 @@ import { useState } from 'react';
import { FileCode, Copy, Check } from 'lucide-react'; import { FileCode, Copy, Check } from 'lucide-react';
import { Card } from '../ui/Card'; import { Card } from '../ui/Card';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { copyToClipboard } from '../../features/shared/utils/clipboard'; import { copyToClipboard } from '../../features/shared/utils/clipboard';
type RuleType = 'claude' | 'universal'; type RuleType = 'claude' | 'universal';

View File

@ -3,7 +3,7 @@ import { Card } from '../ui/Card';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { Input } from '../ui/Input'; import { Input } from '../ui/Input';
import { Badge } from '../ui/Badge'; import { Badge } from '../ui/Badge';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { cn } from '../../lib/utils'; import { cn } from '../../lib/utils';
import { credentialsService, OllamaInstance } from '../../services/credentialsService'; import { credentialsService, OllamaInstance } from '../../services/credentialsService';
import { OllamaModelDiscoveryModal } from './OllamaModelDiscoveryModal'; import { OllamaModelDiscoveryModal } from './OllamaModelDiscoveryModal';

View File

@ -3,7 +3,7 @@ import { Badge } from '../ui/Badge';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { Card } from '../ui/Card'; import { Card } from '../ui/Card';
import { cn } from '../../lib/utils'; import { cn } from '../../lib/utils';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { ollamaService } from '../../services/ollamaService'; import { ollamaService } from '../../services/ollamaService';
import type { HealthIndicatorProps } from './types/OllamaTypes'; import type { HealthIndicatorProps } from './types/OllamaTypes';

View File

@ -13,7 +13,7 @@ import { Button } from '../ui/Button';
import { Input } from '../ui/Input'; import { Input } from '../ui/Input';
import { Badge } from '../ui/Badge'; import { Badge } from '../ui/Badge';
import { Card } from '../ui/Card'; import { Card } from '../ui/Card';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { ollamaService, type OllamaModel, type ModelDiscoveryResponse } from '../../services/ollamaService'; import { ollamaService, type OllamaModel, type ModelDiscoveryResponse } from '../../services/ollamaService';
import type { OllamaInstance, ModelSelectionState } from './types/OllamaTypes'; import type { OllamaInstance, ModelSelectionState } from './types/OllamaTypes';

View File

@ -3,7 +3,7 @@ import ReactDOM from 'react-dom';
import { X, Search, RotateCcw, Zap, Server, Eye, Settings, Download, Box } from 'lucide-react'; import { X, Search, RotateCcw, Zap, Server, Eye, Settings, Download, Box } from 'lucide-react';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { Input } from '../ui/Input'; import { Input } from '../ui/Input';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
interface ContextInfo { interface ContextInfo {
current?: number; current?: number;

View File

@ -4,7 +4,7 @@ import { Card } from '../ui/Card';
import { Input } from '../ui/Input'; import { Input } from '../ui/Input';
import { Select } from '../ui/Select'; import { Select } from '../ui/Select';
import { Button } from '../ui/Button'; import { Button } from '../ui/Button';
import { useToast } from '../../features/ui/hooks/useToast'; import { useToast } from '../../features/shared/hooks/useToast';
import { credentialsService } from '../../services/credentialsService'; import { credentialsService } from '../../services/credentialsService';
import OllamaModelDiscoveryModal from './OllamaModelDiscoveryModal'; import OllamaModelDiscoveryModal from './OllamaModelDiscoveryModal';
import OllamaModelSelectionModal from './OllamaModelSelectionModal'; import OllamaModelSelectionModal from './OllamaModelSelectionModal';

View File

@ -5,7 +5,7 @@
import { Globe, Loader2, Upload } from "lucide-react"; import { Globe, Loader2, Upload } from "lucide-react";
import { useId, useState } from "react"; import { useId, useState } from "react";
import { useToast } from "../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { Button, Input, Label } from "../../ui/primitives"; import { Button, Input, Label } from "../../ui/primitives";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../../ui/primitives/dialog"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../../ui/primitives/dialog";
import { cn } from "../../ui/primitives/styles"; import { cn } from "../../ui/primitives/styles";

View File

@ -6,7 +6,7 @@
import { formatDistanceToNowStrict } from "date-fns"; import { formatDistanceToNowStrict } from "date-fns";
import { Code, ExternalLink, Eye, FileText, MoreHorizontal, Trash2 } from "lucide-react"; import { Code, ExternalLink, Eye, FileText, MoreHorizontal, Trash2 } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { useToast } from "../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { Button } from "../../ui/primitives"; import { Button } from "../../ui/primitives";
import { import {
DropdownMenu, DropdownMenu,

View File

@ -23,14 +23,14 @@ vi.mock("../../services", () => ({
})); }));
// Mock the toast hook // Mock the toast hook
vi.mock("../../../ui/hooks/useToast", () => ({ vi.mock("@/features/shared/hooks/useToast", () => ({
useToast: () => ({ useToast: () => ({
showToast: vi.fn(), showToast: vi.fn(),
}), }),
})); }));
// Mock smart polling // Mock smart polling
vi.mock("../../../ui/hooks", () => ({ vi.mock("@/features/shared/hooks", () => ({
useSmartPolling: () => ({ useSmartPolling: () => ({
refetchInterval: 30000, refetchInterval: 30000,
isPaused: false, isPaused: false,

View File

@ -10,8 +10,8 @@ import { useActiveOperations } from "../../progress/hooks";
import { progressKeys } from "../../progress/hooks/useProgressQueries"; import { progressKeys } from "../../progress/hooks/useProgressQueries";
import type { ActiveOperation, ActiveOperationsResponse } from "../../progress/types"; import type { ActiveOperation, ActiveOperationsResponse } from "../../progress/types";
import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../shared/queryPatterns"; import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../shared/queryPatterns";
import { useSmartPolling } from "../../ui/hooks"; import { useSmartPolling } from "@/features/shared/hooks";
import { useToast } from "../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { knowledgeService } from "../services"; import { knowledgeService } from "../services";
import type { import type {
CrawlRequest, CrawlRequest,

View File

@ -6,7 +6,7 @@
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
import { CrawlingProgress } from "../../progress/components/CrawlingProgress"; import { CrawlingProgress } from "../../progress/components/CrawlingProgress";
import type { ActiveOperation } from "../../progress/types"; import type { ActiveOperation } from "../../progress/types";
import { useToast } from "../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { AddKnowledgeDialog } from "../components/AddKnowledgeDialog"; import { AddKnowledgeDialog } from "../components/AddKnowledgeDialog";
import { KnowledgeHeader } from "../components/KnowledgeHeader"; import { KnowledgeHeader } from "../components/KnowledgeHeader";
import { KnowledgeList } from "../components/KnowledgeList"; import { KnowledgeList } from "../components/KnowledgeList";

View File

@ -1,7 +1,7 @@
import { Copy, ExternalLink } from "lucide-react"; import { Copy, ExternalLink } from "lucide-react";
import type React from "react"; import type React from "react";
import { useState } from "react"; import { useState } from "react";
import { useToast } from "../../ui/hooks"; import { useToast } from "@/features/shared/hooks";
import { Button, cn, glassmorphism, Tabs, TabsContent, TabsList, TabsTrigger } from "../../ui/primitives"; import { Button, cn, glassmorphism, Tabs, TabsContent, TabsList, TabsTrigger } from "../../ui/primitives";
import type { McpServerConfig, McpServerStatus, SupportedIDE } from "../types"; import type { McpServerConfig, McpServerStatus, SupportedIDE } from "../types";
import { copyToClipboard } from "../../shared/utils/clipboard"; import { copyToClipboard } from "../../shared/utils/clipboard";

View File

@ -1,6 +1,6 @@
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { STALE_TIMES } from "../../shared/queryPatterns"; import { STALE_TIMES } from "../../shared/queryPatterns";
import { useSmartPolling } from "../../ui/hooks"; import { useSmartPolling } from "@/features/shared/hooks";
import { mcpApi } from "../services"; import { mcpApi } from "../services";
// Query keys factory // Query keys factory

View File

@ -7,7 +7,7 @@ import { type UseQueryResult, useQueries, useQuery, useQueryClient } from "@tans
import { useEffect, useMemo, useRef } from "react"; import { useEffect, useMemo, useRef } from "react";
import { APIServiceError } from "../../shared/errors"; import { APIServiceError } from "../../shared/errors";
import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../shared/queryPatterns"; import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../shared/queryPatterns";
import { useSmartPolling } from "../../ui/hooks"; import { useSmartPolling } from "../../shared/hooks";
import { progressService } from "../services"; import { progressService } from "../services";
import type { ActiveOperationsResponse, ProgressResponse, ProgressStatus } from "../types"; import type { ActiveOperationsResponse, ProgressResponse, ProgressStatus } from "../types";

View File

@ -1,6 +1,6 @@
import { Clipboard, Pin, Trash2 } from "lucide-react"; import { Clipboard, Pin, Trash2 } from "lucide-react";
import type React from "react"; import type React from "react";
import { useToast } from "../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { cn, glassmorphism } from "../../ui/primitives/styles"; import { cn, glassmorphism } from "../../ui/primitives/styles";
import { SimpleTooltip } from "../../ui/primitives/tooltip"; import { SimpleTooltip } from "../../ui/primitives/tooltip";

View File

@ -20,14 +20,14 @@ vi.mock("../../services", () => ({
})); }));
// Mock the toast hook // Mock the toast hook
vi.mock("../../../ui/hooks/useToast", () => ({ vi.mock("@/features/shared/hooks/useToast", () => ({
useToast: () => ({ useToast: () => ({
showToast: vi.fn(), showToast: vi.fn(),
}), }),
})); }));
// Mock smart polling // Mock smart polling
vi.mock("../../../ui/hooks", () => ({ vi.mock("@/features/shared/hooks", () => ({
useSmartPolling: () => ({ useSmartPolling: () => ({
refetchInterval: 5000, refetchInterval: 5000,
isPaused: false, isPaused: false,

View File

@ -6,8 +6,8 @@ import {
replaceOptimisticEntity, replaceOptimisticEntity,
} from "@/features/shared/optimistic"; } from "@/features/shared/optimistic";
import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../shared/queryPatterns"; import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../shared/queryPatterns";
import { useSmartPolling } from "../../ui/hooks"; import { useSmartPolling } from "@/features/shared/hooks";
import { useToast } from "../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { projectService } from "../services"; import { projectService } from "../services";
import type { CreateProjectRequest, Project, UpdateProjectRequest } from "../types"; import type { CreateProjectRequest, Project, UpdateProjectRequest } from "../types";

View File

@ -1,6 +1,6 @@
import { Clipboard, Edit, Trash2 } from "lucide-react"; import { Clipboard, Edit, Trash2 } from "lucide-react";
import type React from "react"; import type React from "react";
import { useToast } from "../../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { cn, glassmorphism } from "../../../ui/primitives/styles"; import { cn, glassmorphism } from "../../../ui/primitives/styles";
import { SimpleTooltip } from "../../../ui/primitives/tooltip"; import { SimpleTooltip } from "../../../ui/primitives/tooltip";

View File

@ -20,14 +20,14 @@ vi.mock("../../services", () => ({
const showToastMock = vi.fn(); const showToastMock = vi.fn();
// Mock the toast hook // Mock the toast hook
vi.mock("../../../../ui/hooks/useToast", () => ({ vi.mock("../../../../shared/hooks/useToast", () => ({
useToast: () => ({ useToast: () => ({
showToast: showToastMock, showToast: showToastMock,
}), }),
})); }));
// Mock smart polling // Mock smart polling
vi.mock("../../../../ui/hooks", () => ({ vi.mock("../../../../shared/hooks", () => ({
useSmartPolling: () => ({ useSmartPolling: () => ({
refetchInterval: 5000, refetchInterval: 5000,
isPaused: false, isPaused: false,

View File

@ -1,5 +1,5 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { useToast } from "../../../ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import { useProjectFeatures } from "../../hooks/useProjectQueries"; import { useProjectFeatures } from "../../hooks/useProjectQueries";
import type { Assignee, CreateTaskRequest, Task, UpdateTaskRequest, UseTaskEditorReturn } from "../types"; import type { Assignee, CreateTaskRequest, Task, UpdateTaskRequest, UseTaskEditorReturn } from "../types";
import { useCreateTask, useUpdateTask } from "./useTaskQueries"; import { useCreateTask, useUpdateTask } from "./useTaskQueries";

View File

@ -6,8 +6,8 @@ import {
type OptimisticEntity, type OptimisticEntity,
} from "@/features/shared/optimistic"; } from "@/features/shared/optimistic";
import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../../shared/queryPatterns"; import { DISABLED_QUERY_KEY, STALE_TIMES } from "../../../shared/queryPatterns";
import { useSmartPolling } from "../../../ui/hooks"; import { useSmartPolling } from "../../../shared/hooks";
import { useToast } from "../../../ui/hooks/useToast"; import { useToast } from "../../../shared/hooks/useToast";
import { taskService } from "../services"; import { taskService } from "../services";
import type { CreateTaskRequest, Task, UpdateTaskRequest } from "../types"; import type { CreateTaskRequest, Task, UpdateTaskRequest } from "../types";

View File

@ -6,7 +6,7 @@ import { AnimatePresence, motion } from "framer-motion";
import { CheckCircle, Copy, Database, ExternalLink, X } from "lucide-react"; import { CheckCircle, Copy, Database, ExternalLink, X } from "lucide-react";
import React from "react"; import React from "react";
import { copyToClipboard } from "@/features/shared/utils/clipboard"; import { copyToClipboard } from "@/features/shared/utils/clipboard";
import { useToast } from "@/features/ui/hooks/useToast"; import { useToast } from "@/features/shared/hooks/useToast";
import type { PendingMigration } from "../types"; import type { PendingMigration } from "../types";
interface PendingMigrationsModalProps { interface PendingMigrationsModalProps {

View File

@ -4,7 +4,7 @@
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { STALE_TIMES } from "@/features/shared/queryPatterns"; import { STALE_TIMES } from "@/features/shared/queryPatterns";
import { useSmartPolling } from "@/features/ui/hooks/useSmartPolling"; import { useSmartPolling } from "@/features/shared/hooks/useSmartPolling";
import { migrationService } from "../services/migrationService"; import { migrationService } from "../services/migrationService";
import type { MigrationHistoryResponse, MigrationStatusResponse, PendingMigration } from "../types"; import type { MigrationHistoryResponse, MigrationStatusResponse, PendingMigration } from "../types";

View File

@ -4,7 +4,7 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { STALE_TIMES } from "@/features/shared/queryPatterns"; import { STALE_TIMES } from "@/features/shared/queryPatterns";
import { useSmartPolling } from "@/features/ui/hooks/useSmartPolling"; import { useSmartPolling } from "@/features/shared/hooks/useSmartPolling";
import { versionService } from "../services/versionService"; import { versionService } from "../services/versionService";
import type { VersionCheckResponse } from "../types"; import type { VersionCheckResponse } from "../types";

View File

@ -1,3 +1,3 @@
export * from "./useSmartPolling"; export * from "./useSmartPolling";
export * from "./useThemeAware"; export * from "./useThemeAware";
export * from "./useToast"; export * from "./useToast";

View File

@ -1,6 +1,6 @@
import { AlertCircle, CheckCircle, Info, XCircle } from "lucide-react"; import { AlertCircle, CheckCircle, Info, XCircle } from "lucide-react";
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"; import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
import { createOptimisticId } from "../../shared/optimistic"; import { createOptimisticId } from "../optimistic";
// Toast types // Toast types
interface Toast { interface Toast {

View File

@ -1,5 +1,5 @@
import type React from "react"; import type React from "react";
import { createToastContext, getToastIcon, ToastContext } from "../hooks/useToast"; import { createToastContext, getToastIcon, ToastContext } from "../../shared/hooks/useToast";
import { import {
ToastProvider as RadixToastProvider, ToastProvider as RadixToastProvider,
Toast, Toast,

View File

@ -14,7 +14,7 @@ import {
Database, Database,
} from "lucide-react"; } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion"; import { motion, AnimatePresence } from "framer-motion";
import { useToast } from "../features/ui/hooks/useToast"; import { useToast } from "../features/shared/hooks/useToast";
import { useSettings } from "../contexts/SettingsContext"; import { useSettings } from "../contexts/SettingsContext";
import { useStaggeredEntrance } from "../hooks/useStaggeredEntrance"; import { useStaggeredEntrance } from "../hooks/useStaggeredEntrance";
import { FeaturesSection } from "../components/settings/FeaturesSection"; import { FeaturesSection } from "../components/settings/FeaturesSection";